• Darrick J. Wong's avatar
    xfs: make rextslog computation consistent with mkfs · a6a38f30
    Darrick J. Wong authored
    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: f8e566c0 ("xfs: validate the realtime geometry in xfs_validate_sb_common")
    Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    a6a38f30
xfs_sb.c 41.4 KB