Skip to content

Commit a6a38f3

Browse files
author
Darrick J. Wong
committed
xfs: make rextslog computation consistent with mkfs
There's a weird discrepancy in xfsprogs dating back to the creation of the Linux port -- if there are zero rt extents, mkfs will set sb_rextents and sb_rextslog both to zero: sbp->sb_rextslog = (uint8_t)(rtextents ? libxfs_highbit32((unsigned int)rtextents) : 0); However, that's not the check that xfs_repair uses for nonzero rtblocks: if (sb->sb_rextslog != libxfs_highbit32((unsigned int)sb->sb_rextents)) The difference here is that xfs_highbit32 returns -1 if its argument is zero. Unfortunately, this means that in the weird corner case of a realtime volume shorter than 1 rt extent, xfs_repair will immediately flag a freshly formatted filesystem as corrupt. Because mkfs has been writing ondisk artifacts like this for decades, we have to accept that as "correct". TBH, zero rextslog for zero rtextents makes more sense to me anyway. Regrettably, the superblock verifier checks created in commit copied xfs_repair even though mkfs has been writing out such filesystems for ages. Fix the superblock verifier to accept what mkfs spits out; the userspace version of this patch will have to fix xfs_repair as well. Note that the new helper leaves the zeroday bug where the upper 32 bits of sb_rextents is ripped off and fed to highbit32. This leads to a seriously undersized rt summary file, which immediately breaks mkfs: $ hugedisk.sh foo /dev/sdc $(( 0x100000080 * 4096))B $ /sbin/mkfs.xfs -f /dev/sda -m rmapbt=0,reflink=0 -r rtdev=/dev/mapper/foo meta-data=/dev/sda isize=512 agcount=4, agsize=1298176 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=0 bigtime=1 inobtcount=1 nrext64=1 data = bsize=4096 blocks=5192704, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=16384, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =/dev/mapper/foo extsz=4096 blocks=4294967424, rtextents=4294967424 Discarding blocks...Done. mkfs.xfs: Error initializing the realtime space [117 - Structure needs cleaning] The next patch will drop support for rt volumes with fewer than 1 or more than 2^32-1 rt extents, since they've clearly been broken forever. Fixes: f8e566c ("xfs: validate the realtime geometry in xfs_validate_sb_common") Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent a49c708 commit a6a38f3

File tree

4 files changed

+19
-3
lines changed

4 files changed

+19
-3
lines changed

fs/xfs/libxfs/xfs_rtbitmap.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,18 @@ xfs_rtbitmap_blockcount(
11301130
return howmany_64(rtextents, NBBY * mp->m_sb.sb_blocksize);
11311131
}
11321132

1133+
/*
1134+
* Compute the maximum level number of the realtime summary file, as defined by
1135+
* mkfs. The use of highbit32 on a 64-bit quantity is a historic artifact that
1136+
* prohibits correct use of rt volumes with more than 2^32 extents.
1137+
*/
1138+
uint8_t
1139+
xfs_compute_rextslog(
1140+
xfs_rtbxlen_t rtextents)
1141+
{
1142+
return rtextents ? xfs_highbit32(rtextents) : 0;
1143+
}
1144+
11331145
/*
11341146
* Compute the number of rtbitmap words needed to populate every block of a
11351147
* bitmap that is large enough to track the given number of rt extents.

fs/xfs/libxfs/xfs_rtbitmap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,8 @@ xfs_rtfree_extent(
351351
int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno,
352352
xfs_filblks_t rtlen);
353353

354+
uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents);
355+
354356
xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t
355357
rtextents);
356358
unsigned long long xfs_rtbitmap_wordcount(struct xfs_mount *mp,
@@ -369,6 +371,7 @@ unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp,
369371
# define xfs_rtsummary_read_buf(a,b) (-ENOSYS)
370372
# define xfs_rtbuf_cache_relse(a) (0)
371373
# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS)
374+
# define xfs_compute_rextslog(rtx) (0)
372375
static inline xfs_filblks_t
373376
xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents)
374377
{

fs/xfs/libxfs/xfs_sb.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "xfs_da_format.h"
2626
#include "xfs_health.h"
2727
#include "xfs_ag.h"
28+
#include "xfs_rtbitmap.h"
2829

2930
/*
3031
* Physical superblock buffer manipulations. Shared with libxfs in userspace.
@@ -509,7 +510,7 @@ xfs_validate_sb_common(
509510
NBBY * sbp->sb_blocksize);
510511

511512
if (sbp->sb_rextents != rexts ||
512-
sbp->sb_rextslog != xfs_highbit32(sbp->sb_rextents) ||
513+
sbp->sb_rextslog != xfs_compute_rextslog(rexts) ||
513514
sbp->sb_rbmblocks != rbmblocks) {
514515
xfs_notice(mp,
515516
"realtime geometry sanity check failed");

fs/xfs/xfs_rtalloc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,7 @@ xfs_growfs_rt(
964964
nrextents = nrblocks;
965965
do_div(nrextents, in->extsize);
966966
nrbmblocks = xfs_rtbitmap_blockcount(mp, nrextents);
967-
nrextslog = xfs_highbit32(nrextents);
967+
nrextslog = xfs_compute_rextslog(nrextents);
968968
nrsumlevels = nrextslog + 1;
969969
nrsumblocks = xfs_rtsummary_blockcount(mp, nrsumlevels, nrbmblocks);
970970
nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
@@ -1031,7 +1031,7 @@ xfs_growfs_rt(
10311031
nsbp->sb_rblocks = min(nrblocks, nrblocks_step);
10321032
nsbp->sb_rextents = xfs_rtb_to_rtx(nmp, nsbp->sb_rblocks);
10331033
ASSERT(nsbp->sb_rextents != 0);
1034-
nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
1034+
nsbp->sb_rextslog = xfs_compute_rextslog(nsbp->sb_rextents);
10351035
nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
10361036
nrsumblocks = xfs_rtsummary_blockcount(mp, nrsumlevels,
10371037
nsbp->sb_rbmblocks);

0 commit comments

Comments
 (0)