@@ -1015,6 +1015,7 @@ static void ext4_put_super(struct super_block *sb)
1015
1015
struct ext4_sb_info * sbi = EXT4_SB (sb );
1016
1016
struct ext4_super_block * es = sbi -> s_es ;
1017
1017
struct buffer_head * * group_desc ;
1018
+ struct flex_groups * * flex_groups ;
1018
1019
int aborted = 0 ;
1019
1020
int i , err ;
1020
1021
@@ -1052,8 +1053,13 @@ static void ext4_put_super(struct super_block *sb)
1052
1053
for (i = 0 ; i < sbi -> s_gdb_count ; i ++ )
1053
1054
brelse (group_desc [i ]);
1054
1055
kvfree (group_desc );
1056
+ flex_groups = rcu_dereference (sbi -> s_flex_groups );
1057
+ if (flex_groups ) {
1058
+ for (i = 0 ; i < sbi -> s_flex_groups_allocated ; i ++ )
1059
+ kvfree (flex_groups [i ]);
1060
+ kvfree (flex_groups );
1061
+ }
1055
1062
rcu_read_unlock ();
1056
- kvfree (sbi -> s_flex_groups );
1057
1063
percpu_counter_destroy (& sbi -> s_freeclusters_counter );
1058
1064
percpu_counter_destroy (& sbi -> s_freeinodes_counter );
1059
1065
percpu_counter_destroy (& sbi -> s_dirs_counter );
@@ -2384,8 +2390,8 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
2384
2390
int ext4_alloc_flex_bg_array (struct super_block * sb , ext4_group_t ngroup )
2385
2391
{
2386
2392
struct ext4_sb_info * sbi = EXT4_SB (sb );
2387
- struct flex_groups * new_groups ;
2388
- int size ;
2393
+ struct flex_groups * * old_groups , * * new_groups ;
2394
+ int size , i ;
2389
2395
2390
2396
if (!sbi -> s_log_groups_per_flex )
2391
2397
return 0 ;
@@ -2394,29 +2400,45 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
2394
2400
if (size <= sbi -> s_flex_groups_allocated )
2395
2401
return 0 ;
2396
2402
2397
- size = roundup_pow_of_two (size * sizeof ( struct flex_groups ));
2398
- new_groups = kvzalloc ( size , GFP_KERNEL );
2403
+ new_groups = kvzalloc ( roundup_pow_of_two (size *
2404
+ sizeof ( * sbi -> s_flex_groups )) , GFP_KERNEL );
2399
2405
if (!new_groups ) {
2400
- ext4_msg (sb , KERN_ERR , "not enough memory for %d flex groups" ,
2401
- size / ( int ) sizeof ( struct flex_groups ) );
2406
+ ext4_msg (sb , KERN_ERR ,
2407
+ "not enough memory for %d flex group pointers" , size );
2402
2408
return - ENOMEM ;
2403
2409
}
2404
-
2405
- if (sbi -> s_flex_groups ) {
2406
- memcpy (new_groups , sbi -> s_flex_groups ,
2407
- (sbi -> s_flex_groups_allocated *
2408
- sizeof (struct flex_groups )));
2409
- kvfree (sbi -> s_flex_groups );
2410
+ for (i = sbi -> s_flex_groups_allocated ; i < size ; i ++ ) {
2411
+ new_groups [i ] = kvzalloc (roundup_pow_of_two (
2412
+ sizeof (struct flex_groups )),
2413
+ GFP_KERNEL );
2414
+ if (!new_groups [i ]) {
2415
+ for (i -- ; i >= sbi -> s_flex_groups_allocated ; i -- )
2416
+ kvfree (new_groups [i ]);
2417
+ kvfree (new_groups );
2418
+ ext4_msg (sb , KERN_ERR ,
2419
+ "not enough memory for %d flex groups" , size );
2420
+ return - ENOMEM ;
2421
+ }
2410
2422
}
2411
- sbi -> s_flex_groups = new_groups ;
2412
- sbi -> s_flex_groups_allocated = size / sizeof (struct flex_groups );
2423
+ rcu_read_lock ();
2424
+ old_groups = rcu_dereference (sbi -> s_flex_groups );
2425
+ if (old_groups )
2426
+ memcpy (new_groups , old_groups ,
2427
+ (sbi -> s_flex_groups_allocated *
2428
+ sizeof (struct flex_groups * )));
2429
+ rcu_read_unlock ();
2430
+ rcu_assign_pointer (sbi -> s_flex_groups , new_groups );
2431
+ sbi -> s_flex_groups_allocated = size ;
2432
+ if (old_groups )
2433
+ ext4_kvfree_array_rcu (old_groups );
2413
2434
return 0 ;
2414
2435
}
2415
2436
2416
2437
static int ext4_fill_flex_info (struct super_block * sb )
2417
2438
{
2418
2439
struct ext4_sb_info * sbi = EXT4_SB (sb );
2419
2440
struct ext4_group_desc * gdp = NULL ;
2441
+ struct flex_groups * fg ;
2420
2442
ext4_group_t flex_group ;
2421
2443
int i , err ;
2422
2444
@@ -2434,12 +2456,11 @@ static int ext4_fill_flex_info(struct super_block *sb)
2434
2456
gdp = ext4_get_group_desc (sb , i , NULL );
2435
2457
2436
2458
flex_group = ext4_flex_group (sbi , i );
2437
- atomic_add ( ext4_free_inodes_count ( sb , gdp ),
2438
- & sbi -> s_flex_groups [ flex_group ]. free_inodes );
2459
+ fg = sbi_array_rcu_deref ( sbi , s_flex_groups , flex_group );
2460
+ atomic_add ( ext4_free_inodes_count ( sb , gdp ), & fg -> free_inodes );
2439
2461
atomic64_add (ext4_free_group_clusters (sb , gdp ),
2440
- & sbi -> s_flex_groups [flex_group ].free_clusters );
2441
- atomic_add (ext4_used_dirs_count (sb , gdp ),
2442
- & sbi -> s_flex_groups [flex_group ].used_dirs );
2462
+ & fg -> free_clusters );
2463
+ atomic_add (ext4_used_dirs_count (sb , gdp ), & fg -> used_dirs );
2443
2464
}
2444
2465
2445
2466
return 1 ;
@@ -3641,6 +3662,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3641
3662
struct buffer_head * bh , * * group_desc ;
3642
3663
struct ext4_super_block * es = NULL ;
3643
3664
struct ext4_sb_info * sbi = kzalloc (sizeof (* sbi ), GFP_KERNEL );
3665
+ struct flex_groups * * flex_groups ;
3644
3666
ext4_fsblk_t block ;
3645
3667
ext4_fsblk_t sb_block = get_sb_block (& data );
3646
3668
ext4_fsblk_t logical_sb_block ;
@@ -4692,8 +4714,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
4692
4714
ext4_unregister_li_request (sb );
4693
4715
failed_mount6 :
4694
4716
ext4_mb_release (sb );
4695
- if (sbi -> s_flex_groups )
4696
- kvfree (sbi -> s_flex_groups );
4717
+ rcu_read_lock ();
4718
+ flex_groups = rcu_dereference (sbi -> s_flex_groups );
4719
+ if (flex_groups ) {
4720
+ for (i = 0 ; i < sbi -> s_flex_groups_allocated ; i ++ )
4721
+ kvfree (flex_groups [i ]);
4722
+ kvfree (flex_groups );
4723
+ }
4724
+ rcu_read_unlock ();
4697
4725
percpu_counter_destroy (& sbi -> s_freeclusters_counter );
4698
4726
percpu_counter_destroy (& sbi -> s_freeinodes_counter );
4699
4727
percpu_counter_destroy (& sbi -> s_dirs_counter );
0 commit comments