@@ -766,6 +766,31 @@ xfs_growfs_rt_alloc_fake_mount(
766
766
return nmp ;
767
767
}
768
768
769
+ /* Free all the new space and return the number of extents actually freed. */
770
+ static int
771
+ xfs_growfs_rt_free_new (
772
+ struct xfs_rtgroup * rtg ,
773
+ struct xfs_rtalloc_args * nargs ,
774
+ xfs_rtbxlen_t * freed_rtx )
775
+ {
776
+ struct xfs_mount * mp = rtg_mount (rtg );
777
+ xfs_rgnumber_t rgno = rtg_rgno (rtg );
778
+ xfs_rtxnum_t start_rtx = 0 , end_rtx ;
779
+
780
+ if (rgno < mp -> m_sb .sb_rgcount )
781
+ start_rtx = xfs_rtgroup_extents (mp , rgno );
782
+ end_rtx = xfs_rtgroup_extents (nargs -> mp , rgno );
783
+
784
+ /*
785
+ * Compute the first new extent that we want to free, being careful to
786
+ * skip past a realtime superblock at the start of the realtime volume.
787
+ */
788
+ if (xfs_has_rtsb (nargs -> mp ) && rgno == 0 && start_rtx == 0 )
789
+ start_rtx ++ ;
790
+ * freed_rtx = end_rtx - start_rtx ;
791
+ return xfs_rtfree_range (nargs , start_rtx , * freed_rtx );
792
+ }
793
+
769
794
static xfs_rfsblock_t
770
795
xfs_growfs_rt_nrblocks (
771
796
struct xfs_rtgroup * rtg ,
@@ -786,6 +811,43 @@ xfs_growfs_rt_nrblocks(
786
811
return min (nrblocks , step );
787
812
}
788
813
814
+ /*
815
+ * If the post-grow filesystem will have an rtsb; we're initializing the first
816
+ * rtgroup; and the filesystem didn't have a realtime section, write the rtsb
817
+ * now, and attach the rtsb buffer to the real mount.
818
+ */
819
+ static int
820
+ xfs_growfs_rt_init_rtsb (
821
+ const struct xfs_rtalloc_args * nargs ,
822
+ const struct xfs_rtgroup * rtg ,
823
+ const struct xfs_rtalloc_args * args )
824
+ {
825
+ struct xfs_mount * mp = args -> mp ;
826
+ struct xfs_buf * rtsb_bp ;
827
+ int error ;
828
+
829
+ if (!xfs_has_rtsb (nargs -> mp ))
830
+ return 0 ;
831
+ if (rtg_rgno (rtg ) > 0 )
832
+ return 0 ;
833
+ if (mp -> m_sb .sb_rblocks )
834
+ return 0 ;
835
+
836
+ error = xfs_buf_get_uncached (mp -> m_rtdev_targp , XFS_FSB_TO_BB (mp , 1 ),
837
+ 0 , & rtsb_bp );
838
+ if (error )
839
+ return error ;
840
+
841
+ rtsb_bp -> b_maps [0 ].bm_bn = XFS_RTSB_DADDR ;
842
+ rtsb_bp -> b_ops = & xfs_rtsb_buf_ops ;
843
+
844
+ xfs_update_rtsb (rtsb_bp , mp -> m_sb_bp );
845
+ mp -> m_rtsb_bp = rtsb_bp ;
846
+ error = xfs_bwrite (rtsb_bp );
847
+ xfs_buf_unlock (rtsb_bp );
848
+ return error ;
849
+ }
850
+
789
851
static int
790
852
xfs_growfs_rt_bmblock (
791
853
struct xfs_rtgroup * rtg ,
@@ -808,7 +870,8 @@ xfs_growfs_rt_bmblock(
808
870
int error ;
809
871
810
872
/*
811
- * Calculate new sb and mount fields for this round.
873
+ * Calculate new sb and mount fields for this round. Also ensure the
874
+ * rtg_extents value is uptodate as the rtbitmap code relies on it.
812
875
*/
813
876
nmp = nargs .mp = xfs_growfs_rt_alloc_fake_mount (mp ,
814
877
xfs_growfs_rt_nrblocks (rtg , nrblocks , rextsize , bmbno ),
@@ -861,6 +924,10 @@ xfs_growfs_rt_bmblock(
861
924
goto out_cancel ;
862
925
}
863
926
927
+ error = xfs_growfs_rt_init_rtsb (& nargs , rtg , & args );
928
+ if (error )
929
+ goto out_cancel ;
930
+
864
931
/*
865
932
* Update superblock fields.
866
933
*/
@@ -879,12 +946,14 @@ xfs_growfs_rt_bmblock(
879
946
if (nmp -> m_sb .sb_rextslog != mp -> m_sb .sb_rextslog )
880
947
xfs_trans_mod_sb (args .tp , XFS_TRANS_SB_REXTSLOG ,
881
948
nmp -> m_sb .sb_rextslog - mp -> m_sb .sb_rextslog );
949
+ if (nmp -> m_sb .sb_rgcount != mp -> m_sb .sb_rgcount )
950
+ xfs_trans_mod_sb (args .tp , XFS_TRANS_SB_RGCOUNT ,
951
+ nmp -> m_sb .sb_rgcount - mp -> m_sb .sb_rgcount );
882
952
883
953
/*
884
954
* Free the new extent.
885
955
*/
886
- freed_rtx = nmp -> m_sb .sb_rextents - mp -> m_sb .sb_rextents ;
887
- error = xfs_rtfree_range (& nargs , mp -> m_sb .sb_rextents , freed_rtx );
956
+ error = xfs_growfs_rt_free_new (rtg , & nargs , & freed_rtx );
888
957
xfs_rtbuf_cache_relse (& nargs );
889
958
if (error )
890
959
goto out_cancel ;
@@ -925,6 +994,15 @@ xfs_growfs_rt_bmblock(
925
994
return error ;
926
995
}
927
996
997
+ static xfs_rtxnum_t
998
+ xfs_last_rtgroup_extents (
999
+ struct xfs_mount * mp )
1000
+ {
1001
+ return mp -> m_sb .sb_rextents -
1002
+ ((xfs_rtxnum_t )(mp -> m_sb .sb_rgcount - 1 ) *
1003
+ mp -> m_sb .sb_rgextents );
1004
+ }
1005
+
928
1006
/*
929
1007
* Calculate the last rbmblock currently used.
930
1008
*
@@ -935,11 +1013,20 @@ xfs_last_rt_bmblock(
935
1013
struct xfs_rtgroup * rtg )
936
1014
{
937
1015
struct xfs_mount * mp = rtg_mount (rtg );
938
- xfs_fileoff_t bmbno = mp -> m_sb .sb_rbmblocks ;
1016
+ xfs_rgnumber_t rgno = rtg_rgno (rtg );
1017
+ xfs_fileoff_t bmbno = 0 ;
1018
+
1019
+ ASSERT (!mp -> m_sb .sb_rgcount || rgno >= mp -> m_sb .sb_rgcount - 1 );
1020
+
1021
+ if (mp -> m_sb .sb_rgcount && rgno == mp -> m_sb .sb_rgcount - 1 ) {
1022
+ xfs_rtxnum_t nrext = xfs_last_rtgroup_extents (mp );
1023
+
1024
+ /* Also fill up the previous block if not entirely full. */
1025
+ bmbno = xfs_rtbitmap_blockcount_len (mp , nrext );
1026
+ if (xfs_rtx_to_rbmword (mp , nrext ) != 0 )
1027
+ bmbno -- ;
1028
+ }
939
1029
940
- /* Skip the current block if it is exactly full. */
941
- if (xfs_rtx_to_rbmword (mp , mp -> m_sb .sb_rextents ) != 0 )
942
- bmbno -- ;
943
1030
return bmbno ;
944
1031
}
945
1032
@@ -956,38 +1043,56 @@ xfs_growfs_rt_alloc_blocks(
956
1043
struct xfs_mount * mp = rtg_mount (rtg );
957
1044
struct xfs_inode * rbmip = rtg -> rtg_inodes [XFS_RTGI_BITMAP ];
958
1045
struct xfs_inode * rsumip = rtg -> rtg_inodes [XFS_RTGI_SUMMARY ];
959
- xfs_extlen_t orbmblocks ;
960
- xfs_extlen_t orsumblocks ;
961
- xfs_extlen_t nrsumblocks ;
1046
+ xfs_extlen_t orbmblocks = 0 ;
1047
+ xfs_extlen_t orsumblocks = 0 ;
962
1048
struct xfs_mount * nmp ;
963
- int error ;
964
-
965
- /*
966
- * Get the old block counts for bitmap and summary inodes.
967
- * These can't change since other growfs callers are locked out.
968
- */
969
- orbmblocks = XFS_B_TO_FSB (mp , rbmip -> i_disk_size );
970
- orsumblocks = XFS_B_TO_FSB (mp , rsumip -> i_disk_size );
1049
+ int error = 0 ;
971
1050
972
1051
nmp = xfs_growfs_rt_alloc_fake_mount (mp , nrblocks , rextsize );
973
1052
if (!nmp )
974
1053
return - ENOMEM ;
975
-
976
1054
* nrbmblocks = nmp -> m_sb .sb_rbmblocks ;
977
- nrsumblocks = nmp -> m_rsumblocks ;
978
- kfree (nmp );
1055
+
1056
+ if (xfs_has_rtgroups (mp )) {
1057
+ /*
1058
+ * For file systems with the rtgroups feature, the RT bitmap and
1059
+ * summary are always fully allocated, which means that we never
1060
+ * need to grow the existing files.
1061
+ *
1062
+ * But we have to be careful to only fill the bitmap until the
1063
+ * end of the actually used range.
1064
+ */
1065
+ if (rtg_rgno (rtg ) == nmp -> m_sb .sb_rgcount - 1 )
1066
+ * nrbmblocks = xfs_rtbitmap_blockcount_len (nmp ,
1067
+ xfs_last_rtgroup_extents (nmp ));
1068
+
1069
+ if (mp -> m_sb .sb_rgcount &&
1070
+ rtg_rgno (rtg ) == mp -> m_sb .sb_rgcount - 1 )
1071
+ goto out_free ;
1072
+ } else {
1073
+ /*
1074
+ * Get the old block counts for bitmap and summary inodes.
1075
+ * These can't change since other growfs callers are locked out.
1076
+ */
1077
+ orbmblocks = XFS_B_TO_FSB (mp , rbmip -> i_disk_size );
1078
+ orsumblocks = XFS_B_TO_FSB (mp , rsumip -> i_disk_size );
1079
+ }
979
1080
980
1081
error = xfs_rtfile_initialize_blocks (rtg , XFS_RTGI_BITMAP , orbmblocks ,
981
- * nrbmblocks , NULL );
1082
+ nmp -> m_sb . sb_rbmblocks , NULL );
982
1083
if (error )
983
- return error ;
984
- return xfs_rtfile_initialize_blocks (rtg , XFS_RTGI_SUMMARY , orsumblocks ,
985
- nrsumblocks , NULL );
1084
+ goto out_free ;
1085
+ error = xfs_rtfile_initialize_blocks (rtg , XFS_RTGI_SUMMARY , orsumblocks ,
1086
+ nmp -> m_rsumblocks , NULL );
1087
+ out_free :
1088
+ kfree (nmp );
1089
+ return error ;
986
1090
}
987
1091
988
1092
static int
989
1093
xfs_growfs_rtg (
990
1094
struct xfs_mount * mp ,
1095
+ xfs_rgnumber_t rgno ,
991
1096
xfs_rfsblock_t nrblocks ,
992
1097
xfs_agblock_t rextsize )
993
1098
{
@@ -998,7 +1103,7 @@ xfs_growfs_rtg(
998
1103
unsigned int i ;
999
1104
int error ;
1000
1105
1001
- rtg = xfs_rtgroup_grab (mp , 0 );
1106
+ rtg = xfs_rtgroup_grab (mp , rgno );
1002
1107
if (!rtg )
1003
1108
return - EINVAL ;
1004
1109
@@ -1069,14 +1174,67 @@ xfs_growfs_check_rtgeom(
1069
1174
return error ;
1070
1175
}
1071
1176
1177
+ /*
1178
+ * Compute the new number of rt groups and ensure that /rtgroups exists.
1179
+ *
1180
+ * Changing the rtgroup size is not allowed (even if the rt volume hasn't yet
1181
+ * been initialized) because the userspace ABI doesn't support it.
1182
+ */
1183
+ static int
1184
+ xfs_growfs_rt_prep_groups (
1185
+ struct xfs_mount * mp ,
1186
+ xfs_rfsblock_t rblocks ,
1187
+ xfs_extlen_t rextsize ,
1188
+ xfs_rgnumber_t * new_rgcount )
1189
+ {
1190
+ int error ;
1191
+
1192
+ * new_rgcount = howmany_64 (rblocks , mp -> m_sb .sb_rgextents * rextsize );
1193
+ if (* new_rgcount > XFS_MAX_RGNUMBER )
1194
+ return - EINVAL ;
1195
+
1196
+ /* Make sure the /rtgroups dir has been created */
1197
+ if (!mp -> m_rtdirip ) {
1198
+ struct xfs_trans * tp ;
1199
+
1200
+ error = xfs_trans_alloc_empty (mp , & tp );
1201
+ if (error )
1202
+ return error ;
1203
+ error = xfs_rtginode_load_parent (tp );
1204
+ xfs_trans_cancel (tp );
1205
+
1206
+ if (error == - ENOENT )
1207
+ error = xfs_rtginode_mkdir_parent (mp );
1208
+ if (error )
1209
+ return error ;
1210
+ }
1211
+
1212
+ return 0 ;
1213
+ }
1214
+
1215
+ static bool
1216
+ xfs_grow_last_rtg (
1217
+ struct xfs_mount * mp )
1218
+ {
1219
+ if (!xfs_has_rtgroups (mp ))
1220
+ return true;
1221
+ if (mp -> m_sb .sb_rgcount == 0 )
1222
+ return false;
1223
+ return xfs_rtgroup_extents (mp , mp -> m_sb .sb_rgcount - 1 ) <=
1224
+ mp -> m_sb .sb_rgextents ;
1225
+ }
1226
+
1072
1227
/*
1073
1228
* Grow the realtime area of the filesystem.
1074
1229
*/
1075
1230
int
1076
1231
xfs_growfs_rt (
1077
- xfs_mount_t * mp , /* mount point for filesystem */
1078
- xfs_growfs_rt_t * in ) /* growfs rt input struct */
1232
+ struct xfs_mount * mp ,
1233
+ struct xfs_growfs_rt * in )
1079
1234
{
1235
+ xfs_rgnumber_t old_rgcount = mp -> m_sb .sb_rgcount ;
1236
+ xfs_rgnumber_t new_rgcount = 1 ;
1237
+ xfs_rgnumber_t rgno ;
1080
1238
struct xfs_buf * bp ;
1081
1239
xfs_agblock_t old_rextsize = mp -> m_sb .sb_rextsize ;
1082
1240
int error ;
@@ -1134,18 +1292,56 @@ xfs_growfs_rt(
1134
1292
if (error )
1135
1293
goto out_unlock ;
1136
1294
1137
- error = xfs_growfs_rtg (mp , in -> newblocks , in -> extsize );
1138
- if (error )
1139
- goto out_unlock ;
1295
+ if (xfs_has_rtgroups (mp )) {
1296
+ error = xfs_growfs_rt_prep_groups (mp , in -> newblocks ,
1297
+ in -> extsize , & new_rgcount );
1298
+ if (error )
1299
+ goto out_unlock ;
1300
+ }
1140
1301
1141
- if (old_rextsize != in -> extsize ) {
1142
- error = xfs_growfs_rt_fixup_extsize (mp );
1302
+ if (xfs_grow_last_rtg (mp )) {
1303
+ error = xfs_growfs_rtg (mp , old_rgcount - 1 , in -> newblocks ,
1304
+ in -> extsize );
1305
+ if (error )
1306
+ goto out_unlock ;
1307
+ }
1308
+
1309
+ for (rgno = old_rgcount ; rgno < new_rgcount ; rgno ++ ) {
1310
+ xfs_rtbxlen_t rextents = div_u64 (in -> newblocks , in -> extsize );
1311
+
1312
+ error = xfs_rtgroup_alloc (mp , rgno , new_rgcount , rextents );
1143
1313
if (error )
1144
1314
goto out_unlock ;
1315
+
1316
+ error = xfs_growfs_rtg (mp , rgno , in -> newblocks , in -> extsize );
1317
+ if (error ) {
1318
+ struct xfs_rtgroup * rtg ;
1319
+
1320
+ rtg = xfs_rtgroup_grab (mp , rgno );
1321
+ if (!WARN_ON_ONCE (!rtg )) {
1322
+ xfs_rtunmount_rtg (rtg );
1323
+ xfs_rtgroup_rele (rtg );
1324
+ xfs_rtgroup_free (mp , rgno );
1325
+ }
1326
+ break ;
1327
+ }
1145
1328
}
1146
1329
1147
- /* Update secondary superblocks now the physical grow has completed */
1148
- error = xfs_update_secondary_sbs (mp );
1330
+ if (!error && old_rextsize != in -> extsize )
1331
+ error = xfs_growfs_rt_fixup_extsize (mp );
1332
+
1333
+ /*
1334
+ * Update secondary superblocks now the physical grow has completed.
1335
+ *
1336
+ * Also do this in case of an error as we might have already
1337
+ * successfully updated one or more RTGs and incremented sb_rgcount.
1338
+ */
1339
+ if (!xfs_is_shutdown (mp )) {
1340
+ int error2 = xfs_update_secondary_sbs (mp );
1341
+
1342
+ if (!error )
1343
+ error = error2 ;
1344
+ }
1149
1345
1150
1346
out_unlock :
1151
1347
mutex_unlock (& mp -> m_growlock );
0 commit comments