17
17
18
18
#include "ext4_jbd2.h"
19
19
20
+ struct ext4_rcu_ptr {
21
+ struct rcu_head rcu ;
22
+ void * ptr ;
23
+ };
24
+
25
+ static void ext4_rcu_ptr_callback (struct rcu_head * head )
26
+ {
27
+ struct ext4_rcu_ptr * ptr ;
28
+
29
+ ptr = container_of (head , struct ext4_rcu_ptr , rcu );
30
+ kvfree (ptr -> ptr );
31
+ kfree (ptr );
32
+ }
33
+
34
+ void ext4_kvfree_array_rcu (void * to_free )
35
+ {
36
+ struct ext4_rcu_ptr * ptr = kzalloc (sizeof (* ptr ), GFP_KERNEL );
37
+
38
+ if (ptr ) {
39
+ ptr -> ptr = to_free ;
40
+ call_rcu (& ptr -> rcu , ext4_rcu_ptr_callback );
41
+ return ;
42
+ }
43
+ synchronize_rcu ();
44
+ kvfree (to_free );
45
+ }
46
+
20
47
int ext4_resize_begin (struct super_block * sb )
21
48
{
22
49
struct ext4_sb_info * sbi = EXT4_SB (sb );
@@ -542,8 +569,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
542
569
brelse (gdb );
543
570
goto out ;
544
571
}
545
- memcpy (gdb -> b_data , sbi -> s_group_desc [ j ] -> b_data ,
546
- gdb -> b_size );
572
+ memcpy (gdb -> b_data , sbi_array_rcu_deref ( sbi ,
573
+ s_group_desc , j ) -> b_data , gdb -> b_size );
547
574
set_buffer_uptodate (gdb );
548
575
549
576
err = ext4_handle_dirty_metadata (handle , NULL , gdb );
@@ -860,13 +887,15 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
860
887
}
861
888
brelse (dind );
862
889
863
- o_group_desc = EXT4_SB (sb )-> s_group_desc ;
890
+ rcu_read_lock ();
891
+ o_group_desc = rcu_dereference (EXT4_SB (sb )-> s_group_desc );
864
892
memcpy (n_group_desc , o_group_desc ,
865
893
EXT4_SB (sb )-> s_gdb_count * sizeof (struct buffer_head * ));
894
+ rcu_read_unlock ();
866
895
n_group_desc [gdb_num ] = gdb_bh ;
867
- EXT4_SB (sb )-> s_group_desc = n_group_desc ;
896
+ rcu_assign_pointer ( EXT4_SB (sb )-> s_group_desc , n_group_desc ) ;
868
897
EXT4_SB (sb )-> s_gdb_count ++ ;
869
- kvfree (o_group_desc );
898
+ ext4_kvfree_array_rcu (o_group_desc );
870
899
871
900
le16_add_cpu (& es -> s_reserved_gdt_blocks , -1 );
872
901
err = ext4_handle_dirty_super (handle , sb );
@@ -909,9 +938,11 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
909
938
return err ;
910
939
}
911
940
912
- o_group_desc = EXT4_SB (sb )-> s_group_desc ;
941
+ rcu_read_lock ();
942
+ o_group_desc = rcu_dereference (EXT4_SB (sb )-> s_group_desc );
913
943
memcpy (n_group_desc , o_group_desc ,
914
944
EXT4_SB (sb )-> s_gdb_count * sizeof (struct buffer_head * ));
945
+ rcu_read_unlock ();
915
946
n_group_desc [gdb_num ] = gdb_bh ;
916
947
917
948
BUFFER_TRACE (gdb_bh , "get_write_access" );
@@ -922,9 +953,9 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
922
953
return err ;
923
954
}
924
955
925
- EXT4_SB (sb )-> s_group_desc = n_group_desc ;
956
+ rcu_assign_pointer ( EXT4_SB (sb )-> s_group_desc , n_group_desc ) ;
926
957
EXT4_SB (sb )-> s_gdb_count ++ ;
927
- kvfree (o_group_desc );
958
+ ext4_kvfree_array_rcu (o_group_desc );
928
959
return err ;
929
960
}
930
961
@@ -1188,7 +1219,8 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,
1188
1219
* use non-sparse filesystems anymore. This is already checked above.
1189
1220
*/
1190
1221
if (gdb_off ) {
1191
- gdb_bh = sbi -> s_group_desc [gdb_num ];
1222
+ gdb_bh = sbi_array_rcu_deref (sbi , s_group_desc ,
1223
+ gdb_num );
1192
1224
BUFFER_TRACE (gdb_bh , "get_write_access" );
1193
1225
err = ext4_journal_get_write_access (handle , gdb_bh );
1194
1226
@@ -1270,7 +1302,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb,
1270
1302
/*
1271
1303
* get_write_access() has been called on gdb_bh by ext4_add_new_desc().
1272
1304
*/
1273
- gdb_bh = sbi -> s_group_desc [ gdb_num ] ;
1305
+ gdb_bh = sbi_array_rcu_deref ( sbi , s_group_desc , gdb_num ) ;
1274
1306
/* Update group descriptor block for new group */
1275
1307
gdp = (struct ext4_group_desc * )(gdb_bh -> b_data +
1276
1308
gdb_off * EXT4_DESC_SIZE (sb ));
@@ -1497,7 +1529,8 @@ static int ext4_flex_group_add(struct super_block *sb,
1497
1529
for (; gdb_num <= gdb_num_end ; gdb_num ++ ) {
1498
1530
struct buffer_head * gdb_bh ;
1499
1531
1500
- gdb_bh = sbi -> s_group_desc [gdb_num ];
1532
+ gdb_bh = sbi_array_rcu_deref (sbi , s_group_desc ,
1533
+ gdb_num );
1501
1534
if (old_gdb == gdb_bh -> b_blocknr )
1502
1535
continue ;
1503
1536
update_backups (sb , gdb_bh -> b_blocknr , gdb_bh -> b_data ,
0 commit comments