Skip to content

Commit ee32135

Browse files
author
Darrick J. Wong
committed
xfs: grow the realtime section when realtime groups are enabled
Enable growing the rt section when realtime groups are enabled. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent a2c2836 commit ee32135

File tree

4 files changed

+242
-35
lines changed

4 files changed

+242
-35
lines changed

fs/xfs/libxfs/xfs_shared.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp,
160160
#define XFS_TRANS_SB_RBLOCKS 0x00000800
161161
#define XFS_TRANS_SB_REXTENTS 0x00001000
162162
#define XFS_TRANS_SB_REXTSLOG 0x00002000
163+
#define XFS_TRANS_SB_RGCOUNT 0x00004000
163164

164165
/*
165166
* Here we centralize the specification of XFS meta-data buffer reference count

fs/xfs/xfs_rtalloc.c

Lines changed: 231 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,31 @@ xfs_growfs_rt_alloc_fake_mount(
766766
return nmp;
767767
}
768768

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+
769794
static xfs_rfsblock_t
770795
xfs_growfs_rt_nrblocks(
771796
struct xfs_rtgroup *rtg,
@@ -786,6 +811,43 @@ xfs_growfs_rt_nrblocks(
786811
return min(nrblocks, step);
787812
}
788813

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+
789851
static int
790852
xfs_growfs_rt_bmblock(
791853
struct xfs_rtgroup *rtg,
@@ -808,7 +870,8 @@ xfs_growfs_rt_bmblock(
808870
int error;
809871

810872
/*
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.
812875
*/
813876
nmp = nargs.mp = xfs_growfs_rt_alloc_fake_mount(mp,
814877
xfs_growfs_rt_nrblocks(rtg, nrblocks, rextsize, bmbno),
@@ -861,6 +924,10 @@ xfs_growfs_rt_bmblock(
861924
goto out_cancel;
862925
}
863926

927+
error = xfs_growfs_rt_init_rtsb(&nargs, rtg, &args);
928+
if (error)
929+
goto out_cancel;
930+
864931
/*
865932
* Update superblock fields.
866933
*/
@@ -879,12 +946,14 @@ xfs_growfs_rt_bmblock(
879946
if (nmp->m_sb.sb_rextslog != mp->m_sb.sb_rextslog)
880947
xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_REXTSLOG,
881948
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);
882952

883953
/*
884954
* Free the new extent.
885955
*/
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);
888957
xfs_rtbuf_cache_relse(&nargs);
889958
if (error)
890959
goto out_cancel;
@@ -925,6 +994,15 @@ xfs_growfs_rt_bmblock(
925994
return error;
926995
}
927996

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+
9281006
/*
9291007
* Calculate the last rbmblock currently used.
9301008
*
@@ -935,11 +1013,20 @@ xfs_last_rt_bmblock(
9351013
struct xfs_rtgroup *rtg)
9361014
{
9371015
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+
}
9391029

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--;
9431030
return bmbno;
9441031
}
9451032

@@ -956,38 +1043,56 @@ xfs_growfs_rt_alloc_blocks(
9561043
struct xfs_mount *mp = rtg_mount(rtg);
9571044
struct xfs_inode *rbmip = rtg->rtg_inodes[XFS_RTGI_BITMAP];
9581045
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;
9621048
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;
9711050

9721051
nmp = xfs_growfs_rt_alloc_fake_mount(mp, nrblocks, rextsize);
9731052
if (!nmp)
9741053
return -ENOMEM;
975-
9761054
*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+
}
9791080

9801081
error = xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_BITMAP, orbmblocks,
981-
*nrbmblocks, NULL);
1082+
nmp->m_sb.sb_rbmblocks, NULL);
9821083
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;
9861090
}
9871091

9881092
static int
9891093
xfs_growfs_rtg(
9901094
struct xfs_mount *mp,
1095+
xfs_rgnumber_t rgno,
9911096
xfs_rfsblock_t nrblocks,
9921097
xfs_agblock_t rextsize)
9931098
{
@@ -998,7 +1103,7 @@ xfs_growfs_rtg(
9981103
unsigned int i;
9991104
int error;
10001105

1001-
rtg = xfs_rtgroup_grab(mp, 0);
1106+
rtg = xfs_rtgroup_grab(mp, rgno);
10021107
if (!rtg)
10031108
return -EINVAL;
10041109

@@ -1069,14 +1174,67 @@ xfs_growfs_check_rtgeom(
10691174
return error;
10701175
}
10711176

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+
10721227
/*
10731228
* Grow the realtime area of the filesystem.
10741229
*/
10751230
int
10761231
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)
10791234
{
1235+
xfs_rgnumber_t old_rgcount = mp->m_sb.sb_rgcount;
1236+
xfs_rgnumber_t new_rgcount = 1;
1237+
xfs_rgnumber_t rgno;
10801238
struct xfs_buf *bp;
10811239
xfs_agblock_t old_rextsize = mp->m_sb.sb_rextsize;
10821240
int error;
@@ -1134,18 +1292,56 @@ xfs_growfs_rt(
11341292
if (error)
11351293
goto out_unlock;
11361294

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+
}
11401301

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);
11431313
if (error)
11441314
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+
}
11451328
}
11461329

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+
}
11491345

11501346
out_unlock:
11511347
mutex_unlock(&mp->m_growlock);

0 commit comments

Comments
 (0)