55
66#include <linux/fs.h>
77#include <linux/blkdev.h>
8+ #include <linux/radix-tree.h>
89#include <linux/writeback.h>
910#include <linux/workqueue.h>
1011#include <linux/kthread.h>
@@ -1210,9 +1211,9 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
12101211 btrfs_qgroup_init_swapped_blocks (& root -> swapped_blocks );
12111212#ifdef CONFIG_BTRFS_DEBUG
12121213 INIT_LIST_HEAD (& root -> leak_list );
1213- spin_lock (& fs_info -> fs_roots_lock );
1214+ spin_lock (& fs_info -> fs_roots_radix_lock );
12141215 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 );
12161217#endif
12171218}
12181219
@@ -1659,11 +1660,12 @@ static struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
16591660{
16601661 struct btrfs_root * root ;
16611662
1662- spin_lock (& fs_info -> fs_roots_lock );
1663- root = xa_load (& fs_info -> fs_roots , (unsigned long )root_id );
1663+ spin_lock (& fs_info -> fs_roots_radix_lock );
1664+ root = radix_tree_lookup (& fs_info -> fs_roots_radix ,
1665+ (unsigned long )root_id );
16641666 if (root )
16651667 root = btrfs_grab_root (root );
1666- spin_unlock (& fs_info -> fs_roots_lock );
1668+ spin_unlock (& fs_info -> fs_roots_radix_lock );
16671669 return root ;
16681670}
16691671
@@ -1705,14 +1707,20 @@ int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
17051707{
17061708 int ret ;
17071709
1708- spin_lock (& fs_info -> fs_roots_lock );
1709- ret = xa_insert (& fs_info -> fs_roots , (unsigned long )root -> root_key .objectid ,
1710- root , GFP_NOFS );
1710+ ret = radix_tree_preload (GFP_NOFS );
1711+ if (ret )
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 );
17111718 if (ret == 0 ) {
17121719 btrfs_grab_root (root );
1713- set_bit (BTRFS_ROOT_REGISTERED , & root -> state );
1720+ set_bit (BTRFS_ROOT_IN_RADIX , & root -> state );
17141721 }
1715- spin_unlock (& fs_info -> fs_roots_lock );
1722+ spin_unlock (& fs_info -> fs_roots_radix_lock );
1723+ radix_tree_preload_end ();
17161724
17171725 return ret ;
17181726}
@@ -2342,31 +2350,38 @@ void btrfs_put_root(struct btrfs_root *root)
23422350 btrfs_drew_lock_destroy (& root -> snapshot_lock );
23432351 free_root_extent_buffers (root );
23442352#ifdef CONFIG_BTRFS_DEBUG
2345- spin_lock (& root -> fs_info -> fs_roots_lock );
2353+ spin_lock (& root -> fs_info -> fs_roots_radix_lock );
23462354 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 );
23482356#endif
23492357 kfree (root );
23502358 }
23512359}
23522360
23532361void btrfs_free_fs_roots (struct btrfs_fs_info * fs_info )
23542362{
2355- struct btrfs_root * root ;
2356- unsigned long index = 0 ;
2363+ int ret ;
2364+ struct btrfs_root * gang [8 ];
2365+ int i ;
23572366
23582367 while (!list_empty (& fs_info -> dead_roots )) {
2359- root = list_entry (fs_info -> dead_roots .next ,
2360- struct btrfs_root , root_list );
2361- list_del (& root -> root_list );
2368+ gang [ 0 ] = list_entry (fs_info -> dead_roots .next ,
2369+ struct btrfs_root , root_list );
2370+ list_del (& gang [ 0 ] -> root_list );
23622371
2363- if (test_bit (BTRFS_ROOT_REGISTERED , & root -> state ))
2364- btrfs_drop_and_free_fs_root (fs_info , root );
2365- btrfs_put_root (root );
2372+ if (test_bit (BTRFS_ROOT_IN_RADIX , & gang [ 0 ] -> state ))
2373+ btrfs_drop_and_free_fs_root (fs_info , gang [ 0 ] );
2374+ btrfs_put_root (gang [ 0 ] );
23662375 }
23672376
2368- xa_for_each (& fs_info -> fs_roots , index , root ) {
2369- btrfs_drop_and_free_fs_root (fs_info , root );
2377+ while (1 ) {
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 ]);
23702385 }
23712386}
23722387
@@ -3134,7 +3149,7 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
31343149
31353150void btrfs_init_fs_info (struct btrfs_fs_info * fs_info )
31363151{
3137- xa_init_flags (& fs_info -> fs_roots , GFP_ATOMIC );
3152+ INIT_RADIX_TREE (& fs_info -> fs_roots_radix , GFP_ATOMIC );
31383153 xa_init_flags (& fs_info -> extent_buffers , GFP_ATOMIC );
31393154 INIT_LIST_HEAD (& fs_info -> trans_list );
31403155 INIT_LIST_HEAD (& fs_info -> dead_roots );
@@ -3143,7 +3158,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
31433158 INIT_LIST_HEAD (& fs_info -> caching_block_groups );
31443159 spin_lock_init (& fs_info -> delalloc_root_lock );
31453160 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 );
31473162 spin_lock_init (& fs_info -> delayed_iput_lock );
31483163 spin_lock_init (& fs_info -> defrag_inodes_lock );
31493164 spin_lock_init (& fs_info -> super_lock );
@@ -3374,7 +3389,7 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
33743389 /*
33753390 * btrfs_find_orphan_roots() is responsible for finding all the dead
33763391 * 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 before
3392+ * them into the fs_info->fs_roots_radix tree . This must be done before
33783393 * calling btrfs_orphan_cleanup() on the tree root. If we don't do it
33793394 * first, then btrfs_orphan_cleanup() will delete a dead root's orphan
33803395 * 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,
44984513{
44994514 bool drop_ref = false;
45004515
4501- spin_lock (& fs_info -> fs_roots_lock );
4502- xa_erase (& fs_info -> fs_roots , (unsigned long )root -> root_key .objectid );
4503- if (test_and_clear_bit (BTRFS_ROOT_REGISTERED , & root -> state ))
4516+ spin_lock (& fs_info -> fs_roots_radix_lock );
4517+ radix_tree_delete (& fs_info -> fs_roots_radix ,
4518+ (unsigned long )root -> root_key .objectid );
4519+ if (test_and_clear_bit (BTRFS_ROOT_IN_RADIX , & root -> state ))
45044520 drop_ref = true;
4505- spin_unlock (& fs_info -> fs_roots_lock );
4521+ spin_unlock (& fs_info -> fs_roots_radix_lock );
45064522
45074523 if (BTRFS_FS_ERROR (fs_info )) {
45084524 ASSERT (root -> log_root == NULL );
@@ -4518,48 +4534,50 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
45184534
45194535int btrfs_cleanup_fs_roots (struct btrfs_fs_info * fs_info )
45204536{
4521- struct btrfs_root * roots [ 8 ] ;
4522- unsigned long index = 0 ;
4523- int i ;
4537+ u64 root_objectid = 0 ;
4538+ struct btrfs_root * gang [ 8 ] ;
4539+ int i = 0 ;
45244540 int err = 0 ;
4525- int grabbed ;
4541+ unsigned int ret = 0 ;
45264542
45274543 while (1 ) {
4528- struct btrfs_root * root ;
4529-
4530- spin_lock (& fs_info -> fs_roots_lock );
4531- if (!xa_find (& fs_info -> fs_roots , & index , ULONG_MAX , XA_PRESENT )) {
4532- spin_unlock (& fs_info -> fs_roots_lock );
4533- return err ;
4544+ spin_lock (& fs_info -> fs_roots_radix_lock );
4545+ ret = radix_tree_gang_lookup (& fs_info -> fs_roots_radix ,
4546+ (void * * )gang , root_objectid ,
4547+ ARRAY_SIZE (gang ));
4548+ if (!ret ) {
4549+ spin_unlock (& fs_info -> fs_roots_radix_lock );
4550+ break ;
45344551 }
4552+ root_objectid = gang [ret - 1 ]-> root_key .objectid + 1 ;
45354553
4536- grabbed = 0 ;
4537- xa_for_each_start (& fs_info -> fs_roots , index , root , index ) {
4538- /* Avoid grabbing roots in dead_roots */
4539- if (btrfs_root_refs (& root -> root_item ) > 0 )
4540- roots [grabbed ++ ] = btrfs_grab_root (root );
4541- if (grabbed >= ARRAY_SIZE (roots ))
4542- break ;
4554+ for (i = 0 ; i < ret ; i ++ ) {
4555+ /* Avoid to grab roots in dead_roots */
4556+ if (btrfs_root_refs (& gang [i ]-> root_item ) == 0 ) {
4557+ gang [i ] = NULL ;
4558+ continue ;
4559+ }
4560+ /* grab all the search result for later use */
4561+ gang [i ] = btrfs_grab_root (gang [i ]);
45434562 }
4544- spin_unlock (& fs_info -> fs_roots_lock );
4563+ spin_unlock (& fs_info -> fs_roots_radix_lock );
45454564
4546- for (i = 0 ; i < grabbed ; i ++ ) {
4547- if (!roots [i ])
4565+ for (i = 0 ; i < ret ; i ++ ) {
4566+ if (!gang [i ])
45484567 continue ;
4549- index = roots [i ]-> root_key .objectid ;
4550- err = btrfs_orphan_cleanup (roots [i ]);
4568+ root_objectid = gang [i ]-> root_key .objectid ;
4569+ err = btrfs_orphan_cleanup (gang [i ]);
45514570 if (err )
4552- goto out ;
4553- btrfs_put_root (roots [i ]);
4571+ break ;
4572+ btrfs_put_root (gang [i ]);
45544573 }
4555- index ++ ;
4574+ root_objectid ++ ;
45564575 }
45574576
4558- out :
4559- /* Release the roots that remain uncleaned due to error */
4560- for (; i < grabbed ; i ++ ) {
4561- if (roots [i ])
4562- btrfs_put_root (roots [i ]);
4577+ /* release the uncleaned roots due to error */
4578+ for (; i < ret ; i ++ ) {
4579+ if (gang [i ])
4580+ btrfs_put_root (gang [i ]);
45634581 }
45644582 return err ;
45654583}
@@ -4878,28 +4896,31 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info)
48784896
48794897static void btrfs_drop_all_logs (struct btrfs_fs_info * fs_info )
48804898{
4881- unsigned long index = 0 ;
4882- int grabbed = 0 ;
4883- struct btrfs_root * roots [8 ];
4899+ struct btrfs_root * gang [8 ];
4900+ u64 root_objectid = 0 ;
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 ;
48844908
4885- spin_lock (& fs_info -> fs_roots_lock );
4886- while ((grabbed = xa_extract (& fs_info -> fs_roots , (void * * )roots , index ,
4887- ULONG_MAX , 8 , XA_PRESENT ))) {
4888- for (int i = 0 ; i < grabbed ; i ++ )
4889- roots [i ] = btrfs_grab_root (roots [i ]);
4890- spin_unlock (& fs_info -> fs_roots_lock );
4909+ for (i = 0 ; i < ret ; i ++ )
4910+ gang [i ] = btrfs_grab_root (gang [i ]);
4911+ spin_unlock (& fs_info -> fs_roots_radix_lock );
48914912
4892- for (int i = 0 ; i < grabbed ; i ++ ) {
4893- if (!roots [i ])
4913+ for (i = 0 ; i < ret ; i ++ ) {
4914+ if (!gang [i ])
48944915 continue ;
4895- index = roots [i ]-> root_key .objectid ;
4896- btrfs_free_log (NULL , roots [i ]);
4897- btrfs_put_root (roots [i ]);
4916+ root_objectid = gang [i ]-> root_key .objectid ;
4917+ btrfs_free_log (NULL , gang [i ]);
4918+ btrfs_put_root (gang [i ]);
48984919 }
4899- index ++ ;
4900- spin_lock (& fs_info -> fs_roots_lock );
4920+ root_objectid ++ ;
4921+ spin_lock (& fs_info -> fs_roots_radix_lock );
49014922 }
4902- spin_unlock (& fs_info -> fs_roots_lock );
4923+ spin_unlock (& fs_info -> fs_roots_radix_lock );
49034924 btrfs_free_log_root_tree (NULL , fs_info );
49044925}
49054926
0 commit comments