Commit e09f67f1 authored by Linus Torvalds's avatar Linus Torvalds

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
parents c9111b4d 700ff4f0
...@@ -767,20 +767,19 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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,7 @@ static int __update_reloc_root(struct btrfs_root *root, int del) ...@@ -1275,7 +1277,7 @@ 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) { 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);
...@@ -1283,23 +1285,45 @@ static int __update_reloc_root(struct btrfs_root *root, int del) ...@@ -1283,23 +1285,45 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
spin_unlock(&rc->reloc_root_tree.lock); spin_unlock(&rc->reloc_root_tree.lock);
if (!node) if (!node)
return 0; return;
BUG_ON((struct btrfs_root *)node->data != root); BUG_ON((struct btrfs_root *)node->data != root);
if (!del) { spin_lock(&root->fs_info->trans_lock);
spin_lock(&rc->reloc_root_tree.lock); list_del_init(&root->root_list);
node->bytenr = root->node->start; spin_unlock(&root->fs_info->trans_lock);
rb_node = tree_insert(&rc->reloc_root_tree.rb_root, kfree(node);
node->bytenr, &node->rb_node); }
spin_unlock(&rc->reloc_root_tree.lock);
if (rb_node) /*
backref_tree_panic(rb_node, -EEXIST, node->bytenr); * helper to update the 'address of tree root -> reloc tree'
} else { * mapping
spin_lock(&root->fs_info->trans_lock); */
list_del_init(&root->root_list); static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr)
spin_unlock(&root->fs_info->trans_lock); {
kfree(node); 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);
} }
spin_unlock(&rc->reloc_root_tree.lock);
if (!node)
return 0;
BUG_ON((struct btrfs_root *)node->data != root);
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; return 0;
} }
...@@ -1420,7 +1444,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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_) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment