From: Darrick J. Wong Date: Fri, 5 Oct 2018 02:36:10 +0000 (-0500) Subject: xfs: detect and fix bad summary counts at mount X-Git-Tag: v4.19.0-rc0~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52f4e126e0ddb0d2dbcdae243ce8eca4273c1025;p=thirdparty%2Fxfsprogs-dev.git xfs: detect and fix bad summary counts at mount Source kernel commit: 2e9e6481e2a78de3a85083beccfbf6eda2689922 Filippo Giunchedi complained that xfs doesn't even perform basic sanity checks of the fs summary counters at mount time. Therefore, recalculate the summary counters from the AGFs after log recovery if the counts were bad (or we had to recover the fs). Enhance the recalculation routine to fail the mount entirely if the new values are also obviously incorrect. We use a mount state flag to record the "bad summary count" state so that the (subsequent) online fsck patches can detect subtlely incorrect counts and set the flag; clear it userspace asks for a repair; or force a recalculation at the next mount if nobody fixes it by unmount time. Reported-by: Filippo Giunchedi Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Eric Sandeen --- diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index da050abad..969ebd1cd 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -399,7 +399,7 @@ roundup_64(uint64_t x, uint32_t y) #define XFS_MOUNT_IKEEP 0 /* ignored in userspace */ #define XFS_MOUNT_SWALLOC 0 /* ignored in userspace */ #define XFS_MOUNT_RDONLY 0 /* ignored in userspace */ - +#define XFS_MOUNT_BAD_SUMMARY 0 /* ignored in userspace */ #define xfs_trans_set_sync(tp) ((void) 0) #define xfs_trans_agblocks_delta(tp, d) diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index e0513f699..9a48d9301 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -786,6 +786,7 @@ xfs_initialize_perag_data( uint64_t bfree = 0; uint64_t bfreelst = 0; uint64_t btree = 0; + uint64_t fdblocks; int error; for (index = 0; index < agcount; index++) { @@ -809,17 +810,31 @@ xfs_initialize_perag_data( btree += pag->pagf_btreeblks; xfs_perag_put(pag); } + fdblocks = bfree + bfreelst + btree; + + /* + * If the new summary counts are obviously incorrect, fail the + * mount operation because that implies the AGFs are also corrupt. + * Clear BAD_SUMMARY so that we don't unmount with a dirty log, which + * will prevent xfs_repair from fixing anything. + */ + if (fdblocks > sbp->sb_dblocks || ifree > ialloc) { + xfs_alert(mp, "AGF corruption. Please run xfs_repair."); + error = -EFSCORRUPTED; + goto out; + } /* Overwrite incore superblock counters with just-read data */ spin_lock(&mp->m_sb_lock); sbp->sb_ifree = ifree; sbp->sb_icount = ialloc; - sbp->sb_fdblocks = bfree + bfreelst + btree; + sbp->sb_fdblocks = fdblocks; spin_unlock(&mp->m_sb_lock); xfs_reinit_percpu_counters(mp); - - return 0; +out: + mp->m_flags &= ~XFS_MOUNT_BAD_SUMMARY; + return error; } /*