@@ -2966,7 +2966,7 @@ static void begin_page_read(struct btrfs_fs_info *fs_info, struct page *page)
2966
2966
}
2967
2967
2968
2968
/*
2969
- * Find extent buffer for a given bytenr.
2969
+ * Find extent buffer for a givne bytenr.
2970
2970
*
2971
2971
* This is for end_bio_extent_readpage(), thus we can't do any unsafe locking
2972
2972
* in endio context.
@@ -2985,9 +2985,11 @@ static struct extent_buffer *find_extent_buffer_readpage(
2985
2985
return (struct extent_buffer * )page -> private ;
2986
2986
}
2987
2987
2988
- /* For subpage case, we need to lookup extent buffer xarray */
2989
- eb = xa_load (& fs_info -> extent_buffers ,
2990
- bytenr >> fs_info -> sectorsize_bits );
2988
+ /* For subpage case, we need to lookup buffer radix tree */
2989
+ rcu_read_lock ();
2990
+ eb = radix_tree_lookup (& fs_info -> buffer_radix ,
2991
+ bytenr >> fs_info -> sectorsize_bits );
2992
+ rcu_read_unlock ();
2991
2993
ASSERT (eb );
2992
2994
return eb ;
2993
2995
}
@@ -4434,8 +4436,8 @@ static struct extent_buffer *find_extent_buffer_nolock(
4434
4436
struct extent_buffer * eb ;
4435
4437
4436
4438
rcu_read_lock ();
4437
- eb = xa_load (& fs_info -> extent_buffers ,
4438
- start >> fs_info -> sectorsize_bits );
4439
+ eb = radix_tree_lookup (& fs_info -> buffer_radix ,
4440
+ start >> fs_info -> sectorsize_bits );
4439
4441
if (eb && atomic_inc_not_zero (& eb -> refs )) {
4440
4442
rcu_read_unlock ();
4441
4443
return eb ;
@@ -6128,22 +6130,24 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
6128
6130
if (!eb )
6129
6131
return ERR_PTR (- ENOMEM );
6130
6132
eb -> fs_info = fs_info ;
6131
-
6132
- do {
6133
- ret = xa_insert (& fs_info -> extent_buffers ,
6134
- start >> fs_info -> sectorsize_bits ,
6135
- eb , GFP_NOFS );
6136
- if (ret == - ENOMEM ) {
6137
- exists = ERR_PTR (ret );
6133
+ again :
6134
+ ret = radix_tree_preload (GFP_NOFS );
6135
+ if (ret ) {
6136
+ exists = ERR_PTR (ret );
6137
+ goto free_eb ;
6138
+ }
6139
+ spin_lock (& fs_info -> buffer_lock );
6140
+ ret = radix_tree_insert (& fs_info -> buffer_radix ,
6141
+ start >> fs_info -> sectorsize_bits , eb );
6142
+ spin_unlock (& fs_info -> buffer_lock );
6143
+ radix_tree_preload_end ();
6144
+ if (ret == - EEXIST ) {
6145
+ exists = find_extent_buffer (fs_info , start );
6146
+ if (exists )
6138
6147
goto free_eb ;
6139
- }
6140
- if (ret == - EBUSY ) {
6141
- exists = find_extent_buffer (fs_info , start );
6142
- if (exists )
6143
- goto free_eb ;
6144
- }
6145
- } while (ret );
6146
-
6148
+ else
6149
+ goto again ;
6150
+ }
6147
6151
check_buffer_tree_ref (eb );
6148
6152
set_bit (EXTENT_BUFFER_IN_TREE , & eb -> bflags );
6149
6153
@@ -6318,22 +6322,25 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
6318
6322
}
6319
6323
if (uptodate )
6320
6324
set_bit (EXTENT_BUFFER_UPTODATE , & eb -> bflags );
6321
-
6322
- do {
6323
- ret = xa_insert (& fs_info -> extent_buffers ,
6324
- start >> fs_info -> sectorsize_bits ,
6325
- eb , GFP_NOFS );
6326
- if (ret == - ENOMEM ) {
6327
- exists = ERR_PTR (ret );
6325
+ again :
6326
+ ret = radix_tree_preload (GFP_NOFS );
6327
+ if (ret ) {
6328
+ exists = ERR_PTR (ret );
6329
+ goto free_eb ;
6330
+ }
6331
+
6332
+ spin_lock (& fs_info -> buffer_lock );
6333
+ ret = radix_tree_insert (& fs_info -> buffer_radix ,
6334
+ start >> fs_info -> sectorsize_bits , eb );
6335
+ spin_unlock (& fs_info -> buffer_lock );
6336
+ radix_tree_preload_end ();
6337
+ if (ret == - EEXIST ) {
6338
+ exists = find_extent_buffer (fs_info , start );
6339
+ if (exists )
6328
6340
goto free_eb ;
6329
- }
6330
- if (ret == - EBUSY ) {
6331
- exists = find_extent_buffer (fs_info , start );
6332
- if (exists )
6333
- goto free_eb ;
6334
- }
6335
- } while (ret );
6336
-
6341
+ else
6342
+ goto again ;
6343
+ }
6337
6344
/* add one reference for the tree */
6338
6345
check_buffer_tree_ref (eb );
6339
6346
set_bit (EXTENT_BUFFER_IN_TREE , & eb -> bflags );
@@ -6378,8 +6385,10 @@ static int release_extent_buffer(struct extent_buffer *eb)
6378
6385
6379
6386
spin_unlock (& eb -> refs_lock );
6380
6387
6381
- xa_erase (& fs_info -> extent_buffers ,
6382
- eb -> start >> fs_info -> sectorsize_bits );
6388
+ spin_lock (& fs_info -> buffer_lock );
6389
+ radix_tree_delete (& fs_info -> buffer_radix ,
6390
+ eb -> start >> fs_info -> sectorsize_bits );
6391
+ spin_unlock (& fs_info -> buffer_lock );
6383
6392
} else {
6384
6393
spin_unlock (& eb -> refs_lock );
6385
6394
}
@@ -7324,25 +7333,42 @@ void memmove_extent_buffer(const struct extent_buffer *dst,
7324
7333
}
7325
7334
}
7326
7335
7336
+ #define GANG_LOOKUP_SIZE 16
7327
7337
static struct extent_buffer * get_next_extent_buffer (
7328
7338
struct btrfs_fs_info * fs_info , struct page * page , u64 bytenr )
7329
7339
{
7330
- struct extent_buffer * eb ;
7331
- unsigned long index ;
7340
+ struct extent_buffer * gang [ GANG_LOOKUP_SIZE ] ;
7341
+ struct extent_buffer * found = NULL ;
7332
7342
u64 page_start = page_offset (page );
7343
+ u64 cur = page_start ;
7333
7344
7334
7345
ASSERT (in_range (bytenr , page_start , PAGE_SIZE ));
7335
7346
lockdep_assert_held (& fs_info -> buffer_lock );
7336
7347
7337
- xa_for_each_start (& fs_info -> extent_buffers , index , eb ,
7338
- page_start >> fs_info -> sectorsize_bits ) {
7339
- if (in_range (eb -> start , page_start , PAGE_SIZE ))
7340
- return eb ;
7341
- else if (eb -> start >= page_start + PAGE_SIZE )
7342
- /* Already beyond page end */
7343
- return NULL ;
7348
+ while (cur < page_start + PAGE_SIZE ) {
7349
+ int ret ;
7350
+ int i ;
7351
+
7352
+ ret = radix_tree_gang_lookup (& fs_info -> buffer_radix ,
7353
+ (void * * )gang , cur >> fs_info -> sectorsize_bits ,
7354
+ min_t (unsigned int , GANG_LOOKUP_SIZE ,
7355
+ PAGE_SIZE / fs_info -> nodesize ));
7356
+ if (ret == 0 )
7357
+ goto out ;
7358
+ for (i = 0 ; i < ret ; i ++ ) {
7359
+ /* Already beyond page end */
7360
+ if (gang [i ]-> start >= page_start + PAGE_SIZE )
7361
+ goto out ;
7362
+ /* Found one */
7363
+ if (gang [i ]-> start >= bytenr ) {
7364
+ found = gang [i ];
7365
+ goto out ;
7366
+ }
7367
+ }
7368
+ cur = gang [ret - 1 ]-> start + gang [ret - 1 ]-> len ;
7344
7369
}
7345
- return NULL ;
7370
+ out :
7371
+ return found ;
7346
7372
}
7347
7373
7348
7374
static int try_release_subpage_extent_buffer (struct page * page )
0 commit comments