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
@ -767,20 +767,19 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
|
|||||||
if (!path)
|
if (!path)
|
||||||
return -ENOMEM;
|
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) {
|
if (!trans) {
|
||||||
path->skip_locking = 1;
|
path->skip_locking = 1;
|
||||||
path->search_commit_root = 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:
|
again:
|
||||||
ret = btrfs_search_slot(trans, root->fs_info->extent_root,
|
ret = btrfs_search_slot(trans, root->fs_info->extent_root,
|
||||||
&key, path, 0, 0);
|
&key, path, 0, 0);
|
||||||
@ -788,7 +787,6 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) {
|
if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) {
|
||||||
metadata = 0;
|
|
||||||
if (path->slots[0]) {
|
if (path->slots[0]) {
|
||||||
path->slots[0]--;
|
path->slots[0]--;
|
||||||
btrfs_item_key_to_cpu(path->nodes[0], &key,
|
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_lock(&head->mutex);
|
||||||
mutex_unlock(&head->mutex);
|
mutex_unlock(&head->mutex);
|
||||||
btrfs_put_delayed_ref(&head->node);
|
btrfs_put_delayed_ref(&head->node);
|
||||||
goto again;
|
goto search_again;
|
||||||
}
|
}
|
||||||
if (head->extent_op && head->extent_op->update_flags)
|
if (head->extent_op && head->extent_op->update_flags)
|
||||||
extent_flags |= head->extent_op->flags_to_set;
|
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);
|
err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
|
||||||
if (err == -EINTR)
|
if (err == -EINTR)
|
||||||
goto out;
|
goto out_drop_write;
|
||||||
dentry = lookup_one_len(vol_args->name, parent, namelen);
|
dentry = lookup_one_len(vol_args->name, parent, namelen);
|
||||||
if (IS_ERR(dentry)) {
|
if (IS_ERR(dentry)) {
|
||||||
err = PTR_ERR(dentry);
|
err = PTR_ERR(dentry);
|
||||||
@ -2284,6 +2284,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
|
|||||||
dput(dentry);
|
dput(dentry);
|
||||||
out_unlock_dir:
|
out_unlock_dir:
|
||||||
mutex_unlock(&dir->i_mutex);
|
mutex_unlock(&dir->i_mutex);
|
||||||
|
out_drop_write:
|
||||||
mnt_drop_write_file(file);
|
mnt_drop_write_file(file);
|
||||||
out:
|
out:
|
||||||
kfree(vol_args);
|
kfree(vol_args);
|
||||||
|
@ -571,7 +571,9 @@ static int is_cowonly_root(u64 root_objectid)
|
|||||||
root_objectid == BTRFS_CHUNK_TREE_OBJECTID ||
|
root_objectid == BTRFS_CHUNK_TREE_OBJECTID ||
|
||||||
root_objectid == BTRFS_DEV_TREE_OBJECTID ||
|
root_objectid == BTRFS_DEV_TREE_OBJECTID ||
|
||||||
root_objectid == BTRFS_TREE_LOG_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 1;
|
||||||
return 0;
|
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
|
* 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 rb_node *rb_node;
|
||||||
struct mapping_node *node = NULL;
|
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);
|
spin_lock(&rc->reloc_root_tree.lock);
|
||||||
rb_node = tree_search(&rc->reloc_root_tree.rb_root,
|
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) {
|
if (rb_node) {
|
||||||
node = rb_entry(rb_node, struct mapping_node, rb_node);
|
node = rb_entry(rb_node, struct mapping_node, rb_node);
|
||||||
rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
|
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;
|
return 0;
|
||||||
BUG_ON((struct btrfs_root *)node->data != root);
|
BUG_ON((struct btrfs_root *)node->data != root);
|
||||||
|
|
||||||
if (!del) {
|
spin_lock(&rc->reloc_root_tree.lock);
|
||||||
spin_lock(&rc->reloc_root_tree.lock);
|
node->bytenr = new_bytenr;
|
||||||
node->bytenr = root->node->start;
|
rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
|
||||||
rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
|
node->bytenr, &node->rb_node);
|
||||||
node->bytenr, &node->rb_node);
|
spin_unlock(&rc->reloc_root_tree.lock);
|
||||||
spin_unlock(&rc->reloc_root_tree.lock);
|
if (rb_node)
|
||||||
if (rb_node)
|
backref_tree_panic(rb_node, -EEXIST, node->bytenr);
|
||||||
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);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1420,7 +1444,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
|
|||||||
{
|
{
|
||||||
struct btrfs_root *reloc_root;
|
struct btrfs_root *reloc_root;
|
||||||
struct btrfs_root_item *root_item;
|
struct btrfs_root_item *root_item;
|
||||||
int del = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!root->reloc_root)
|
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 &&
|
if (root->fs_info->reloc_ctl->merge_reloc_tree &&
|
||||||
btrfs_root_refs(root_item) == 0) {
|
btrfs_root_refs(root_item) == 0) {
|
||||||
root->reloc_root = NULL;
|
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) {
|
if (reloc_root->commit_root != reloc_root->node) {
|
||||||
btrfs_set_root_node(root_item, reloc_root->node);
|
btrfs_set_root_node(root_item, reloc_root->node);
|
||||||
free_extent_buffer(reloc_root->commit_root);
|
free_extent_buffer(reloc_root->commit_root);
|
||||||
@ -2287,7 +2308,7 @@ void free_reloc_roots(struct list_head *list)
|
|||||||
while (!list_empty(list)) {
|
while (!list_empty(list)) {
|
||||||
reloc_root = list_entry(list->next, struct btrfs_root,
|
reloc_root = list_entry(list->next, struct btrfs_root,
|
||||||
root_list);
|
root_list);
|
||||||
__update_reloc_root(reloc_root, 1);
|
__del_reloc_root(reloc_root);
|
||||||
free_extent_buffer(reloc_root->node);
|
free_extent_buffer(reloc_root->node);
|
||||||
free_extent_buffer(reloc_root->commit_root);
|
free_extent_buffer(reloc_root->commit_root);
|
||||||
kfree(reloc_root);
|
kfree(reloc_root);
|
||||||
@ -2332,7 +2353,7 @@ int merge_reloc_roots(struct reloc_control *rc)
|
|||||||
|
|
||||||
ret = merge_reloc_root(rc, root);
|
ret = merge_reloc_root(rc, root);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
__update_reloc_root(reloc_root, 1);
|
__del_reloc_root(reloc_root);
|
||||||
free_extent_buffer(reloc_root->node);
|
free_extent_buffer(reloc_root->node);
|
||||||
free_extent_buffer(reloc_root->commit_root);
|
free_extent_buffer(reloc_root->commit_root);
|
||||||
kfree(reloc_root);
|
kfree(reloc_root);
|
||||||
@ -2388,6 +2409,13 @@ int merge_reloc_roots(struct reloc_control *rc)
|
|||||||
btrfs_std_error(root->fs_info, ret);
|
btrfs_std_error(root->fs_info, ret);
|
||||||
if (!list_empty(&reloc_roots))
|
if (!list_empty(&reloc_roots))
|
||||||
free_reloc_roots(&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));
|
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 &&
|
BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
|
||||||
root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
|
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);
|
level = btrfs_header_level(buf);
|
||||||
if (btrfs_header_generation(buf) <=
|
if (btrfs_header_generation(buf) <=
|
||||||
btrfs_root_last_snapshot(&root->root_item))
|
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,
|
if (!access_ok(VERIFY_READ, arg->clone_sources,
|
||||||
sizeof(*arg->clone_sources *
|
sizeof(*arg->clone_sources) *
|
||||||
arg->clone_sources_count))) {
|
arg->clone_sources_count)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -432,7 +432,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||||||
} else {
|
} else {
|
||||||
printk(KERN_INFO "btrfs: setting nodatacow\n");
|
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, COMPRESS);
|
||||||
btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
|
btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
|
||||||
btrfs_set_opt(info->mount_opt, NODATACOW);
|
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);
|
btrfs_set_fs_incompat(info, COMPRESS_LZO);
|
||||||
} else if (strncmp(args[0].from, "no", 2) == 0) {
|
} else if (strncmp(args[0].from, "no", 2) == 0) {
|
||||||
compress_type = "no";
|
compress_type = "no";
|
||||||
info->compress_type = BTRFS_COMPRESS_NONE;
|
|
||||||
btrfs_clear_opt(info->mount_opt, COMPRESS);
|
btrfs_clear_opt(info->mount_opt, COMPRESS);
|
||||||
btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
|
btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
|
||||||
compress_force = false;
|
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);
|
btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
|
||||||
pr_info("btrfs: force %s compression\n",
|
pr_info("btrfs: force %s compression\n",
|
||||||
compress_type);
|
compress_type);
|
||||||
} else
|
} else if (btrfs_test_opt(root, COMPRESS)) {
|
||||||
pr_info("btrfs: use %s compression\n",
|
pr_info("btrfs: use %s compression\n",
|
||||||
compress_type);
|
compress_type);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Opt_ssd:
|
case Opt_ssd:
|
||||||
printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
|
printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user