提交 a81d3b1b 编写于 作者: D David Sterba

Merge branch 'hotfixes-20111024/josef/for-chris' into btrfs-next-stable

......@@ -59,22 +59,19 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
if (!value)
return ERR_PTR(-ENOMEM);
size = __btrfs_getxattr(inode, name, value, size);
}
if (size > 0) {
acl = posix_acl_from_xattr(value, size);
if (IS_ERR(acl)) {
kfree(value);
return acl;
}
set_cached_acl(inode, type, acl);
}
kfree(value);
} else if (size == -ENOENT || size == -ENODATA || size == 0) {
/* FIXME, who returns -ENOENT? I think nobody */
acl = NULL;
set_cached_acl(inode, type, acl);
} else {
acl = ERR_PTR(-EIO);
}
kfree(value);
if (!IS_ERR(acl))
set_cached_acl(inode, type, acl);
return acl;
}
......
......@@ -902,9 +902,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
orig_ptr = btrfs_node_blockptr(mid, orig_slot);
if (level < BTRFS_MAX_LEVEL - 1)
if (level < BTRFS_MAX_LEVEL - 1) {
parent = path->nodes[level + 1];
pslot = path->slots[level + 1];
}
/*
* deal with the case where there is only one pointer in the root
......@@ -1107,9 +1108,10 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
mid = path->nodes[level];
WARN_ON(btrfs_header_generation(mid) != trans->transid);
if (level < BTRFS_MAX_LEVEL - 1)
if (level < BTRFS_MAX_LEVEL - 1) {
parent = path->nodes[level + 1];
pslot = path->slots[level + 1];
}
if (!parent)
return 1;
......
......@@ -4954,6 +4954,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
bool failed_cluster_refill = false;
bool failed_alloc = false;
bool use_cluster = true;
bool have_caching_bg = false;
u64 ideal_cache_percent = 0;
u64 ideal_cache_offset = 0;
......@@ -5036,6 +5037,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
}
}
search:
have_caching_bg = false;
down_read(&space_info->groups_sem);
list_for_each_entry(block_group, &space_info->block_groups[index],
list) {
......@@ -5244,6 +5246,8 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
failed_alloc = true;
goto have_block_group;
} else if (!offset) {
if (!cached)
have_caching_bg = true;
goto loop;
}
checks:
......@@ -5294,6 +5298,9 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
}
up_read(&space_info->groups_sem);
if (!ins->objectid && loop >= LOOP_CACHING_WAIT && have_caching_bg)
goto search;
if (!ins->objectid && ++index < BTRFS_NR_RAID_TYPES)
goto search;
......@@ -7312,7 +7319,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
goto out;
}
inode = lookup_free_space_inode(root, block_group, path);
inode = lookup_free_space_inode(tree_root, block_group, path);
if (!IS_ERR(inode)) {
ret = btrfs_orphan_add(trans, inode);
BUG_ON(ret);
......
......@@ -1107,7 +1107,7 @@ int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
struct extent_state **cached_state, gfp_t mask)
{
return set_extent_bit(tree, start, end,
EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE,
EXTENT_DELALLOC | EXTENT_UPTODATE,
0, NULL, cached_state, mask);
}
......
......@@ -393,7 +393,10 @@ static noinline int compress_file_range(struct inode *inode,
(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS))) {
WARN_ON(pages);
pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
BUG_ON(!pages);
if (!pages) {
/* just bail out to the uncompressed code */
goto cont;
}
if (BTRFS_I(inode)->force_compress)
compress_type = BTRFS_I(inode)->force_compress;
......@@ -424,6 +427,7 @@ static noinline int compress_file_range(struct inode *inode,
will_compress = 1;
}
}
cont:
if (start == 0) {
trans = btrfs_join_transaction(root);
BUG_ON(IS_ERR(trans));
......@@ -5773,8 +5777,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err)
if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) {
ret = btrfs_ordered_update_i_size(inode, 0, ordered);
if (!ret)
ret = btrfs_update_inode(trans, root, inode);
err = ret;
err = btrfs_update_inode(trans, root, inode);
goto out;
}
......
......@@ -282,6 +282,7 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
struct fstrim_range range;
u64 minlen = ULLONG_MAX;
u64 num_devices = 0;
u64 total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
int ret;
if (!capable(CAP_SYS_ADMIN))
......@@ -300,12 +301,15 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
}
}
rcu_read_unlock();
if (!num_devices)
return -EOPNOTSUPP;
if (copy_from_user(&range, arg, sizeof(range)))
return -EFAULT;
if (range.start > total_bytes)
return -EINVAL;
range.len = min(range.len, total_bytes - range.start);
range.minlen = max(range.minlen, minlen);
ret = btrfs_trim_fs(root, &range);
if (ret < 0)
......@@ -765,7 +769,7 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len,
int ret = 1;
/*
* make sure that once we start defragging and extent, we keep on
* make sure that once we start defragging an extent, we keep on
* defragging it
*/
if (start < *defrag_end)
......@@ -810,7 +814,6 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len,
* extent will force at least part of that big extent to be defragged.
*/
if (ret) {
*last_len += len;
*defrag_end = extent_map_end(em);
} else {
*last_len = 0;
......@@ -978,18 +981,20 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
struct btrfs_super_block *disk_super;
struct file_ra_state *ra = NULL;
unsigned long last_index;
u64 isize = i_size_read(inode);
u64 features;
u64 last_len = 0;
u64 skip = 0;
u64 defrag_end = 0;
u64 newer_off = range->start;
int newer_left = 0;
unsigned long i;
unsigned long ra_index = 0;
int ret;
int defrag_count = 0;
int compress_type = BTRFS_COMPRESS_ZLIB;
int extent_thresh = range->extent_thresh;
int newer_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT;
int max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT;
int cluster = max_cluster;
u64 new_align = ~((u64)128 * 1024 - 1);
struct page **pages = NULL;
......@@ -1003,7 +1008,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
compress_type = range->compress_type;
}
if (inode->i_size == 0)
if (isize == 0)
return 0;
/*
......@@ -1019,7 +1024,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
ra = &file->f_ra;
}
pages = kmalloc(sizeof(struct page *) * newer_cluster,
pages = kmalloc(sizeof(struct page *) * max_cluster,
GFP_NOFS);
if (!pages) {
ret = -ENOMEM;
......@@ -1028,10 +1033,10 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
/* find the last page to defrag */
if (range->start + range->len > range->start) {
last_index = min_t(u64, inode->i_size - 1,
last_index = min_t(u64, isize - 1,
range->start + range->len - 1) >> PAGE_CACHE_SHIFT;
} else {
last_index = (inode->i_size - 1) >> PAGE_CACHE_SHIFT;
last_index = (isize - 1) >> PAGE_CACHE_SHIFT;
}
if (newer_than) {
......@@ -1044,14 +1049,13 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
* the extents in the file evenly spaced
*/
i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
newer_left = newer_cluster;
} else
goto out_ra;
} else {
i = range->start >> PAGE_CACHE_SHIFT;
}
if (!max_to_defrag)
max_to_defrag = last_index - 1;
max_to_defrag = last_index;
/*
* make writeback starts from i, so the defrag range can be
......@@ -1085,18 +1089,31 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
i = max(i + 1, next);
continue;
}
if (!newer_than) {
cluster = (PAGE_CACHE_ALIGN(defrag_end) >>
PAGE_CACHE_SHIFT) - i;
cluster = min(cluster, max_cluster);
} else {
cluster = max_cluster;
}
if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)
BTRFS_I(inode)->force_compress = compress_type;
btrfs_force_ra(inode->i_mapping, ra, file, i, newer_cluster);
if (i + cluster > ra_index) {
ra_index = max(i, ra_index);
btrfs_force_ra(inode->i_mapping, ra, file, ra_index,
cluster);
ra_index += max_cluster;
}
ret = cluster_pages_for_defrag(inode, pages, i, newer_cluster);
ret = cluster_pages_for_defrag(inode, pages, i, cluster);
if (ret < 0)
goto out_ra;
defrag_count += ret;
balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret);
i += ret;
if (newer_than) {
if (newer_off == (u64)-1)
......@@ -1111,12 +1128,17 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
if (!ret) {
range->start = newer_off;
i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
newer_left = newer_cluster;
} else {
break;
}
} else {
if (ret > 0) {
i += ret;
last_len += ret << PAGE_CACHE_SHIFT;
} else {
i++;
last_len = 0;
}
}
}
......@@ -1149,9 +1171,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
btrfs_set_super_incompat_flags(disk_super, features);
}
if (!file)
kfree(ra);
return defrag_count;
ret = defrag_count;
out_ra:
if (!file)
......
......@@ -158,8 +158,7 @@ static void print_extent_ref_v0(struct extent_buffer *eb, int slot)
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
{
int i;
u32 type;
u32 nr = btrfs_header_nritems(l);
u32 type, nr;
struct btrfs_item *item;
struct btrfs_root_item *ri;
struct btrfs_dir_item *di;
......@@ -172,6 +171,11 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
struct btrfs_key key;
struct btrfs_key found_key;
if (!l)
return;
nr = btrfs_header_nritems(l);
printk(KERN_INFO "leaf %llu total ptrs %d free space %d\n",
(unsigned long long)btrfs_header_bytenr(l), nr,
btrfs_leaf_free_space(root, l));
......
......@@ -3322,8 +3322,11 @@ static int find_data_references(struct reloc_control *rc,
}
key.objectid = ref_objectid;
key.offset = ref_offset;
key.type = BTRFS_EXTENT_DATA_KEY;
if (ref_offset > ((u64)-1 << 32))
key.offset = 0;
else
key.offset = ref_offset;
path->search_commit_root = 1;
path->skip_locking = 1;
......
......@@ -419,7 +419,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices)
{
substring_t args[MAX_OPT_ARGS];
char *opts, *orig, *p;
char *device_name, *opts, *orig, *p;
int error = 0;
int intarg;
......@@ -470,8 +470,14 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
}
break;
case Opt_device:
error = btrfs_scan_one_device(match_strdup(&args[0]),
device_name = match_strdup(&args[0]);
if (!device_name) {
error = -ENOMEM;
goto out;
}
error = btrfs_scan_one_device(device_name,
flags, holder, fs_devices);
kfree(device_name);
if (error)
goto out;
break;
......@@ -734,6 +740,16 @@ static int btrfs_set_super(struct super_block *s, void *data)
return set_anon_super(s, data);
}
/*
* subvolumes are identified by ino 256
*/
static inline int is_subvolume_inode(struct inode *inode)
{
if (inode && inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
return 1;
return 0;
}
/*
* This will strip out the subvol=%s argument for an argument string and add
* subvolid=0 to make sure we get the actual tree root for path walking to the
......@@ -837,6 +853,15 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
if (error)
return ERR_PTR(error);
if (!is_subvolume_inode(path.dentry->d_inode)) {
path_put(&path);
mntput(mnt);
error = -EINVAL;
printk(KERN_ERR "btrfs: '%s' is not a valid subvolume\n",
subvol_name);
return ERR_PTR(-EINVAL);
}
/* Get a ref to the sb and the dentry we found and return it */
s = path.mnt->mnt_sb;
atomic_inc(&s->s_active);
......@@ -933,6 +958,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
s->s_flags = flags | MS_NOSEC;
strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
btrfs_sb(s)->fs_info->bdev_holder = fs_type;
error = btrfs_fill_super(s, fs_devices, data,
flags & MS_SILENT ? 1 : 0);
if (error) {
......@@ -940,7 +966,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
return ERR_PTR(error);
}
btrfs_sb(s)->fs_info->bdev_holder = fs_type;
s->s_flags |= MS_ACTIVE;
}
......
......@@ -597,10 +597,8 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
set_blocksize(bdev, 4096);
bh = btrfs_read_dev_super(bdev);
if (!bh) {
ret = -EINVAL;
if (!bh)
goto error_close;
}
disk_super = (struct btrfs_super_block *)bh->b_data;
devid = btrfs_stack_device_id(&disk_super->dev_item);
......@@ -655,7 +653,7 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
continue;
}
if (fs_devices->open_devices == 0) {
ret = -EIO;
ret = -EINVAL;
goto out;
}
fs_devices->seeding = seeding;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册