Skip to content

Commit 7195f24

Browse files
author
Darrick J. Wong
committed
xfs: make xfs_rtblock_t a segmented address like xfs_fsblock_t
Now that we've finished adding allocation groups to the realtime volume, let's make the file block mapping address (xfs_rtblock_t) a segmented value just like we do on the data device. This means that group number and block number conversions can be done with shifting and masking instead of integer division. While in theory we could continue caching the rgno shift value in m_rgblklog, the fact that we now always use the shift value means that we have an opportunity to increase the redundancy of the rt geometry by storing it in the ondisk superblock and adding more sb verifier code. Extend the sueprblock to store the rgblklog value. Now that we have segmented addresses, set the correct values in m_groups[XG_TYPE_RTG] so that the xfs_group helpers work correctly. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent 3f0205e commit 7195f24

File tree

12 files changed

+126
-84
lines changed

12 files changed

+126
-84
lines changed

fs/xfs/libxfs/xfs_bmap.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3152,10 +3152,8 @@ xfs_bmap_adjacent_valid(
31523152

31533153
if (XFS_IS_REALTIME_INODE(ap->ip) &&
31543154
(ap->datatype & XFS_ALLOC_USERDATA)) {
3155-
if (x >= mp->m_sb.sb_rblocks)
3156-
return false;
31573155
if (!xfs_has_rtgroups(mp))
3158-
return true;
3156+
return x < mp->m_sb.sb_rblocks;
31593157

31603158
return xfs_rtb_to_rgno(mp, x) == xfs_rtb_to_rgno(mp, y) &&
31613159
xfs_rtb_to_rgno(mp, x) < mp->m_sb.sb_rgcount &&

fs/xfs/libxfs/xfs_format.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ typedef struct xfs_sb {
179179
xfs_rgnumber_t sb_rgcount; /* number of realtime groups */
180180
xfs_rtxlen_t sb_rgextents; /* size of a realtime group in rtx */
181181

182+
uint8_t sb_rgblklog; /* rt group number shift */
183+
uint8_t sb_pad[7]; /* zeroes */
184+
182185
/* must be padded to 64 bit alignment */
183186
} xfs_sb_t;
184187

@@ -268,6 +271,9 @@ struct xfs_dsb {
268271
__be32 sb_rgcount; /* # of realtime groups */
269272
__be32 sb_rgextents; /* size of rtgroup in rtx */
270273

274+
__u8 sb_rgblklog; /* rt group number shift */
275+
__u8 sb_pad[7]; /* zeroes */
276+
271277
/*
272278
* The size of this structure must be padded to 64 bit alignment.
273279
*

fs/xfs/libxfs/xfs_ondisk.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ xfs_check_ondisk_structs(void)
3737
XFS_CHECK_STRUCT_SIZE(struct xfs_dinode, 176);
3838
XFS_CHECK_STRUCT_SIZE(struct xfs_disk_dquot, 104);
3939
XFS_CHECK_STRUCT_SIZE(struct xfs_dqblk, 136);
40-
XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 280);
40+
XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 288);
4141
XFS_CHECK_STRUCT_SIZE(struct xfs_dsymlink_hdr, 56);
4242
XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_key, 4);
4343
XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_rec, 16);

fs/xfs/libxfs/xfs_rtbitmap.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ xfs_rtx_to_rtb(
2626
xfs_rtxnum_t rtx)
2727
{
2828
struct xfs_mount *mp = rtg_mount(rtg);
29-
xfs_rtblock_t start = xfs_rgno_start_rtb(mp, rtg_rgno(rtg));
29+
xfs_rtblock_t start = xfs_group_start_fsb(rtg_group(rtg));
3030

3131
if (mp->m_rtxblklog >= 0)
3232
return start + (rtx << mp->m_rtxblklog);
@@ -128,11 +128,11 @@ xfs_rtb_to_rtx(
128128
struct xfs_mount *mp,
129129
xfs_rtblock_t rtbno)
130130
{
131-
uint64_t __rgbno = __xfs_rtb_to_rgbno(mp, rtbno);
132-
131+
/* open-coded 64-bit masking operation */
132+
rtbno &= mp->m_groups[XG_TYPE_RTG].blkmask;
133133
if (likely(mp->m_rtxblklog >= 0))
134-
return __rgbno >> mp->m_rtxblklog;
135-
return div_u64(__rgbno, mp->m_sb.sb_rextsize);
134+
return rtbno >> mp->m_rtxblklog;
135+
return div_u64(rtbno, mp->m_sb.sb_rextsize);
136136
}
137137

138138
/* Return the offset of an rt block number within an rt extent. */
@@ -141,9 +141,10 @@ xfs_rtb_to_rtxoff(
141141
struct xfs_mount *mp,
142142
xfs_rtblock_t rtbno)
143143
{
144+
/* open-coded 64-bit masking operation */
145+
rtbno &= mp->m_groups[XG_TYPE_RTG].blkmask;
144146
if (likely(mp->m_rtxblklog >= 0))
145147
return rtbno & mp->m_rtxblkmask;
146-
147148
return do_div(rtbno, mp->m_sb.sb_rextsize);
148149
}
149150

fs/xfs/libxfs/xfs_rtgroup.h

Lines changed: 21 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -122,70 +122,28 @@ xfs_rtgroup_next(
122122
return xfs_rtgroup_next_range(mp, rtg, 0, mp->m_sb.sb_rgcount - 1);
123123
}
124124

125-
static inline xfs_rtblock_t
126-
xfs_rgno_start_rtb(
127-
struct xfs_mount *mp,
128-
xfs_rgnumber_t rgno)
129-
{
130-
if (mp->m_rgblklog >= 0)
131-
return ((xfs_rtblock_t)rgno << mp->m_rgblklog);
132-
return ((xfs_rtblock_t)rgno * mp->m_rgblocks);
133-
}
134-
135-
static inline xfs_rtblock_t
136-
__xfs_rgbno_to_rtb(
137-
struct xfs_mount *mp,
138-
xfs_rgnumber_t rgno,
139-
xfs_rgblock_t rgbno)
140-
{
141-
return xfs_rgno_start_rtb(mp, rgno) + rgbno;
142-
}
143-
144125
static inline xfs_rtblock_t
145126
xfs_rgbno_to_rtb(
146127
struct xfs_rtgroup *rtg,
147128
xfs_rgblock_t rgbno)
148129
{
149-
return __xfs_rgbno_to_rtb(rtg_mount(rtg), rtg_rgno(rtg), rgbno);
130+
return xfs_gbno_to_fsb(rtg_group(rtg), rgbno);
150131
}
151132

152133
static inline xfs_rgnumber_t
153134
xfs_rtb_to_rgno(
154135
struct xfs_mount *mp,
155136
xfs_rtblock_t rtbno)
156137
{
157-
if (!xfs_has_rtgroups(mp))
158-
return 0;
159-
160-
if (mp->m_rgblklog >= 0)
161-
return rtbno >> mp->m_rgblklog;
162-
163-
return div_u64(rtbno, mp->m_rgblocks);
164-
}
165-
166-
static inline uint64_t
167-
__xfs_rtb_to_rgbno(
168-
struct xfs_mount *mp,
169-
xfs_rtblock_t rtbno)
170-
{
171-
uint32_t rem;
172-
173-
if (!xfs_has_rtgroups(mp))
174-
return rtbno;
175-
176-
if (mp->m_rgblklog >= 0)
177-
return rtbno & mp->m_rgblkmask;
178-
179-
div_u64_rem(rtbno, mp->m_rgblocks, &rem);
180-
return rem;
138+
return xfs_fsb_to_gno(mp, rtbno, XG_TYPE_RTG);
181139
}
182140

183141
static inline xfs_rgblock_t
184142
xfs_rtb_to_rgbno(
185143
struct xfs_mount *mp,
186144
xfs_rtblock_t rtbno)
187145
{
188-
return __xfs_rtb_to_rgbno(mp, rtbno);
146+
return xfs_fsb_to_gbno(mp, rtbno, XG_TYPE_RTG);
189147
}
190148

191149
/* Is rtbno the start of a RT group? */
@@ -194,23 +152,38 @@ xfs_rtbno_is_group_start(
194152
struct xfs_mount *mp,
195153
xfs_rtblock_t rtbno)
196154
{
197-
return (rtbno & mp->m_rgblkmask) == 0;
155+
return (rtbno & mp->m_groups[XG_TYPE_RTG].blkmask) == 0;
198156
}
199157

200158
static inline xfs_daddr_t
201159
xfs_rtb_to_daddr(
202160
struct xfs_mount *mp,
203161
xfs_rtblock_t rtbno)
204162
{
205-
return rtbno << mp->m_blkbb_log;
163+
struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG];
164+
xfs_rgnumber_t rgno = xfs_rtb_to_rgno(mp, rtbno);
165+
uint64_t start_bno = (xfs_rtblock_t)rgno * g->blocks;
166+
167+
return XFS_FSB_TO_BB(mp, start_bno + (rtbno & g->blkmask));
206168
}
207169

208170
static inline xfs_rtblock_t
209171
xfs_daddr_to_rtb(
210172
struct xfs_mount *mp,
211173
xfs_daddr_t daddr)
212174
{
213-
return daddr >> mp->m_blkbb_log;
175+
xfs_rfsblock_t bno = XFS_BB_TO_FSBT(mp, daddr);
176+
177+
if (xfs_has_rtgroups(mp)) {
178+
struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG];
179+
xfs_rgnumber_t rgno;
180+
uint32_t rgbno;
181+
182+
rgno = div_u64_rem(bno, g->blocks, &rgbno);
183+
return ((xfs_rtblock_t)rgno << g->blklog) + rgbno;
184+
}
185+
186+
return bno;
214187
}
215188

