[PATCH 1/2] xfs: always init fdblocks in mount

From: Zheng Bin <zhengbin13@huawei.com> hulk inclusion category: bugfix bugzilla: 31088 CVE: NA --------------------------- Use fuzz(hydra) to test XFS and automatically generate tmp.img(XFS v5 format, but some metadata is wrong) xfs_repair information(just one AG): agf_freeblks 0, counted 3224 in ag 0 agf_longest 0, counted 3224 in ag 0 sb_fdblocks 3228, counted 3224 Test as follows: mount tmp.img tmpdir cp file1M tmpdir sync In 4.19-stable, sync will stuck, while in linux-next, sync not stuck. The reason is same to commit d0c7feaf8767 ("xfs: add agf freeblocks verify in xfs_agf_verify"), cause agf_longest is 0, we can not block this in xfs_agf_verify. Make sure fdblocks is always inited in mount(also init ifree, icount). xfs_mountfs xfs_check_summary_counts xfs_initialize_perag_data Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Reviewed-by: Hou Tao <houtao1@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> --- fs/xfs/libxfs/xfs_ag_resv.c | 11 +++++++---- fs/xfs/xfs_mount.c | 33 --------------------------------- 2 files changed, 7 insertions(+), 37 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c index e2ba2a3..4f099fc 100644 --- a/fs/xfs/libxfs/xfs_ag_resv.c +++ b/fs/xfs/libxfs/xfs_ag_resv.c @@ -309,10 +309,13 @@ } #ifdef DEBUG - /* need to read in the AGF for the ASSERT below to work */ - error = xfs_alloc_pagf_init(pag->pag_mount, tp, pag->pag_agno, 0); - if (error) - return error; + if (!pag->pagf_init) { + /* need to read in the AGF for the ASSERT below to work */ + error = xfs_alloc_pagf_init(pag->pag_mount, tp, + pag->pag_agno, 0); + if (error) + return error; + } ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved + xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved <= diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 02d1509..3af91e2 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -624,39 +624,6 @@ return -EFSCORRUPTED; } - /* - * Now the log is mounted, we know if it was an unclean shutdown or - * not. If it was, with the first phase of recovery has completed, we - * have consistent AG blocks on disk. We have not recovered EFIs yet, - * but they are recovered transactionally in the second recovery phase - * later. - * - * If the log was clean when we mounted, we can check the summary - * counters. If any of them are obviously incorrect, we can recompute - * them from the AGF headers in the next step. - */ - if (XFS_LAST_UNMOUNT_WAS_CLEAN(mp) && - (mp->m_sb.sb_fdblocks > mp->m_sb.sb_dblocks || - !xfs_verify_icount(mp, mp->m_sb.sb_icount) || - mp->m_sb.sb_ifree > mp->m_sb.sb_icount)) - mp->m_flags |= XFS_MOUNT_BAD_SUMMARY; - - /* - * We can safely re-initialise incore superblock counters from the - * per-ag data. These may not be correct if the filesystem was not - * cleanly unmounted, so we waited for recovery to finish before doing - * this. - * - * If the filesystem was cleanly unmounted or the previous check did - * not flag anything weird, then we can trust the values in the - * superblock to be correct and we don't need to do anything here. - * Otherwise, recalculate the summary counters. - */ - if ((!xfs_sb_version_haslazysbcount(&mp->m_sb) || - XFS_LAST_UNMOUNT_WAS_CLEAN(mp)) && - !(mp->m_flags & XFS_MOUNT_BAD_SUMMARY)) - return 0; - return xfs_initialize_perag_data(mp, mp->m_sb.sb_agcount); } -- 1.8.3

From: Zheng Bin <zhengbin13@huawei.com> hulk inclusion category: bugfix bugzilla: 31088 CVE: NA --------------------------- If fdblocks < mp->m_alloc_set_aside, statp->f_bfree will overflow. When we df -h /mnt(xfs mount point), will show this: Filesystem Size Used Avail Use% Mounted on /dev/loop0 17M -64Z -32K 100% /mnt We can construct an img like this: dd if=/dev/zero of=xfs.img bs=1M count=20 mkfs.xfs -d agcount=1 xfs.img xfs_db -x xfs.img sb 0 write fdblocks 0 agf 0 write freeblks 0 write longest 0 quit Make sure statp->f_bfree does not underflow. Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Reviewed-by: Hou Tao <houtao1@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> --- fs/xfs/xfs_super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index dce8114..e126bc6 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1114,7 +1114,8 @@ struct proc_xfs_info { statp->f_blocks = sbp->sb_dblocks - lsize; spin_unlock(&mp->m_sb_lock); - statp->f_bfree = fdblocks - mp->m_alloc_set_aside; + /* make sure statp->f_bfree does not underflow */ + statp->f_bfree = max_t(int64_t, fdblocks - mp->m_alloc_set_aside, 0); statp->f_bavail = statp->f_bfree; fakeinos = statp->f_bfree << sbp->sb_inopblog; -- 1.8.3
participants (1)
-
Yang Yingliang