• Darrick J. Wong's avatar
    xfs: set bnobt/cntbt numrecs correctly when formatting new AGs · 8e698ee7
    Darrick J. Wong authored
    Through generic/300, I discovered that mkfs.xfs creates corrupt
    filesystems when given these parameters:
    
    # mkfs.xfs -d size=512M /dev/sda -f -d su=128k,sw=4 --unsupported
    Filesystems formatted with --unsupported are not supported!!
    meta-data=/dev/sda               isize=512    agcount=8, agsize=16352 blks
             =                       sectsz=512   attr=2, projid32bit=1
             =                       crc=1        finobt=1, sparse=1, rmapbt=1
             =                       reflink=1    bigtime=1 inobtcount=1 nrext64=1
    data     =                       bsize=4096   blocks=130816, imaxpct=25
             =                       sunit=32     swidth=128 blks
    naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
    log      =internal log           bsize=4096   blocks=8192, version=2
             =                       sectsz=512   sunit=32 blks, lazy-count=1
    realtime =none                   extsz=4096   blocks=0, rtextents=0
             =                       rgcount=0    rgsize=0 blks
    Discarding blocks...Done.
    # xfs_repair -n /dev/sda
    Phase 1 - find and verify superblock...
            - reporting progress in intervals of 15 minutes
    Phase 2 - using internal log
            - zero log...
            - 16:30:50: zeroing log - 16320 of 16320 blocks done
            - scan filesystem freespace and inode maps...
    agf_freeblks 25, counted 0 in ag 4
    sb_fdblocks 8823, counted 8798
    
    The root cause of this problem is the numrecs handling in
    xfs_freesp_init_recs, which is used to initialize a new AG.  Prior to
    calling the function, we set up the new bnobt block with numrecs == 1
    and rely on _freesp_init_recs to format that new record.  If the last
    record created has a blockcount of zero, then it sets numrecs = 0.
    
    That last bit isn't correct if the AG contains the log, the start of the
    log is not immediately after the initial blocks due to stripe alignment,
    and the end of the log is perfectly aligned with the end of the AG.  For
    this case, we actually formatted a single bnobt record to handle the
    free space before the start of the (stripe aligned) log, and incremented
    arec to try to format a second record.  That second record turned out to
    be unnecessary, so what we really want is to leave numrecs at 1.
    
    The numrecs handling itself is overly complicated because a different
    function sets numrecs == 1.  Change the bnobt creation code to start
    with numrecs set to zero and only increment it after successfully
    formatting a free space extent into the btree block.
    
    Fixes: f327a007 ("xfs: account for log space when formatting new AGs")
    Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
    Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
    Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
    8e698ee7
xfs_ag.c 27.6 KB