Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "This is a small collection of fixes. It was rebased this morning, but I was just fixing signed-off-by tags with the wrong email" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: fix access_ok() check in btrfs_ioctl_send() Btrfs: make sure we cleanup all reloc roots if error happens Btrfs: skip building backref tree for uuid and quota tree when doing balance relocation Btrfs: fix an oops when doing balance relocation Btrfs: don't miss skinny extent items on delayed ref head contention btrfs: call mnt_drop_write after interrupted subvol deletion Btrfs: don't clear the default compression type
This commit is contained in:
commit
e09f67f147
5 changed files with 73 additions and 42 deletions
|
@ -767,20 +767,19 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
|
|||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
if (metadata) {
|
||||
key.objectid = bytenr;
|
||||
key.type = BTRFS_METADATA_ITEM_KEY;
|
||||
key.offset = offset;
|
||||
} else {
|
||||
key.objectid = bytenr;
|
||||
key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
key.offset = offset;
|
||||
}
|
||||
|
||||
if (!trans) {
|
||||
path->skip_locking = 1;
|
||||
path->search_commit_root = 1;
|
||||
}
|
||||
|
||||
search_again:
|
||||
key.objectid = bytenr;
|
||||
key.offset = offset;
|
||||
if (metadata)
|
||||
key.type = BTRFS_METADATA_ITEM_KEY;
|
||||
else
|
||||
key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
|
||||
again:
|
||||
ret = btrfs_search_slot(trans, root->fs_info->extent_root,
|
||||
&key, path, 0, 0);
|
||||
|
@ -788,7 +787,6 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
|
|||
goto out_free;
|
||||
|
||||
if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) {
|
||||
metadata = 0;
|
||||
if (path->slots[0]) {
|
||||
path->slots[0]--;
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &key,
|
||||
|
@ -855,7 +853,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
|
|||
mutex_lock(&head->mutex);
|
||||
mutex_unlock(&head->mutex);
|
||||
btrfs_put_delayed_ref(&head->node);
|
||||
goto again;
|
||||
goto search_again;
|
||||
}
|
||||
if (head->extent_op && head->extent_op->update_flags)
|
||||
extent_flags |= head->extent_op->flags_to_set;
|
||||
|
|
|
@ -2121,7 +2121,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
|
|||
|
||||
err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
|
||||
if (err == -EINTR)
|
||||
goto out;
|
||||
goto out_drop_write;
|
||||
dentry = lookup_one_len(vol_args->name, parent, namelen);
|
||||
if (IS_ERR(dentry)) {
|
||||
err = PTR_ERR(dentry);
|
||||
|
@ -2284,6 +2284,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
|
|||
dput(dentry);
|
||||
out_unlock_dir:
|
||||
mutex_unlock(&dir->i_mutex);
|
||||
out_drop_write:
|
||||
mnt_drop_write_file(file);
|
||||
out:
|
||||
kfree(vol_args);
|
||||
|
|
|
@ -571,7 +571,9 @@ static int is_cowonly_root(u64 root_objectid)
|
|||
root_objectid == BTRFS_CHUNK_TREE_OBJECTID ||
|
||||
root_objectid == BTRFS_DEV_TREE_OBJECTID ||
|
||||
root_objectid == BTRFS_TREE_LOG_OBJECTID ||
|
||||
root_objectid == BTRFS_CSUM_TREE_OBJECTID)
|
||||
root_objectid == BTRFS_CSUM_TREE_OBJECTID ||
|
||||
root_objectid == BTRFS_UUID_TREE_OBJECTID ||
|
||||
root_objectid == BTRFS_QUOTA_TREE_OBJECTID)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1264,10 +1266,10 @@ static int __must_check __add_reloc_root(struct btrfs_root *root)
|
|||
}
|
||||
|
||||
/*
|
||||
* helper to update/delete the 'address of tree root -> reloc tree'
|
||||
* helper to delete the 'address of tree root -> reloc tree'
|
||||
* mapping
|
||||
*/
|
||||
static int __update_reloc_root(struct btrfs_root *root, int del)
|
||||
static void __del_reloc_root(struct btrfs_root *root)
|
||||
{
|
||||
struct rb_node *rb_node;
|
||||
struct mapping_node *node = NULL;
|
||||
|
@ -1275,7 +1277,36 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
|
|||
|
||||
spin_lock(&rc->reloc_root_tree.lock);
|
||||
rb_node = tree_search(&rc->reloc_root_tree.rb_root,
|
||||
root->commit_root->start);
|
||||
root->node->start);
|
||||
if (rb_node) {
|
||||
node = rb_entry(rb_node, struct mapping_node, rb_node);
|
||||
rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
|
||||
}
|
||||
spin_unlock(&rc->reloc_root_tree.lock);
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
BUG_ON((struct btrfs_root *)node->data != root);
|
||||
|
||||
spin_lock(&root->fs_info->trans_lock);
|
||||
list_del_init(&root->root_list);
|
||||
spin_unlock(&root->fs_info->trans_lock);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* helper to update the 'address of tree root -> reloc tree'
|
||||
* mapping
|
||||
*/
|
||||
static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr)
|
||||
{
|
||||
struct rb_node *rb_node;
|
||||
struct mapping_node *node = NULL;
|
||||
struct reloc_control *rc = root->fs_info->reloc_ctl;
|
||||
|
||||
spin_lock(&rc->reloc_root_tree.lock);
|
||||
rb_node = tree_search(&rc->reloc_root_tree.rb_root,
|
||||
root->node->start);
|
||||
if (rb_node) {
|
||||
node = rb_entry(rb_node, struct mapping_node, rb_node);
|
||||
rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
|
||||
|
@ -1286,20 +1317,13 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
|
|||
return 0;
|
||||
BUG_ON((struct btrfs_root *)node->data != root);
|
||||
|
||||
if (!del) {
|
||||
spin_lock(&rc->reloc_root_tree.lock);
|
||||
node->bytenr = root->node->start;
|
||||
rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
|
||||
node->bytenr, &node->rb_node);
|
||||
spin_unlock(&rc->reloc_root_tree.lock);
|
||||
if (rb_node)
|
||||
backref_tree_panic(rb_node, -EEXIST, node->bytenr);
|
||||
} else {
|
||||
spin_lock(&root->fs_info->trans_lock);
|
||||
list_del_init(&root->root_list);
|
||||
spin_unlock(&root->fs_info->trans_lock);
|
||||
kfree(node);
|
||||
}
|
||||
spin_lock(&rc->reloc_root_tree.lock);
|
||||
node->bytenr = new_bytenr;
|
||||
rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
|
||||
node->bytenr, &node->rb_node);
|
||||
spin_unlock(&rc->reloc_root_tree.lock);
|
||||
if (rb_node)
|
||||
backref_tree_panic(rb_node, -EEXIST, node->bytenr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1420,7 +1444,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
|
|||
{
|
||||
struct btrfs_root *reloc_root;
|
||||
struct btrfs_root_item *root_item;
|
||||
int del = 0;
|
||||
int ret;
|
||||
|
||||
if (!root->reloc_root)
|
||||
|
@ -1432,11 +1455,9 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
|
|||
if (root->fs_info->reloc_ctl->merge_reloc_tree &&
|
||||
btrfs_root_refs(root_item) == 0) {
|
||||
root->reloc_root = NULL;
|
||||
del = 1;
|
||||
__del_reloc_root(reloc_root);
|
||||
}
|
||||
|
||||
__update_reloc_root(reloc_root, del);
|
||||
|
||||
if (reloc_root->commit_root != reloc_root->node) {
|
||||
btrfs_set_root_node(root_item, reloc_root->node);
|
||||
free_extent_buffer(reloc_root->commit_root);
|
||||
|
@ -2287,7 +2308,7 @@ void free_reloc_roots(struct list_head *list)
|
|||
while (!list_empty(list)) {
|
||||
reloc_root = list_entry(list->next, struct btrfs_root,
|
||||
root_list);
|
||||
__update_reloc_root(reloc_root, 1);
|
||||
__del_reloc_root(reloc_root);
|
||||
free_extent_buffer(reloc_root->node);
|
||||
free_extent_buffer(reloc_root->commit_root);
|
||||
kfree(reloc_root);
|
||||
|
@ -2332,7 +2353,7 @@ int merge_reloc_roots(struct reloc_control *rc)
|
|||
|
||||
ret = merge_reloc_root(rc, root);
|
||||
if (ret) {
|
||||
__update_reloc_root(reloc_root, 1);
|
||||
__del_reloc_root(reloc_root);
|
||||
free_extent_buffer(reloc_root->node);
|
||||
free_extent_buffer(reloc_root->commit_root);
|
||||
kfree(reloc_root);
|
||||
|
@ -2388,6 +2409,13 @@ int merge_reloc_roots(struct reloc_control *rc)
|
|||
btrfs_std_error(root->fs_info, ret);
|
||||
if (!list_empty(&reloc_roots))
|
||||
free_reloc_roots(&reloc_roots);
|
||||
|
||||
/* new reloc root may be added */
|
||||
mutex_lock(&root->fs_info->reloc_mutex);
|
||||
list_splice_init(&rc->reloc_roots, &reloc_roots);
|
||||
mutex_unlock(&root->fs_info->reloc_mutex);
|
||||
if (!list_empty(&reloc_roots))
|
||||
free_reloc_roots(&reloc_roots);
|
||||
}
|
||||
|
||||
BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
|
||||
|
@ -4522,6 +4550,11 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
|
|||
BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
|
||||
root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
|
||||
|
||||
if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
|
||||
if (buf == root->node)
|
||||
__update_reloc_root(root, cow->start);
|
||||
}
|
||||
|
||||
level = btrfs_header_level(buf);
|
||||
if (btrfs_header_generation(buf) <=
|
||||
btrfs_root_last_snapshot(&root->root_item))
|
||||
|
|
|
@ -4723,8 +4723,8 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
|
|||
}
|
||||
|
||||
if (!access_ok(VERIFY_READ, arg->clone_sources,
|
||||
sizeof(*arg->clone_sources *
|
||||
arg->clone_sources_count))) {
|
||||
sizeof(*arg->clone_sources) *
|
||||
arg->clone_sources_count)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -432,7 +432,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
} else {
|
||||
printk(KERN_INFO "btrfs: setting nodatacow\n");
|
||||
}
|
||||
info->compress_type = BTRFS_COMPRESS_NONE;
|
||||
btrfs_clear_opt(info->mount_opt, COMPRESS);
|
||||
btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
|
||||
btrfs_set_opt(info->mount_opt, NODATACOW);
|
||||
|
@ -461,7 +460,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
btrfs_set_fs_incompat(info, COMPRESS_LZO);
|
||||
} else if (strncmp(args[0].from, "no", 2) == 0) {
|
||||
compress_type = "no";
|
||||
info->compress_type = BTRFS_COMPRESS_NONE;
|
||||
btrfs_clear_opt(info->mount_opt, COMPRESS);
|
||||
btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
|
||||
compress_force = false;
|
||||
|
@ -474,9 +472,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
|
||||
pr_info("btrfs: force %s compression\n",
|
||||
compress_type);
|
||||
} else
|
||||
} else if (btrfs_test_opt(root, COMPRESS)) {
|
||||
pr_info("btrfs: use %s compression\n",
|
||||
compress_type);
|
||||
}
|
||||
break;
|
||||
case Opt_ssd:
|
||||
printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
|
||||
|
|
Loading…
Reference in a new issue