Merge branch 'hotfixes-20111024/josef/for-chris' into btrfs-next-stable
This commit is contained in:
commit
a81d3b1ba2
|
@ -59,22 +59,19 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
|
||||||
if (!value)
|
if (!value)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
size = __btrfs_getxattr(inode, name, value, size);
|
size = __btrfs_getxattr(inode, name, value, size);
|
||||||
|
}
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
acl = posix_acl_from_xattr(value, size);
|
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) {
|
} else if (size == -ENOENT || size == -ENODATA || size == 0) {
|
||||||
/* FIXME, who returns -ENOENT? I think nobody */
|
/* FIXME, who returns -ENOENT? I think nobody */
|
||||||
acl = NULL;
|
acl = NULL;
|
||||||
set_cached_acl(inode, type, acl);
|
|
||||||
} else {
|
} else {
|
||||||
acl = ERR_PTR(-EIO);
|
acl = ERR_PTR(-EIO);
|
||||||
}
|
}
|
||||||
|
kfree(value);
|
||||||
|
|
||||||
|
if (!IS_ERR(acl))
|
||||||
|
set_cached_acl(inode, type, acl);
|
||||||
|
|
||||||
return 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);
|
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];
|
parent = path->nodes[level + 1];
|
||||||
pslot = path->slots[level + 1];
|
pslot = path->slots[level + 1];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* deal with the case where there is only one pointer in the root
|
* 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];
|
mid = path->nodes[level];
|
||||||
WARN_ON(btrfs_header_generation(mid) != trans->transid);
|
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];
|
parent = path->nodes[level + 1];
|
||||||
pslot = path->slots[level + 1];
|
pslot = path->slots[level + 1];
|
||||||
|
}
|
||||||
|
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -4954,6 +4954,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
|
||||||
bool failed_cluster_refill = false;
|
bool failed_cluster_refill = false;
|
||||||
bool failed_alloc = false;
|
bool failed_alloc = false;
|
||||||
bool use_cluster = true;
|
bool use_cluster = true;
|
||||||
|
bool have_caching_bg = false;
|
||||||
u64 ideal_cache_percent = 0;
|
u64 ideal_cache_percent = 0;
|
||||||
u64 ideal_cache_offset = 0;
|
u64 ideal_cache_offset = 0;
|
||||||
|
|
||||||
|
@ -5036,6 +5037,7 @@ ideal_cache:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
search:
|
search:
|
||||||
|
have_caching_bg = false;
|
||||||
down_read(&space_info->groups_sem);
|
down_read(&space_info->groups_sem);
|
||||||
list_for_each_entry(block_group, &space_info->block_groups[index],
|
list_for_each_entry(block_group, &space_info->block_groups[index],
|
||||||
list) {
|
list) {
|
||||||
|
@ -5244,6 +5246,8 @@ refill_cluster:
|
||||||
failed_alloc = true;
|
failed_alloc = true;
|
||||||
goto have_block_group;
|
goto have_block_group;
|
||||||
} else if (!offset) {
|
} else if (!offset) {
|
||||||
|
if (!cached)
|
||||||
|
have_caching_bg = true;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
checks:
|
checks:
|
||||||
|
@ -5294,6 +5298,9 @@ loop:
|
||||||
}
|
}
|
||||||
up_read(&space_info->groups_sem);
|
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)
|
if (!ins->objectid && ++index < BTRFS_NR_RAID_TYPES)
|
||||||
goto search;
|
goto search;
|
||||||
|
|
||||||
|
@ -7312,7 +7319,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
|
||||||
goto out;
|
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)) {
|
if (!IS_ERR(inode)) {
|
||||||
ret = btrfs_orphan_add(trans, inode);
|
ret = btrfs_orphan_add(trans, inode);
|
||||||
BUG_ON(ret);
|
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)
|
struct extent_state **cached_state, gfp_t mask)
|
||||||
{
|
{
|
||||||
return set_extent_bit(tree, start, end,
|
return set_extent_bit(tree, start, end,
|
||||||
EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE,
|
EXTENT_DELALLOC | EXTENT_UPTODATE,
|
||||||
0, NULL, cached_state, mask);
|
0, NULL, cached_state, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -393,7 +393,10 @@ again:
|
||||||
(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS))) {
|
(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS))) {
|
||||||
WARN_ON(pages);
|
WARN_ON(pages);
|
||||||
pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
|
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)
|
if (BTRFS_I(inode)->force_compress)
|
||||||
compress_type = BTRFS_I(inode)->force_compress;
|
compress_type = BTRFS_I(inode)->force_compress;
|
||||||
|
@ -424,6 +427,7 @@ again:
|
||||||
will_compress = 1;
|
will_compress = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cont:
|
||||||
if (start == 0) {
|
if (start == 0) {
|
||||||
trans = btrfs_join_transaction(root);
|
trans = btrfs_join_transaction(root);
|
||||||
BUG_ON(IS_ERR(trans));
|
BUG_ON(IS_ERR(trans));
|
||||||
|
@ -5773,8 +5777,7 @@ again:
|
||||||
if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) {
|
if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) {
|
||||||
ret = btrfs_ordered_update_i_size(inode, 0, ordered);
|
ret = btrfs_ordered_update_i_size(inode, 0, ordered);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = btrfs_update_inode(trans, root, inode);
|
err = btrfs_update_inode(trans, root, inode);
|
||||||
err = ret;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,7 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
|
||||||
struct fstrim_range range;
|
struct fstrim_range range;
|
||||||
u64 minlen = ULLONG_MAX;
|
u64 minlen = ULLONG_MAX;
|
||||||
u64 num_devices = 0;
|
u64 num_devices = 0;
|
||||||
|
u64 total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!capable(CAP_SYS_ADMIN))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
|
@ -300,12 +301,15 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (!num_devices)
|
if (!num_devices)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (copy_from_user(&range, arg, sizeof(range)))
|
if (copy_from_user(&range, arg, sizeof(range)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
if (range.start > total_bytes)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
range.len = min(range.len, total_bytes - range.start);
|
||||||
range.minlen = max(range.minlen, minlen);
|
range.minlen = max(range.minlen, minlen);
|
||||||
ret = btrfs_trim_fs(root, &range);
|
ret = btrfs_trim_fs(root, &range);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -765,7 +769,7 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len,
|
||||||
int ret = 1;
|
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
|
* defragging it
|
||||||
*/
|
*/
|
||||||
if (start < *defrag_end)
|
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.
|
* extent will force at least part of that big extent to be defragged.
|
||||||
*/
|
*/
|
||||||
if (ret) {
|
if (ret) {
|
||||||
*last_len += len;
|
|
||||||
*defrag_end = extent_map_end(em);
|
*defrag_end = extent_map_end(em);
|
||||||
} else {
|
} else {
|
||||||
*last_len = 0;
|
*last_len = 0;
|
||||||
|
@ -978,18 +981,20 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
|
||||||
struct btrfs_super_block *disk_super;
|
struct btrfs_super_block *disk_super;
|
||||||
struct file_ra_state *ra = NULL;
|
struct file_ra_state *ra = NULL;
|
||||||
unsigned long last_index;
|
unsigned long last_index;
|
||||||
|
u64 isize = i_size_read(inode);
|
||||||
u64 features;
|
u64 features;
|
||||||
u64 last_len = 0;
|
u64 last_len = 0;
|
||||||
u64 skip = 0;
|
u64 skip = 0;
|
||||||
u64 defrag_end = 0;
|
u64 defrag_end = 0;
|
||||||
u64 newer_off = range->start;
|
u64 newer_off = range->start;
|
||||||
int newer_left = 0;
|
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
unsigned long ra_index = 0;
|
||||||
int ret;
|
int ret;
|
||||||
int defrag_count = 0;
|
int defrag_count = 0;
|
||||||
int compress_type = BTRFS_COMPRESS_ZLIB;
|
int compress_type = BTRFS_COMPRESS_ZLIB;
|
||||||
int extent_thresh = range->extent_thresh;
|
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);
|
u64 new_align = ~((u64)128 * 1024 - 1);
|
||||||
struct page **pages = NULL;
|
struct page **pages = NULL;
|
||||||
|
|
||||||
|
@ -1003,7 +1008,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
|
||||||
compress_type = range->compress_type;
|
compress_type = range->compress_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inode->i_size == 0)
|
if (isize == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1019,7 +1024,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
|
||||||
ra = &file->f_ra;
|
ra = &file->f_ra;
|
||||||
}
|
}
|
||||||
|
|
||||||
pages = kmalloc(sizeof(struct page *) * newer_cluster,
|
pages = kmalloc(sizeof(struct page *) * max_cluster,
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
if (!pages) {
|
if (!pages) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -1028,10 +1033,10 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
|
||||||
|
|
||||||
/* find the last page to defrag */
|
/* find the last page to defrag */
|
||||||
if (range->start + range->len > range->start) {
|
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;
|
range->start + range->len - 1) >> PAGE_CACHE_SHIFT;
|
||||||
} else {
|
} else {
|
||||||
last_index = (inode->i_size - 1) >> PAGE_CACHE_SHIFT;
|
last_index = (isize - 1) >> PAGE_CACHE_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newer_than) {
|
if (newer_than) {
|
||||||
|
@ -1044,14 +1049,13 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
|
||||||
* the extents in the file evenly spaced
|
* the extents in the file evenly spaced
|
||||||
*/
|
*/
|
||||||
i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
|
i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
|
||||||
newer_left = newer_cluster;
|
|
||||||
} else
|
} else
|
||||||
goto out_ra;
|
goto out_ra;
|
||||||
} else {
|
} else {
|
||||||
i = range->start >> PAGE_CACHE_SHIFT;
|
i = range->start >> PAGE_CACHE_SHIFT;
|
||||||
}
|
}
|
||||||
if (!max_to_defrag)
|
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
|
* 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);
|
i = max(i + 1, next);
|
||||||
continue;
|
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)
|
if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)
|
||||||
BTRFS_I(inode)->force_compress = compress_type;
|
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)
|
if (ret < 0)
|
||||||
goto out_ra;
|
goto out_ra;
|
||||||
|
|
||||||
defrag_count += ret;
|
defrag_count += ret;
|
||||||
balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret);
|
balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret);
|
||||||
i += ret;
|
|
||||||
|
|
||||||
if (newer_than) {
|
if (newer_than) {
|
||||||
if (newer_off == (u64)-1)
|
if (newer_off == (u64)-1)
|
||||||
|
@ -1111,12 +1128,17 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
range->start = newer_off;
|
range->start = newer_off;
|
||||||
i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
|
i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
|
||||||
newer_left = newer_cluster;
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (ret > 0) {
|
||||||
|
i += ret;
|
||||||
|
last_len += ret << PAGE_CACHE_SHIFT;
|
||||||
} else {
|
} else {
|
||||||
i++;
|
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);
|
btrfs_set_super_incompat_flags(disk_super, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file)
|
ret = defrag_count;
|
||||||
kfree(ra);
|
|
||||||
return defrag_count;
|
|
||||||
|
|
||||||
out_ra:
|
out_ra:
|
||||||
if (!file)
|
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)
|
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u32 type;
|
u32 type, nr;
|
||||||
u32 nr = btrfs_header_nritems(l);
|
|
||||||
struct btrfs_item *item;
|
struct btrfs_item *item;
|
||||||
struct btrfs_root_item *ri;
|
struct btrfs_root_item *ri;
|
||||||
struct btrfs_dir_item *di;
|
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 key;
|
||||||
struct btrfs_key found_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",
|
printk(KERN_INFO "leaf %llu total ptrs %d free space %d\n",
|
||||||
(unsigned long long)btrfs_header_bytenr(l), nr,
|
(unsigned long long)btrfs_header_bytenr(l), nr,
|
||||||
btrfs_leaf_free_space(root, l));
|
btrfs_leaf_free_space(root, l));
|
||||||
|
|
|
@ -3322,8 +3322,11 @@ static int find_data_references(struct reloc_control *rc,
|
||||||
}
|
}
|
||||||
|
|
||||||
key.objectid = ref_objectid;
|
key.objectid = ref_objectid;
|
||||||
key.offset = ref_offset;
|
|
||||||
key.type = BTRFS_EXTENT_DATA_KEY;
|
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->search_commit_root = 1;
|
||||||
path->skip_locking = 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)
|
u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices)
|
||||||
{
|
{
|
||||||
substring_t args[MAX_OPT_ARGS];
|
substring_t args[MAX_OPT_ARGS];
|
||||||
char *opts, *orig, *p;
|
char *device_name, *opts, *orig, *p;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int intarg;
|
int intarg;
|
||||||
|
|
||||||
|
@ -470,8 +470,14 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Opt_device:
|
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);
|
flags, holder, fs_devices);
|
||||||
|
kfree(device_name);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
break;
|
||||||
|
@ -734,6 +740,16 @@ static int btrfs_set_super(struct super_block *s, void *data)
|
||||||
return set_anon_super(s, 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
|
* 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
|
* 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)
|
if (error)
|
||||||
return ERR_PTR(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 */
|
/* Get a ref to the sb and the dentry we found and return it */
|
||||||
s = path.mnt->mnt_sb;
|
s = path.mnt->mnt_sb;
|
||||||
atomic_inc(&s->s_active);
|
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;
|
s->s_flags = flags | MS_NOSEC;
|
||||||
strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
|
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,
|
error = btrfs_fill_super(s, fs_devices, data,
|
||||||
flags & MS_SILENT ? 1 : 0);
|
flags & MS_SILENT ? 1 : 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -940,7 +966,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
btrfs_sb(s)->fs_info->bdev_holder = fs_type;
|
|
||||||
s->s_flags |= MS_ACTIVE;
|
s->s_flags |= MS_ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -597,10 +597,8 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
|
||||||
set_blocksize(bdev, 4096);
|
set_blocksize(bdev, 4096);
|
||||||
|
|
||||||
bh = btrfs_read_dev_super(bdev);
|
bh = btrfs_read_dev_super(bdev);
|
||||||
if (!bh) {
|
if (!bh)
|
||||||
ret = -EINVAL;
|
|
||||||
goto error_close;
|
goto error_close;
|
||||||
}
|
|
||||||
|
|
||||||
disk_super = (struct btrfs_super_block *)bh->b_data;
|
disk_super = (struct btrfs_super_block *)bh->b_data;
|
||||||
devid = btrfs_stack_device_id(&disk_super->dev_item);
|
devid = btrfs_stack_device_id(&disk_super->dev_item);
|
||||||
|
@ -655,7 +653,7 @@ error:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fs_devices->open_devices == 0) {
|
if (fs_devices->open_devices == 0) {
|
||||||
ret = -EIO;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fs_devices->seeding = seeding;
|
fs_devices->seeding = seeding;
|
||||||
|
|
Loading…
Reference in New Issue