216189
#ifdef CONFIG_XFS_RT

fs/xfs/libxfs/xfs_sb.c

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -368,12 +368,23 @@ xfs_validate_sb_write(
368368
return 0;
369369
}
370370

371+
int
372+
xfs_compute_rgblklog(
373+
xfs_rtxlen_t rgextents,
374+
xfs_rgblock_t rextsize)
375+
{
376+
uint64_t rgblocks = (uint64_t)rgextents * rextsize;
377+
378+
return xfs_highbit64(rgblocks - 1) + 1;
379+
}
380+
371381
static int
372382
xfs_validate_sb_rtgroups(
373383
struct xfs_mount *mp,
374384
struct xfs_sb *sbp)
375385
{
376386
uint64_t groups;
387+
int rgblklog;
377388

378389
if (sbp->sb_rextsize == 0) {
379390
xfs_warn(mp,
@@ -418,6 +429,14 @@ xfs_validate_sb_rtgroups(
418429
return -EINVAL;
419430
}
420431

432+
rgblklog = xfs_compute_rgblklog(sbp->sb_rgextents, sbp->sb_rextsize);
433+
if (sbp->sb_rgblklog != rgblklog) {
434+
xfs_warn(mp,
435+
"Realtime group log (%d) does not match expected value (%d).",
436+
sbp->sb_rgblklog, rgblklog);
437+
return -EINVAL;
438+
}
439+
421440
return 0;
422441
}
423442

@@ -484,6 +503,12 @@ xfs_validate_sb_common(
484503
}
485504

486505
if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) {
506+
if (memchr_inv(sbp->sb_pad, 0, sizeof(sbp->sb_pad))) {
507+
xfs_warn(mp,
508+
"Metadir superblock padding fields must be zero.");
509+
return -EINVAL;
510+
}
511+
487512
error = xfs_validate_sb_rtgroups(mp, sbp);
488513
if (error)
489514
return error;
@@ -789,6 +814,8 @@ __xfs_sb_from_disk(
789814

790815
if (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) {
791816
to->sb_metadirino = be64_to_cpu(from->sb_metadirino);
817+
to->sb_rgblklog = from->sb_rgblklog;
818+
memcpy(to->sb_pad, from->sb_pad, sizeof(to->sb_pad));
792819
to->sb_rgcount = be32_to_cpu(from->sb_rgcount);
793820
to->sb_rgextents = be32_to_cpu(from->sb_rgextents);
794821
to->sb_rbmino = NULLFSINO;
@@ -956,6 +983,8 @@ xfs_sb_to_disk(
956983

957984
if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) {
958985
to->sb_metadirino = cpu_to_be64(from->sb_metadirino);
986+
to->sb_rgblklog = from->sb_rgblklog;
987+
memset(to->sb_pad, 0, sizeof(to->sb_pad));
959988
to->sb_rgcount = cpu_to_be32(from->sb_rgcount);
960989
to->sb_rgextents = cpu_to_be32(from->sb_rgextents);
961990
to->sb_rbmino = cpu_to_be64(0);
@@ -1090,8 +1119,9 @@ const struct xfs_buf_ops xfs_sb_quiet_buf_ops = {
10901119
.verify_write = xfs_sb_write_verify,
10911120
};
10921121

1122+
/* Compute cached rt geometry from the incore sb. */
10931123
void
1094-
xfs_mount_sb_set_rextsize(
1124+
xfs_sb_mount_rextsize(
10951125
struct xfs_mount *mp,
10961126
struct xfs_sb *sbp)
10971127
{
@@ -1100,13 +1130,32 @@ xfs_mount_sb_set_rextsize(
11001130
mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize);
11011131
mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize);
11021132

1103-
mp->m_rgblocks = sbp->sb_rgextents * sbp->sb_rextsize;
1104-
mp->m_rgblklog = log2_if_power2(mp->m_rgblocks);
1105-
mp->m_rgblkmask = mask64_if_power2(mp->m_rgblocks);
1133+
if (xfs_sb_is_v5(sbp) &&
1134+
(sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) {
1135+
rgs->blocks = sbp->sb_rgextents * sbp->sb_rextsize;
1136+
rgs->blklog = mp->m_sb.sb_rgblklog;
1137+
rgs->blkmask = xfs_mask32lo(mp->m_sb.sb_rgblklog);
1138+
} else {
1139+
rgs->blocks = 0;
1140+
rgs->blklog = 0;
1141+
rgs->blkmask = (uint64_t)-1;
1142+
}
1143+
}
1144+
1145+
/* Update incore sb rt extent size, then recompute the cached rt geometry. */
1146+
void
1147+
xfs_mount_sb_set_rextsize(
1148+
struct xfs_mount *mp,
1149+
struct xfs_sb *sbp,
1150+
xfs_agblock_t rextsize)
1151+
{
1152+
sbp->sb_rextsize = rextsize;
1153+
if (xfs_sb_is_v5(sbp) &&
1154+
(sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR))
1155+
sbp->sb_rgblklog = xfs_compute_rgblklog(sbp->sb_rgextents,
1156+
rextsize);
11061157

1107-
rgs->blocks = 0;
1108-
rgs->blklog = 0;
1109-
rgs->blkmask = (uint64_t)-1;
1158+
xfs_sb_mount_rextsize(mp, sbp);
11101159
}
11111160

11121161
/*
@@ -1140,7 +1189,7 @@ xfs_sb_mount_common(
11401189
ags->blklog = mp->m_sb.sb_agblklog;
11411190
ags->blkmask = xfs_mask32lo(mp->m_sb.sb_agblklog);
11421191

1143-
xfs_mount_sb_set_rextsize(mp, sbp);
1192+
xfs_sb_mount_rextsize(mp, sbp);
11441193

11451194
mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, true);
11461195
mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, false);

fs/xfs/libxfs/xfs_sb.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ extern void xfs_log_sb(struct xfs_trans *tp);
1717
extern int xfs_sync_sb(struct xfs_mount *mp, bool wait);
1818
extern int xfs_sync_sb_buf(struct xfs_mount *mp, bool update_rtsb);
1919
extern void xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp);
20+
void xfs_sb_mount_rextsize(struct xfs_mount *mp, struct xfs_sb *sbp);
2021
void xfs_mount_sb_set_rextsize(struct xfs_mount *mp,
21-
struct xfs_sb *sbp);
22+
struct xfs_sb *sbp, xfs_agblock_t rextsize);
2223
extern void xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from);
2324
extern void xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from);
2425
extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp);
@@ -43,5 +44,6 @@ bool xfs_validate_stripe_geometry(struct xfs_mount *mp,
4344
bool xfs_validate_rt_geometry(struct xfs_sb *sbp);
4445

4546
uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents);
47+
int xfs_compute_rgblklog(xfs_rtxlen_t rgextents, xfs_rgblock_t rextsize);
4648

4749
#endif /* __XFS_SB_H__ */

fs/xfs/libxfs/xfs_types.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,6 @@ xfs_verify_rtbno(
146146
struct xfs_mount *mp,
147147
xfs_rtblock_t rtbno)
148148
{
149-
if (rtbno >= mp->m_sb.sb_rblocks)
150-
return false;
151-
152149
if (xfs_has_rtgroups(mp)) {
153150
xfs_rgnumber_t rgno = xfs_rtb_to_rgno(mp, rtbno);
154151
xfs_rtxnum_t rtx = xfs_rtb_to_rtx(mp, rtbno);
@@ -159,8 +156,10 @@ xfs_verify_rtbno(
159156
return false;
160157
if (xfs_has_rtsb(mp) && rgno == 0 && rtx == 0)
161158
return false;
159+
return true;
162160
}
163-
return true;
161+
162+
return rtbno < mp->m_sb.sb_rblocks;
164163
}
165164

166165
/*

fs/xfs/scrub/agheader.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,15 @@ xchk_superblock(
279279
if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok)))
280280
xchk_block_set_corrupt(sc, bp);
281281

282-
if (sb->sb_features2 != sb->sb_bad_features2)
283-
xchk_block_set_preen(sc, bp);
282+
if (xfs_has_metadir(mp)) {
283+
if (sb->sb_rgblklog != mp->m_sb.sb_rgblklog)
284+
xchk_block_set_corrupt(sc, bp);
285+
if (memchr_inv(sb->sb_pad, 0, sizeof(sb->sb_pad)))
286+
xchk_block_set_preen(sc, bp);
287+
} else {
288+
if (sb->sb_features2 != sb->sb_bad_features2)
289+
xchk_block_set_preen(sc, bp);
290+
}
284291
}
285292

286293
/* Check sb_features2 flags that are set at mkfs time. */

0 commit comments

Comments
 (0)