@@ -2356,7 +2356,7 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
2356
2356
{
2357
2357
struct ext4_sb_info * sbi = EXT4_SB (sb );
2358
2358
unsigned size ;
2359
- struct ext4_group_info * * * new_groupinfo ;
2359
+ struct ext4_group_info * * * old_groupinfo , * * * new_groupinfo ;
2360
2360
2361
2361
size = (ngroups + EXT4_DESC_PER_BLOCK (sb ) - 1 ) >>
2362
2362
EXT4_DESC_PER_BLOCK_BITS (sb );
@@ -2369,13 +2369,16 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
2369
2369
ext4_msg (sb , KERN_ERR , "can't allocate buddy meta group" );
2370
2370
return - ENOMEM ;
2371
2371
}
2372
- if (sbi -> s_group_info ) {
2373
- memcpy (new_groupinfo , sbi -> s_group_info ,
2372
+ rcu_read_lock ();
2373
+ old_groupinfo = rcu_dereference (sbi -> s_group_info );
2374
+ if (old_groupinfo )
2375
+ memcpy (new_groupinfo , old_groupinfo ,
2374
2376
sbi -> s_group_info_size * sizeof (* sbi -> s_group_info ));
2375
- kvfree (sbi -> s_group_info );
2376
- }
2377
- sbi -> s_group_info = new_groupinfo ;
2377
+ rcu_read_unlock ();
2378
+ rcu_assign_pointer (sbi -> s_group_info , new_groupinfo );
2378
2379
sbi -> s_group_info_size = size / sizeof (* sbi -> s_group_info );
2380
+ if (old_groupinfo )
2381
+ ext4_kvfree_array_rcu (old_groupinfo );
2379
2382
ext4_debug ("allocated s_groupinfo array for %d meta_bg's\n" ,
2380
2383
sbi -> s_group_info_size );
2381
2384
return 0 ;
@@ -2387,6 +2390,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
2387
2390
{
2388
2391
int i ;
2389
2392
int metalen = 0 ;
2393
+ int idx = group >> EXT4_DESC_PER_BLOCK_BITS (sb );
2390
2394
struct ext4_sb_info * sbi = EXT4_SB (sb );
2391
2395
struct ext4_group_info * * meta_group_info ;
2392
2396
struct kmem_cache * cachep = get_groupinfo_cache (sb -> s_blocksize_bits );
@@ -2405,12 +2409,12 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
2405
2409
"for a buddy group" );
2406
2410
goto exit_meta_group_info ;
2407
2411
}
2408
- sbi -> s_group_info [group >> EXT4_DESC_PER_BLOCK_BITS (sb )] =
2409
- meta_group_info ;
2412
+ rcu_read_lock ();
2413
+ rcu_dereference (sbi -> s_group_info )[idx ] = meta_group_info ;
2414
+ rcu_read_unlock ();
2410
2415
}
2411
2416
2412
- meta_group_info =
2413
- sbi -> s_group_info [group >> EXT4_DESC_PER_BLOCK_BITS (sb )];
2417
+ meta_group_info = sbi_array_rcu_deref (sbi , s_group_info , idx );
2414
2418
i = group & (EXT4_DESC_PER_BLOCK (sb ) - 1 );
2415
2419
2416
2420
meta_group_info [i ] = kmem_cache_zalloc (cachep , GFP_NOFS );
@@ -2458,8 +2462,13 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
2458
2462
exit_group_info :
2459
2463
/* If a meta_group_info table has been allocated, release it now */
2460
2464
if (group % EXT4_DESC_PER_BLOCK (sb ) == 0 ) {
2461
- kfree (sbi -> s_group_info [group >> EXT4_DESC_PER_BLOCK_BITS (sb )]);
2462
- sbi -> s_group_info [group >> EXT4_DESC_PER_BLOCK_BITS (sb )] = NULL ;
2465
+ struct ext4_group_info * * * group_info ;
2466
+
2467
+ rcu_read_lock ();
2468
+ group_info = rcu_dereference (sbi -> s_group_info );
2469
+ kfree (group_info [idx ]);
2470
+ group_info [idx ] = NULL ;
2471
+ rcu_read_unlock ();
2463
2472
}
2464
2473
exit_meta_group_info :
2465
2474
return - ENOMEM ;
@@ -2472,6 +2481,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
2472
2481
struct ext4_sb_info * sbi = EXT4_SB (sb );
2473
2482
int err ;
2474
2483
struct ext4_group_desc * desc ;
2484
+ struct ext4_group_info * * * group_info ;
2475
2485
struct kmem_cache * cachep ;
2476
2486
2477
2487
err = ext4_mb_alloc_groupinfo (sb , ngroups );
@@ -2507,11 +2517,16 @@ static int ext4_mb_init_backend(struct super_block *sb)
2507
2517
while (i -- > 0 )
2508
2518
kmem_cache_free (cachep , ext4_get_group_info (sb , i ));
2509
2519
i = sbi -> s_group_info_size ;
2520
+ rcu_read_lock ();
2521
+ group_info = rcu_dereference (sbi -> s_group_info );
2510
2522
while (i -- > 0 )
2511
- kfree (sbi -> s_group_info [i ]);
2523
+ kfree (group_info [i ]);
2524
+ rcu_read_unlock ();
2512
2525
iput (sbi -> s_buddy_cache );
2513
2526
err_freesgi :
2514
- kvfree (sbi -> s_group_info );
2527
+ rcu_read_lock ();
2528
+ kvfree (rcu_dereference (sbi -> s_group_info ));
2529
+ rcu_read_unlock ();
2515
2530
return - ENOMEM ;
2516
2531
}
2517
2532
@@ -2700,7 +2715,7 @@ int ext4_mb_release(struct super_block *sb)
2700
2715
ext4_group_t ngroups = ext4_get_groups_count (sb );
2701
2716
ext4_group_t i ;
2702
2717
int num_meta_group_infos ;
2703
- struct ext4_group_info * grinfo ;
2718
+ struct ext4_group_info * grinfo , * * * group_info ;
2704
2719
struct ext4_sb_info * sbi = EXT4_SB (sb );
2705
2720
struct kmem_cache * cachep = get_groupinfo_cache (sb -> s_blocksize_bits );
2706
2721
@@ -2719,9 +2734,12 @@ int ext4_mb_release(struct super_block *sb)
2719
2734
num_meta_group_infos = (ngroups +
2720
2735
EXT4_DESC_PER_BLOCK (sb ) - 1 ) >>
2721
2736
EXT4_DESC_PER_BLOCK_BITS (sb );
2737
+ rcu_read_lock ();
2738
+ group_info = rcu_dereference (sbi -> s_group_info );
2722
2739
for (i = 0 ; i < num_meta_group_infos ; i ++ )
2723
- kfree (sbi -> s_group_info [i ]);
2724
- kvfree (sbi -> s_group_info );
2740
+ kfree (group_info [i ]);
2741
+ kvfree (group_info );
2742
+ rcu_read_unlock ();
2725
2743
}
2726
2744
kfree (sbi -> s_mb_offsets );
2727
2745
kfree (sbi -> s_mb_maxs );
0 commit comments