diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 22 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 3 | ||||
| -rw-r--r-- | fs/btrfs/relocation.c | 81 | ||||
| -rw-r--r-- | fs/btrfs/send.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 5 |
5 files changed, 73 insertions, 42 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 45d98d01028f..9c01509dd8ab 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -767,20 +767,19 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, | |||
| 767 | if (!path) | 767 | if (!path) |
| 768 | return -ENOMEM; | 768 | return -ENOMEM; |
| 769 | 769 | ||
| 770 | if (metadata) { | ||
| 771 | key.objectid = bytenr; | ||
| 772 | key.type = BTRFS_METADATA_ITEM_KEY; | ||
| 773 | key.offset = offset; | ||
| 774 | } else { | ||
| 775 | key.objectid = bytenr; | ||
| 776 | key.type = BTRFS_EXTENT_ITEM_KEY; | ||
| 777 | key.offset = offset; | ||
| 778 | } | ||
| 779 | |||
| 780 | if (!trans) { | 770 | if (!trans) { |
| 781 | path->skip_locking = 1; | 771 | path->skip_locking = 1; |
| 782 | path->search_commit_root = 1; | 772 | path->search_commit_root = 1; |
| 783 | } | 773 | } |
| 774 | |||
| 775 | search_again: | ||
| 776 | key.objectid = bytenr; | ||
| 777 | key.offset = offset; | ||
| 778 | if (metadata) | ||
| 779 | key.type = BTRFS_METADATA_ITEM_KEY; | ||
| 780 | else | ||
| 781 | key.type = BTRFS_EXTENT_ITEM_KEY; | ||
| 782 | |||
| 784 | again: | 783 | again: |
| 785 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, | 784 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, |
| 786 | &key, path, 0, 0); | 785 | &key, path, 0, 0); |
| @@ -788,7 +787,6 @@ again: | |||
| 788 | goto out_free; | 787 | goto out_free; |
| 789 | 788 | ||
| 790 | if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) { | 789 | if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) { |
| 791 | metadata = 0; | ||
| 792 | if (path->slots[0]) { | 790 | if (path->slots[0]) { |
| 793 | path->slots[0]--; | 791 | path->slots[0]--; |
| 794 | btrfs_item_key_to_cpu(path->nodes[0], &key, | 792 | btrfs_item_key_to_cpu(path->nodes[0], &key, |
| @@ -855,7 +853,7 @@ again: | |||
| 855 | mutex_lock(&head->mutex); | 853 | mutex_lock(&head->mutex); |
| 856 | mutex_unlock(&head->mutex); | 854 | mutex_unlock(&head->mutex); |
| 857 | btrfs_put_delayed_ref(&head->node); | 855 | btrfs_put_delayed_ref(&head->node); |
| 858 | goto again; | 856 | goto search_again; |
| 859 | } | 857 | } |
| 860 | if (head->extent_op && head->extent_op->update_flags) | 858 | if (head->extent_op && head->extent_op->update_flags) |
| 861 | extent_flags |= head->extent_op->flags_to_set; | 859 | extent_flags |= head->extent_op->flags_to_set; |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a111622598b0..21da5762b0b1 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -2121,7 +2121,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
| 2121 | 2121 | ||
| 2122 | err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT); | 2122 | err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT); |
| 2123 | if (err == -EINTR) | 2123 | if (err == -EINTR) |
| 2124 | goto out; | 2124 | goto out_drop_write; |
| 2125 | dentry = lookup_one_len(vol_args->name, parent, namelen); | 2125 | dentry = lookup_one_len(vol_args->name, parent, namelen); |
| 2126 | if (IS_ERR(dentry)) { | 2126 | if (IS_ERR(dentry)) { |
| 2127 | err = PTR_ERR(dentry); | 2127 | err = PTR_ERR(dentry); |
| @@ -2284,6 +2284,7 @@ out_dput: | |||
| 2284 | dput(dentry); | 2284 | dput(dentry); |
| 2285 | out_unlock_dir: | 2285 | out_unlock_dir: |
| 2286 | mutex_unlock(&dir->i_mutex); | 2286 | mutex_unlock(&dir->i_mutex); |
| 2287 | out_drop_write: | ||
| 2287 | mnt_drop_write_file(file); | 2288 | mnt_drop_write_file(file); |
| 2288 | out: | 2289 | out: |
| 2289 | kfree(vol_args); | 2290 | kfree(vol_args); |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index ce459a7cb16d..429c73c374b8 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -571,7 +571,9 @@ static int is_cowonly_root(u64 root_objectid) | |||
| 571 | root_objectid == BTRFS_CHUNK_TREE_OBJECTID || | 571 | root_objectid == BTRFS_CHUNK_TREE_OBJECTID || |
| 572 | root_objectid == BTRFS_DEV_TREE_OBJECTID || | 572 | root_objectid == BTRFS_DEV_TREE_OBJECTID || |
| 573 | root_objectid == BTRFS_TREE_LOG_OBJECTID || | 573 | root_objectid == BTRFS_TREE_LOG_OBJECTID || |
| 574 | root_objectid == BTRFS_CSUM_TREE_OBJECTID) | 574 | root_objectid == BTRFS_CSUM_TREE_OBJECTID || |
| 575 | root_objectid == BTRFS_UUID_TREE_OBJECTID || | ||
| 576 | root_objectid == BTRFS_QUOTA_TREE_OBJECTID) | ||
| 575 | return 1; | 577 | return 1; |
| 576 | return 0; | 578 | return 0; |
| 577 | } | 579 | } |
| @@ -1264,10 +1266,10 @@ static int __must_check __add_reloc_root(struct btrfs_root *root) | |||
| 1264 | } | 1266 | } |
| 1265 | 1267 | ||
| 1266 | /* | 1268 | /* |
| 1267 | * helper to update/delete the 'address of tree root -> reloc tree' | 1269 | * helper to delete the 'address of tree root -> reloc tree' |
| 1268 | * mapping | 1270 | * mapping |
| 1269 | */ | 1271 | */ |
| 1270 | static int __update_reloc_root(struct btrfs_root *root, int del) | 1272 | static void __del_reloc_root(struct btrfs_root *root) |
| 1271 | { | 1273 | { |
| 1272 | struct rb_node *rb_node; | 1274 | struct rb_node *rb_node; |
| 1273 | struct mapping_node *node = NULL; | 1275 | struct mapping_node *node = NULL; |
| @@ -1275,7 +1277,7 @@ static int __update_reloc_root(struct btrfs_root *root, int del) | |||
| 1275 | 1277 | ||
| 1276 | spin_lock(&rc->reloc_root_tree.lock); | 1278 | spin_lock(&rc->reloc_root_tree.lock); |
| 1277 | rb_node = tree_search(&rc->reloc_root_tree.rb_root, | 1279 | rb_node = tree_search(&rc->reloc_root_tree.rb_root, |
| 1278 | root->commit_root->start); | 1280 | root->node->start); |
| 1279 | if (rb_node) { | 1281 | if (rb_node) { |
| 1280 | node = rb_entry(rb_node, struct mapping_node, rb_node); | 1282 | node = rb_entry(rb_node, struct mapping_node, rb_node); |
| 1281 | rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); | 1283 | 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 | spin_unlock(&rc->reloc_root_tree.lock); | 1285 | spin_unlock(&rc->reloc_root_tree.lock); |
| 1284 | 1286 | ||
| 1285 | if (!node) | 1287 | if (!node) |
| 1286 | return 0; | 1288 | return; |
| 1287 | BUG_ON((struct btrfs_root *)node->data != root); | 1289 | BUG_ON((struct btrfs_root *)node->data != root); |
| 1288 | 1290 | ||
| 1289 | if (!del) { | 1291 | spin_lock(&root->fs_info->trans_lock); |
| 1290 | spin_lock(&rc->reloc_root_tree.lock); | 1292 | list_del_init(&root->root_list); |
| 1291 | node->bytenr = root->node->start; | 1293 | spin_unlock(&root->fs_info->trans_lock); |
| 1292 | rb_node = tree_insert(&rc->reloc_root_tree.rb_root, | 1294 | kfree(node); |
| 1293 | node->bytenr, &node->rb_node); | 1295 | } |
| 1294 | spin_unlock(&rc->reloc_root_tree.lock); | 1296 | |
| 1295 | if (rb_node) | 1297 | /* |
| 1296 | backref_tree_panic(rb_node, -EEXIST, node->bytenr); | 1298 | * helper to update the 'address of tree root -> reloc tree' |
| 1297 | } else { | 1299 | * mapping |
| 1298 | spin_lock(&root->fs_info->trans_lock); | 1300 | */ |
| 1299 | list_del_init(&root->root_list); | 1301 | static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr) |
| 1300 | spin_unlock(&root->fs_info->trans_lock); | 1302 | { |
| 1301 | kfree(node); | 1303 | struct rb_node *rb_node; |
| 1304 | struct mapping_node *node = NULL; | ||
| 1305 | struct reloc_control *rc = root->fs_info->reloc_ctl; | ||
| 1306 | |||
| 1307 | spin_lock(&rc->reloc_root_tree.lock); | ||
| 1308 | rb_node = tree_search(&rc->reloc_root_tree.rb_root, | ||
| 1309 | root->node->start); | ||
| 1310 | if (rb_node) { | ||
| 1311 | node = rb_entry(rb_node, struct mapping_node, rb_node); | ||
| 1312 | rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); | ||
| 1302 | } | 1313 | } |
| 1314 | spin_unlock(&rc->reloc_root_tree.lock); | ||
| 1315 | |||
| 1316 | if (!node) | ||
| 1317 | return 0; | ||
| 1318 | BUG_ON((struct btrfs_root *)node->data != root); | ||
| 1319 | |||
| 1320 | spin_lock(&rc->reloc_root_tree.lock); | ||
| 1321 | node->bytenr = new_bytenr; | ||
| 1322 | rb_node = tree_insert(&rc->reloc_root_tree.rb_root, | ||
| 1323 | node->bytenr, &node->rb_node); | ||
| 1324 | spin_unlock(&rc->reloc_root_tree.lock); | ||
| 1325 | if (rb_node) | ||
| 1326 | backref_tree_panic(rb_node, -EEXIST, node->bytenr); | ||
| 1303 | return 0; | 1327 | return 0; |
| 1304 | } | 1328 | } |
| 1305 | 1329 | ||
| @@ -1420,7 +1444,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, | |||
| 1420 | { | 1444 | { |
| 1421 | struct btrfs_root *reloc_root; | 1445 | struct btrfs_root *reloc_root; |
| 1422 | struct btrfs_root_item *root_item; | 1446 | struct btrfs_root_item *root_item; |
| 1423 | int del = 0; | ||
| 1424 | int ret; | 1447 | int ret; |
| 1425 | 1448 | ||
| 1426 | if (!root->reloc_root) | 1449 | if (!root->reloc_root) |
| @@ -1432,11 +1455,9 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, | |||
| 1432 | if (root->fs_info->reloc_ctl->merge_reloc_tree && | 1455 | if (root->fs_info->reloc_ctl->merge_reloc_tree && |
| 1433 | btrfs_root_refs(root_item) == 0) { | 1456 | btrfs_root_refs(root_item) == 0) { |
| 1434 | root->reloc_root = NULL; | 1457 | root->reloc_root = NULL; |
| 1435 | del = 1; | 1458 | __del_reloc_root(reloc_root); |
| 1436 | } | 1459 | } |
| 1437 | 1460 | ||
| 1438 | __update_reloc_root(reloc_root, del); | ||
| 1439 | |||
| 1440 | if (reloc_root->commit_root != reloc_root->node) { | 1461 | if (reloc_root->commit_root != reloc_root->node) { |
| 1441 | btrfs_set_root_node(root_item, reloc_root->node); | 1462 | btrfs_set_root_node(root_item, reloc_root->node); |
| 1442 | free_extent_buffer(reloc_root->commit_root); | 1463 | free_extent_buffer(reloc_root->commit_root); |
| @@ -2287,7 +2308,7 @@ void free_reloc_roots(struct list_head *list) | |||
| 2287 | while (!list_empty(list)) { | 2308 | while (!list_empty(list)) { |
| 2288 | reloc_root = list_entry(list->next, struct btrfs_root, | 2309 | reloc_root = list_entry(list->next, struct btrfs_root, |
| 2289 | root_list); | 2310 | root_list); |
| 2290 | __update_reloc_root(reloc_root, 1); | 2311 | __del_reloc_root(reloc_root); |
| 2291 | free_extent_buffer(reloc_root->node); | 2312 | free_extent_buffer(reloc_root->node); |
| 2292 | free_extent_buffer(reloc_root->commit_root); | 2313 | free_extent_buffer(reloc_root->commit_root); |
| 2293 | kfree(reloc_root); | 2314 | kfree(reloc_root); |
| @@ -2332,7 +2353,7 @@ again: | |||
| 2332 | 2353 | ||
| 2333 | ret = merge_reloc_root(rc, root); | 2354 | ret = merge_reloc_root(rc, root); |
| 2334 | if (ret) { | 2355 | if (ret) { |
| 2335 | __update_reloc_root(reloc_root, 1); | 2356 | __del_reloc_root(reloc_root); |
| 2336 | free_extent_buffer(reloc_root->node); | 2357 | free_extent_buffer(reloc_root->node); |
| 2337 | free_extent_buffer(reloc_root->commit_root); | 2358 | free_extent_buffer(reloc_root->commit_root); |
| 2338 | kfree(reloc_root); | 2359 | kfree(reloc_root); |
| @@ -2388,6 +2409,13 @@ out: | |||
| 2388 | btrfs_std_error(root->fs_info, ret); | 2409 | btrfs_std_error(root->fs_info, ret); |
| 2389 | if (!list_empty(&reloc_roots)) | 2410 | if (!list_empty(&reloc_roots)) |
| 2390 | free_reloc_roots(&reloc_roots); | 2411 | free_reloc_roots(&reloc_roots); |
| 2412 | |||
| 2413 | /* new reloc root may be added */ | ||
| 2414 | mutex_lock(&root->fs_info->reloc_mutex); | ||
| 2415 | list_splice_init(&rc->reloc_roots, &reloc_roots); | ||
| 2416 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
| 2417 | if (!list_empty(&reloc_roots)) | ||
| 2418 | free_reloc_roots(&reloc_roots); | ||
| 2391 | } | 2419 | } |
| 2392 | 2420 | ||
| 2393 | BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); | 2421 | 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 | BUG_ON(rc->stage == UPDATE_DATA_PTRS && | 4550 | BUG_ON(rc->stage == UPDATE_DATA_PTRS && |
| 4523 | root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID); | 4551 | root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID); |
| 4524 | 4552 | ||
| 4553 | if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) { | ||
| 4554 | if (buf == root->node) | ||
| 4555 | __update_reloc_root(root, cow->start); | ||
| 4556 | } | ||
| 4557 | |||
| 4525 | level = btrfs_header_level(buf); | 4558 | level = btrfs_header_level(buf); |
| 4526 | if (btrfs_header_generation(buf) <= | 4559 | if (btrfs_header_generation(buf) <= |
| 4527 | btrfs_root_last_snapshot(&root->root_item)) | 4560 | btrfs_root_last_snapshot(&root->root_item)) |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 6837fe87f3a6..945d1db98f26 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
| @@ -4723,8 +4723,8 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) | |||
| 4723 | } | 4723 | } |
| 4724 | 4724 | ||
| 4725 | if (!access_ok(VERIFY_READ, arg->clone_sources, | 4725 | if (!access_ok(VERIFY_READ, arg->clone_sources, |
| 4726 | sizeof(*arg->clone_sources * | 4726 | sizeof(*arg->clone_sources) * |
| 4727 | arg->clone_sources_count))) { | 4727 | arg->clone_sources_count)) { |
| 4728 | ret = -EFAULT; | 4728 | ret = -EFAULT; |
| 4729 | goto out; | 4729 | goto out; |
| 4730 | } | 4730 | } |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 2d8ac1bf0cf9..d71a11d13dfa 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -432,7 +432,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 432 | } else { | 432 | } else { |
| 433 | printk(KERN_INFO "btrfs: setting nodatacow\n"); | 433 | printk(KERN_INFO "btrfs: setting nodatacow\n"); |
| 434 | } | 434 | } |
| 435 | info->compress_type = BTRFS_COMPRESS_NONE; | ||
| 436 | btrfs_clear_opt(info->mount_opt, COMPRESS); | 435 | btrfs_clear_opt(info->mount_opt, COMPRESS); |
| 437 | btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS); | 436 | btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS); |
| 438 | btrfs_set_opt(info->mount_opt, NODATACOW); | 437 | btrfs_set_opt(info->mount_opt, NODATACOW); |
| @@ -461,7 +460,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 461 | btrfs_set_fs_incompat(info, COMPRESS_LZO); | 460 | btrfs_set_fs_incompat(info, COMPRESS_LZO); |
| 462 | } else if (strncmp(args[0].from, "no", 2) == 0) { | 461 | } else if (strncmp(args[0].from, "no", 2) == 0) { |
| 463 | compress_type = "no"; | 462 | compress_type = "no"; |
| 464 | info->compress_type = BTRFS_COMPRESS_NONE; | ||
| 465 | btrfs_clear_opt(info->mount_opt, COMPRESS); | 463 | btrfs_clear_opt(info->mount_opt, COMPRESS); |
| 466 | btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS); | 464 | btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS); |
| 467 | compress_force = false; | 465 | compress_force = false; |
| @@ -474,9 +472,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 474 | btrfs_set_opt(info->mount_opt, FORCE_COMPRESS); | 472 | btrfs_set_opt(info->mount_opt, FORCE_COMPRESS); |
| 475 | pr_info("btrfs: force %s compression\n", | 473 | pr_info("btrfs: force %s compression\n", |
| 476 | compress_type); | 474 | compress_type); |
| 477 | } else | 475 | } else if (btrfs_test_opt(root, COMPRESS)) { |
| 478 | pr_info("btrfs: use %s compression\n", | 476 | pr_info("btrfs: use %s compression\n", |
| 479 | compress_type); | 477 | compress_type); |
| 478 | } | ||
| 480 | break; | 479 | break; |
| 481 | case Opt_ssd: | 480 | case Opt_ssd: |
| 482 | printk(KERN_INFO "btrfs: use ssd allocation scheme\n"); | 481 | printk(KERN_INFO "btrfs: use ssd allocation scheme\n"); |
