History

Revert "btrfs: turn fs_roots_radix in btrfs_fs_info into an XArray"

This reverts commit 48b36a602a335c184505346b5b37077840660634. Revert the xarray conversion, there's a problem with potential sleep-inside-spinlock [1] when calling xa_insert that triggers GFP_NOFS allocation. The radix tree used the preloading mechanism to avoid sleeping but this is not available in xarray. Conversion from spin lock to mutex is possible but at time of rc6 is riskier than a clean revert. [1] https://lore.kernel.org/linux-btrfs/cover.1657097693.git.fdmanana@suse.com/

David Sterba committed 4 years ago

Commit fc7cbcd1 parent b3a3b026 files · +171 −139Browse files

Unified · Split

6 files
  1. fs/btrfs/ctree.h +3 −5
  2. fs/btrfs/disk-io.c +97 −76
  3. fs/btrfs/extent-tree.c +1 −1
  4. fs/btrfs/inode.c +6 −7
  5. fs/btrfs/tests/btrfs-tests.c +1 −1
  6. fs/btrfs/transaction.c +63 −49
fs/btrfs/ctree.h+3−5
@@ -675,9 +675,8 @@ struct btrfs_fs_info { · 674 unmodified lines
675 rwlock_t global_root_lock;675 rwlock_t global_root_lock;
676 struct rb_root global_root_tree;676 struct rb_root global_root_tree;
677 677
678 /* The xarray that holds all the FS roots */678 spinlock_t fs_roots_radix_lock;
679 spinlock_t fs_roots_lock;679 struct radix_tree_root fs_roots_radix;
680 struct xarray fs_roots;
681 680
682 /* block group cache stuff */681 /* block group cache stuff */
683 rwlock_t block_group_cache_lock;682 rwlock_t block_group_cache_lock;
@@ -1119,8 +1118,7 @@ enum { · 435 unmodified lines
1119 */1118 */
1120 BTRFS_ROOT_SHAREABLE,1119 BTRFS_ROOT_SHAREABLE,
1121 BTRFS_ROOT_TRACK_DIRTY,1120 BTRFS_ROOT_TRACK_DIRTY,
1122 /* The root is tracked in fs_info::fs_roots */1121 BTRFS_ROOT_IN_RADIX,
1123 BTRFS_ROOT_REGISTERED,
1124 BTRFS_ROOT_ORPHAN_ITEM_INSERTED,1122 BTRFS_ROOT_ORPHAN_ITEM_INSERTED,
1125 BTRFS_ROOT_DEFRAG_RUNNING,1123 BTRFS_ROOT_DEFRAG_RUNNING,
1126 BTRFS_ROOT_FORCE_COW,1124 BTRFS_ROOT_FORCE_COW,
fs/btrfs/disk-io.c+97−76
@@ -5,6 +5,7 @@ · 4 unmodified lines
5 5
6#include <linux/fs.h>6#include <linux/fs.h>
7#include <linux/blkdev.h>7#include <linux/blkdev.h>
8#include <linux/radix-tree.h>
8#include <linux/writeback.h>9#include <linux/writeback.h>
9#include <linux/workqueue.h>10#include <linux/workqueue.h>
10#include <linux/kthread.h>11#include <linux/kthread.h>
@@ -1210,9 +1211,9 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info, · 1199 unmodified lines
1210 btrfs_qgroup_init_swapped_blocks(&root->swapped_blocks);1211 btrfs_qgroup_init_swapped_blocks(&root->swapped_blocks);
1211#ifdef CONFIG_BTRFS_DEBUG1212#ifdef CONFIG_BTRFS_DEBUG
1212 INIT_LIST_HEAD(&root->leak_list);1213 INIT_LIST_HEAD(&root->leak_list);
1213 spin_lock(&fs_info->fs_roots_lock);1214 spin_lock(&fs_info->fs_roots_radix_lock);
1214 list_add_tail(&root->leak_list, &fs_info->allocated_roots);1215 list_add_tail(&root->leak_list, &fs_info->allocated_roots);
1215 spin_unlock(&fs_info->fs_roots_lock);1216 spin_unlock(&fs_info->fs_roots_radix_lock);
1216#endif1217#endif
1217}1218}
1218 1219
@@ -1659,11 +1660,12 @@ static struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, · 440 unmodified lines
1659{1660{
1660 struct btrfs_root *root;1661 struct btrfs_root *root;
1661 1662
1662 spin_lock(&fs_info->fs_roots_lock);1663 spin_lock(&fs_info->fs_roots_radix_lock);
1663 root = xa_load(&fs_info->fs_roots, (unsigned long)root_id);1664 root = radix_tree_lookup(&fs_info->fs_roots_radix,
1665 (unsigned long)root_id);
1664 if (root)1666 if (root)
1665 root = btrfs_grab_root(root);1667 root = btrfs_grab_root(root);
1666 spin_unlock(&fs_info->fs_roots_lock);1668 spin_unlock(&fs_info->fs_roots_radix_lock);
1667 return root;1669 return root;
1668}1670}
1669 1671
@@ -1705,14 +1707,20 @@ int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info, · 35 unmodified lines
1705{1707{
1706 int ret;1708 int ret;
1707 1709
1708 spin_lock(&fs_info->fs_roots_lock);1710 ret = radix_tree_preload(GFP_NOFS);
1709 ret = xa_insert(&fs_info->fs_roots, (unsigned long)root->root_key.objectid,1711 if (ret)
1710 root, GFP_NOFS);1712 return ret;
1713
1714 spin_lock(&fs_info->fs_roots_radix_lock);
1715 ret = radix_tree_insert(&fs_info->fs_roots_radix,
1716 (unsigned long)root->root_key.objectid,
1717 root);
1711 if (ret == 0) {1718 if (ret == 0) {
1712 btrfs_grab_root(root);1719 btrfs_grab_root(root);
1713 set_bit(BTRFS_ROOT_REGISTERED, &root->state);1720 set_bit(BTRFS_ROOT_IN_RADIX, &root->state);
1714 }1721 }
1715 spin_unlock(&fs_info->fs_roots_lock);1722 spin_unlock(&fs_info->fs_roots_radix_lock);
1723 radix_tree_preload_end();
1716 1724
1717 return ret;1725 return ret;
1718}1726}
@@ -2342,9 +2350,9 @@ void btrfs_put_root(struct btrfs_root *root) · 623 unmodified lines
2342 btrfs_drew_lock_destroy(&root->snapshot_lock);2350 btrfs_drew_lock_destroy(&root->snapshot_lock);
2343 free_root_extent_buffers(root);2351 free_root_extent_buffers(root);
2344#ifdef CONFIG_BTRFS_DEBUG2352#ifdef CONFIG_BTRFS_DEBUG
2345 spin_lock(&root->fs_info->fs_roots_lock);2353 spin_lock(&root->fs_info->fs_roots_radix_lock);
2346 list_del_init(&root->leak_list);2354 list_del_init(&root->leak_list);
2347 spin_unlock(&root->fs_info->fs_roots_lock);2355 spin_unlock(&root->fs_info->fs_roots_radix_lock);
2348#endif2356#endif
2349 kfree(root);2357 kfree(root);
2350 }2358 }
@@ -2352,21 +2360,28 @@ void btrfs_put_root(struct btrfs_root *root) · 1 unmodified line
2352 2360
2353void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)2361void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
2354{2362{
2355 struct btrfs_root *root;2363 int ret;
2356 unsigned long index = 0;2364 struct btrfs_root *gang[8];
2365 int i;
2357 2366
2358 while (!list_empty(&fs_info->dead_roots)) {2367 while (!list_empty(&fs_info->dead_roots)) {
2359 root = list_entry(fs_info->dead_roots.next,2368 gang[0] = list_entry(fs_info->dead_roots.next,
2360 struct btrfs_root, root_list);2369 struct btrfs_root, root_list);
2361 list_del(&root->root_list);2370 list_del(&gang[0]->root_list);
2362 2371
2363 if (test_bit(BTRFS_ROOT_REGISTERED, &root->state))2372 if (test_bit(BTRFS_ROOT_IN_RADIX, &gang[0]->state))
2364 btrfs_drop_and_free_fs_root(fs_info, root);2373 btrfs_drop_and_free_fs_root(fs_info, gang[0]);
2365 btrfs_put_root(root);2374 btrfs_put_root(gang[0]);
2366 }2375 }
2367 2376
2368 xa_for_each(&fs_info->fs_roots, index, root) {2377 while (1) {
2369 btrfs_drop_and_free_fs_root(fs_info, root);2378 ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
2379 (void **)gang, 0,
2380 ARRAY_SIZE(gang));
2381 if (!ret)
2382 break;
2383 for (i = 0; i < ret; i++)
2384 btrfs_drop_and_free_fs_root(fs_info, gang[i]);
2370 }2385 }
2371}2386}
2372 2387
@@ -3134,7 +3149,7 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info) · 761 unmodified lines
3134 3149
3135void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)3150void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
3136{3151{
3137 xa_init_flags(&fs_info->fs_roots, GFP_ATOMIC);3152 INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
3138 xa_init_flags(&fs_info->extent_buffers, GFP_ATOMIC);3153 xa_init_flags(&fs_info->extent_buffers, GFP_ATOMIC);
3139 INIT_LIST_HEAD(&fs_info->trans_list);3154 INIT_LIST_HEAD(&fs_info->trans_list);
3140 INIT_LIST_HEAD(&fs_info->dead_roots);3155 INIT_LIST_HEAD(&fs_info->dead_roots);
@@ -3143,7 +3158,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info) · 2 unmodified lines
3143 INIT_LIST_HEAD(&fs_info->caching_block_groups);3158 INIT_LIST_HEAD(&fs_info->caching_block_groups);
3144 spin_lock_init(&fs_info->delalloc_root_lock);3159 spin_lock_init(&fs_info->delalloc_root_lock);
3145 spin_lock_init(&fs_info->trans_lock);3160 spin_lock_init(&fs_info->trans_lock);
3146 spin_lock_init(&fs_info->fs_roots_lock);3161 spin_lock_init(&fs_info->fs_roots_radix_lock);
3147 spin_lock_init(&fs_info->delayed_iput_lock);3162 spin_lock_init(&fs_info->delayed_iput_lock);
3148 spin_lock_init(&fs_info->defrag_inodes_lock);3163 spin_lock_init(&fs_info->defrag_inodes_lock);
3149 spin_lock_init(&fs_info->super_lock);3164 spin_lock_init(&fs_info->super_lock);
@@ -3374,7 +3389,7 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info) · 224 unmodified lines
3374 /*3389 /*
3375 * btrfs_find_orphan_roots() is responsible for finding all the dead3390 * btrfs_find_orphan_roots() is responsible for finding all the dead
3376 * roots (with 0 refs), flag them with BTRFS_ROOT_DEAD_TREE and load3391 * roots (with 0 refs), flag them with BTRFS_ROOT_DEAD_TREE and load
3377 * them into the fs_info->fs_roots. This must be done before3392 * them into the fs_info->fs_roots_radix tree. This must be done before
3378 * calling btrfs_orphan_cleanup() on the tree root. If we don't do it3393 * calling btrfs_orphan_cleanup() on the tree root. If we don't do it
3379 * first, then btrfs_orphan_cleanup() will delete a dead root's orphan3394 * first, then btrfs_orphan_cleanup() will delete a dead root's orphan
3380 * item before the root's tree is deleted - this means that if we unmount3395 * item before the root's tree is deleted - this means that if we unmount
@@ -4498,11 +4513,12 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, · 1117 unmodified lines
4498{4513{
4499 bool drop_ref = false;4514 bool drop_ref = false;
4500 4515
4501 spin_lock(&fs_info->fs_roots_lock);4516 spin_lock(&fs_info->fs_roots_radix_lock);
4502 xa_erase(&fs_info->fs_roots, (unsigned long)root->root_key.objectid);4517 radix_tree_delete(&fs_info->fs_roots_radix,
4503 if (test_and_clear_bit(BTRFS_ROOT_REGISTERED, &root->state))4518 (unsigned long)root->root_key.objectid);
4519 if (test_and_clear_bit(BTRFS_ROOT_IN_RADIX, &root->state))
4504 drop_ref = true;4520 drop_ref = true;
4505 spin_unlock(&fs_info->fs_roots_lock);4521 spin_unlock(&fs_info->fs_roots_radix_lock);
4506 4522
4507 if (BTRFS_FS_ERROR(fs_info)) {4523 if (BTRFS_FS_ERROR(fs_info)) {
4508 ASSERT(root->log_root == NULL);4524 ASSERT(root->log_root == NULL);
@@ -4518,48 +4534,50 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, · 9 unmodified lines
4518 4534
4519int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info)4535int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info)
4520{4536{
4521 struct btrfs_root *roots[8];4537 u64 root_objectid = 0;
4522 unsigned long index = 0;4538 struct btrfs_root *gang[8];
4523 int i;4539 int i = 0;
4524 int err = 0;4540 int err = 0;
4525 int grabbed;4541 unsigned int ret = 0;
4526 4542
4527 while (1) {4543 while (1) {
4528 struct btrfs_root *root;4544 spin_lock(&fs_info->fs_roots_radix_lock);
4529 4545 ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
4530 spin_lock(&fs_info->fs_roots_lock);4546 (void **)gang, root_objectid,
4531 if (!xa_find(&fs_info->fs_roots, &index, ULONG_MAX, XA_PRESENT)) {4547 ARRAY_SIZE(gang));
4532 spin_unlock(&fs_info->fs_roots_lock);4548 if (!ret) {
4533 return err;4549 spin_unlock(&fs_info->fs_roots_radix_lock);
4550 break;
4534 }4551 }
4552 root_objectid = gang[ret - 1]->root_key.objectid + 1;
4535 4553
4536 grabbed = 0;4554 for (i = 0; i < ret; i++) {
4537 xa_for_each_start(&fs_info->fs_roots, index, root, index) {4555 /* Avoid to grab roots in dead_roots */
4538 /* Avoid grabbing roots in dead_roots */4556 if (btrfs_root_refs(&gang[i]->root_item) == 0) {
4539 if (btrfs_root_refs(&root->root_item) > 0)4557 gang[i] = NULL;
4540 roots[grabbed++] = btrfs_grab_root(root);4558 continue;
4541 if (grabbed >= ARRAY_SIZE(roots))4559 }
4542 break;4560 /* grab all the search result for later use */
4561 gang[i] = btrfs_grab_root(gang[i]);
4543 }4562 }
4544 spin_unlock(&fs_info->fs_roots_lock);4563 spin_unlock(&fs_info->fs_roots_radix_lock);
4545 4564
4546 for (i = 0; i < grabbed; i++) {4565 for (i = 0; i < ret; i++) {
4547 if (!roots[i])4566 if (!gang[i])
4548 continue;4567 continue;
4549 index = roots[i]->root_key.objectid;4568 root_objectid = gang[i]->root_key.objectid;
4550 err = btrfs_orphan_cleanup(roots[i]);4569 err = btrfs_orphan_cleanup(gang[i]);
4551 if (err)4570 if (err)
4552 goto out;4571 break;
4553 btrfs_put_root(roots[i]);4572 btrfs_put_root(gang[i]);
4554 }4573 }
4555 index++;4574 root_objectid++;
4556 }4575 }
4557 4576
4558out:4577 /* release the uncleaned roots due to error */
4559 /* Release the roots that remain uncleaned due to error */4578 for (; i < ret; i++) {
4560 for (; i < grabbed; i++) {4579 if (gang[i])
4561 if (roots[i])4580 btrfs_put_root(gang[i]);
4562 btrfs_put_root(roots[i]);
4563 }4581 }
4564 return err;4582 return err;
4565}4583}
@@ -4878,28 +4896,31 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info) · 312 unmodified lines
4878 4896
4879static void btrfs_drop_all_logs(struct btrfs_fs_info *fs_info)4897static void btrfs_drop_all_logs(struct btrfs_fs_info *fs_info)
4880{4898{
4881 unsigned long index = 0;4899 struct btrfs_root *gang[8];
4882 int grabbed = 0;4900 u64 root_objectid = 0;
4883 struct btrfs_root *roots[8];4901 int ret;
4902
4903 spin_lock(&fs_info->fs_roots_radix_lock);
4904 while ((ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
4905 (void **)gang, root_objectid,
4906 ARRAY_SIZE(gang))) != 0) {
4907 int i;
4884 4908
4885 spin_lock(&fs_info->fs_roots_lock);4909 for (i = 0; i < ret; i++)
4886 while ((grabbed = xa_extract(&fs_info->fs_roots, (void **)roots, index,4910 gang[i] = btrfs_grab_root(gang[i]);
4887 ULONG_MAX, 8, XA_PRESENT))) {4911 spin_unlock(&fs_info->fs_roots_radix_lock);
4888 for (int i = 0; i < grabbed; i++)
4889 roots[i] = btrfs_grab_root(roots[i]);
4890 spin_unlock(&fs_info->fs_roots_lock);
4891 4912
4892 for (int i = 0; i < grabbed; i++) {4913 for (i = 0; i < ret; i++) {
4893 if (!roots[i])4914 if (!gang[i])
4894 continue;4915 continue;
4895 index = roots[i]->root_key.objectid;4916 root_objectid = gang[i]->root_key.objectid;
4896 btrfs_free_log(NULL, roots[i]);4917 btrfs_free_log(NULL, gang[i]);
4897 btrfs_put_root(roots[i]);4918 btrfs_put_root(gang[i]);
4898 }4919 }
4899 index++;4920 root_objectid++;
4900 spin_lock(&fs_info->fs_roots_lock);4921 spin_lock(&fs_info->fs_roots_radix_lock);
4901 }4922 }
4902 spin_unlock(&fs_info->fs_roots_lock);4923 spin_unlock(&fs_info->fs_roots_radix_lock);
4903 btrfs_free_log_root_tree(NULL, fs_info);4924 btrfs_free_log_root_tree(NULL, fs_info);
4904}4925}
4905 4926
fs/btrfs/extent-tree.c+1−1
@@ -5829,7 +5829,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc) · 5828 unmodified lines
5829 btrfs_qgroup_convert_reserved_meta(root, INT_MAX);5829 btrfs_qgroup_convert_reserved_meta(root, INT_MAX);
5830 btrfs_qgroup_free_meta_all_pertrans(root);5830 btrfs_qgroup_free_meta_all_pertrans(root);
5831 5831
5832 if (test_bit(BTRFS_ROOT_REGISTERED, &root->state))5832 if (test_bit(BTRFS_ROOT_IN_RADIX, &root->state))
5833 btrfs_add_dropped_root(trans, root);5833 btrfs_add_dropped_root(trans, root);
5834 else5834 else
5835 btrfs_put_root(root);5835 btrfs_put_root(root);
fs/btrfs/inode.c+6−7
@@ -3578,7 +3578,6 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) · 3577 unmodified lines
3578 u64 last_objectid = 0;3578 u64 last_objectid = 0;
3579 int ret = 0, nr_unlink = 0;3579 int ret = 0, nr_unlink = 0;
3580 3580
3581 /* Bail out if the cleanup is already running. */
3582 if (test_and_set_bit(BTRFS_ROOT_ORPHAN_CLEANUP, &root->state))3581 if (test_and_set_bit(BTRFS_ROOT_ORPHAN_CLEANUP, &root->state))
3583 return 0;3582 return 0;
3584 3583
@@ -3661,17 +3660,17 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) · 76 unmodified lines
3661 *3660 *
3662 * btrfs_find_orphan_roots() ran before us, which has3661 * btrfs_find_orphan_roots() ran before us, which has
3663 * found all deleted roots and loaded them into3662 * found all deleted roots and loaded them into
3664 * fs_info->fs_roots. So here we can find if an3663 * fs_info->fs_roots_radix. So here we can find if an
3665 * orphan item corresponds to a deleted root by looking3664 * orphan item corresponds to a deleted root by looking
3666 * up the root from that xarray.3665 * up the root from that radix tree.
3667 */3666 */
3668 3667
3669 spin_lock(&fs_info->fs_roots_lock);3668 spin_lock(&fs_info->fs_roots_radix_lock);
3670 dead_root = xa_load(&fs_info->fs_roots,3669 dead_root = radix_tree_lookup(&fs_info->fs_roots_radix,
3671 (unsigned long)found_key.objectid);3670 (unsigned long)found_key.objectid);
3672 if (dead_root && btrfs_root_refs(&dead_root->root_item) == 0)3671 if (dead_root && btrfs_root_refs(&dead_root->root_item) == 0)
3673 is_dead_root = 1;3672 is_dead_root = 1;
3674 spin_unlock(&fs_info->fs_roots_lock);3673 spin_unlock(&fs_info->fs_roots_radix_lock);
3675 3674
3676 if (is_dead_root) {3675 if (is_dead_root) {
3677 /* prevent this orphan from being found again */3676 /* prevent this orphan from being found again */
fs/btrfs/tests/btrfs-tests.c+1−1
@@ -186,7 +186,7 @@ void btrfs_free_dummy_root(struct btrfs_root *root) · 185 unmodified lines
186 if (!root)186 if (!root)
187 return;187 return;
188 /* Will be freed by btrfs_free_fs_roots */188 /* Will be freed by btrfs_free_fs_roots */
189 if (WARN_ON(test_bit(BTRFS_ROOT_REGISTERED, &root->state)))189 if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state)))
190 return;190 return;
191 btrfs_global_root_delete(root);191 btrfs_global_root_delete(root);
192 btrfs_put_root(root);192 btrfs_put_root(root);
fs/btrfs/transaction.c+63−49
@@ -23,7 +23,7 @@ · 22 unmodified lines
23#include "space-info.h"23#include "space-info.h"
24#include "zoned.h"24#include "zoned.h"
25 25
26#define BTRFS_ROOT_TRANS_TAG XA_MARK_026#define BTRFS_ROOT_TRANS_TAG 0
27 27
28/*28/*
29 * Transaction states and transitions29 * Transaction states and transitions
@@ -437,15 +437,15 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans, · 407 unmodified lines
437 */437 */
438 smp_wmb();438 smp_wmb();
439 439
440 spin_lock(&fs_info->fs_roots_lock);440 spin_lock(&fs_info->fs_roots_radix_lock);
441 if (root->last_trans == trans->transid && !force) {441 if (root->last_trans == trans->transid && !force) {
442 spin_unlock(&fs_info->fs_roots_lock);442 spin_unlock(&fs_info->fs_roots_radix_lock);
443 return 0;443 return 0;
444 }444 }
445 xa_set_mark(&fs_info->fs_roots,445 radix_tree_tag_set(&fs_info->fs_roots_radix,
446 (unsigned long)root->root_key.objectid,446 (unsigned long)root->root_key.objectid,
447 BTRFS_ROOT_TRANS_TAG);447 BTRFS_ROOT_TRANS_TAG);
448 spin_unlock(&fs_info->fs_roots_lock);448 spin_unlock(&fs_info->fs_roots_radix_lock);
449 root->last_trans = trans->transid;449 root->last_trans = trans->transid;
450 450
451 /* this is pretty tricky. We don't want to451 /* this is pretty tricky. We don't want to
@@ -487,9 +487,11 @@ void btrfs_add_dropped_root(struct btrfs_trans_handle *trans, · 35 unmodified lines
487 spin_unlock(&cur_trans->dropped_roots_lock);487 spin_unlock(&cur_trans->dropped_roots_lock);
488 488
489 /* Make sure we don't try to update the root at commit time */489 /* Make sure we don't try to update the root at commit time */
490 xa_clear_mark(&fs_info->fs_roots,490 spin_lock(&fs_info->fs_roots_radix_lock);
491 (unsigned long)root->root_key.objectid,491 radix_tree_tag_clear(&fs_info->fs_roots_radix,
492 BTRFS_ROOT_TRANS_TAG);492 (unsigned long)root->root_key.objectid,
493 BTRFS_ROOT_TRANS_TAG);
494 spin_unlock(&fs_info->fs_roots_radix_lock);
493}495}
494 496
495int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,497int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
@@ -1402,8 +1404,9 @@ void btrfs_add_dead_root(struct btrfs_root *root) · 906 unmodified lines
1402static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)1404static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
1403{1405{
1404 struct btrfs_fs_info *fs_info = trans->fs_info;1406 struct btrfs_fs_info *fs_info = trans->fs_info;
1405 struct btrfs_root *root;1407 struct btrfs_root *gang[8];
1406 unsigned long index;1408 int i;
1409 int ret;
1407 1410
1408 /*1411 /*
1409 * At this point no one can be using this transaction to modify any tree1412 * At this point no one can be using this transaction to modify any tree
@@ -1411,46 +1414,57 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans) · 1 unmodified line
1411 */1414 */
1412 ASSERT(trans->transaction->state == TRANS_STATE_COMMIT_DOING);1415 ASSERT(trans->transaction->state == TRANS_STATE_COMMIT_DOING);
1413 1416
1414 spin_lock(&fs_info->fs_roots_lock);1417 spin_lock(&fs_info->fs_roots_radix_lock);
1415 xa_for_each_marked(&fs_info->fs_roots, index, root, BTRFS_ROOT_TRANS_TAG) {1418 while (1) {
1416 int ret;1419 ret = radix_tree_gang_lookup_tag(&fs_info->fs_roots_radix,
1417 1420 (void **)gang, 0,
1418 /*1421 ARRAY_SIZE(gang),
1419 * At this point we can neither have tasks logging inodes1422 BTRFS_ROOT_TRANS_TAG);
1420 * from a root nor trying to commit a log tree.1423 if (ret == 0)
1421 */1424 break;
1422 ASSERT(atomic_read(&root->log_writers) == 0);1425 for (i = 0; i < ret; i++) {
1423 ASSERT(atomic_read(&root->log_commit[0]) == 0);1426 struct btrfs_root *root = gang[i];
1424 ASSERT(atomic_read(&root->log_commit[1]) == 0);1427 int ret2;
1425 1428
1426 xa_clear_mark(&fs_info->fs_roots,1429 /*
1427 (unsigned long)root->root_key.objectid,1430 * At this point we can neither have tasks logging inodes
1428 BTRFS_ROOT_TRANS_TAG);1431 * from a root nor trying to commit a log tree.
1429 spin_unlock(&fs_info->fs_roots_lock);1432 */
1430 1433 ASSERT(atomic_read(&root->log_writers) == 0);
1431 btrfs_free_log(trans, root);1434 ASSERT(atomic_read(&root->log_commit[0]) == 0);
1432 ret = btrfs_update_reloc_root(trans, root);1435 ASSERT(atomic_read(&root->log_commit[1]) == 0);
1433 if (ret)1436
1434 return ret;1437 radix_tree_tag_clear(&fs_info->fs_roots_radix,
1435 1438 (unsigned long)root->root_key.objectid,
1436 /* See comments in should_cow_block() */1439 BTRFS_ROOT_TRANS_TAG);
1437 clear_bit(BTRFS_ROOT_FORCE_COW, &root->state);1440 spin_unlock(&fs_info->fs_roots_radix_lock);
1438 smp_mb__after_atomic();1441
1442 btrfs_free_log(trans, root);
1443 ret2 = btrfs_update_reloc_root(trans, root);
1444 if (ret2)
1445 return ret2;
1446
1447 /* see comments in should_cow_block() */
1448 clear_bit(BTRFS_ROOT_FORCE_COW, &root->state);
1449 smp_mb__after_atomic();
1450
1451 if (root->commit_root != root->node) {
1452 list_add_tail(&root->dirty_list,
1453 &trans->transaction->switch_commits);
1454 btrfs_set_root_node(&root->root_item,
1455 root->node);
1456 }
1439 1457
1440 if (root->commit_root != root->node) {1458 ret2 = btrfs_update_root(trans, fs_info->tree_root,
1441 list_add_tail(&root->dirty_list,1459 &root->root_key,
1442 &trans->transaction->switch_commits);1460 &root->root_item);
1443 btrfs_set_root_node(&root->root_item, root->node);1461 if (ret2)
1462 return ret2;
1463 spin_lock(&fs_info->fs_roots_radix_lock);
1464 btrfs_qgroup_free_meta_all_pertrans(root);
1444 }1465 }
1445
1446 ret = btrfs_update_root(trans, fs_info->tree_root,
1447 &root->root_key, &root->root_item);
1448 if (ret)
1449 return ret;
1450 spin_lock(&fs_info->fs_roots_lock);
1451 btrfs_qgroup_free_meta_all_pertrans(root);
1452 }1466 }
1453 spin_unlock(&fs_info->fs_roots_lock);1467 spin_unlock(&fs_info->fs_roots_radix_lock);
1454 return 0;1468 return 0;
1455}1469}
1456 1470