* [PATCH v2 0/2] xfs: always init fdblocks in mount and avoid f_bfree overflow
@ 2020-03-17 7:05 Zheng Bin
2020-03-17 7:05 ` [PATCH v2 1/2] xfs: always init fdblocks in mount Zheng Bin
2020-03-17 7:05 ` [PATCH v2 2/2] xfs: avoid f_bfree overflow Zheng Bin
0 siblings, 2 replies; 4+ messages in thread
From: Zheng Bin @ 2020-03-17 7:05 UTC (permalink / raw)
To: bfoster, dchinner, sandeen, darrick.wong, linux-xfs; +Cc: yi.zhang, houtao1
v1->v2: modify comment, add is agf inited judge in xfs_ag_resv_init
Zheng Bin (2):
xfs: always init fdblocks in mount
xfs: avoid f_bfree overflow
fs/xfs/libxfs/xfs_ag_resv.c | 11 +++++++----
fs/xfs/xfs_mount.c | 39 ++++++---------------------------------
fs/xfs/xfs_super.c | 3 ++-
3 files changed, 15 insertions(+), 38 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/2] xfs: always init fdblocks in mount
2020-03-17 7:05 [PATCH v2 0/2] xfs: always init fdblocks in mount and avoid f_bfree overflow Zheng Bin
@ 2020-03-17 7:05 ` Zheng Bin
2020-03-17 19:01 ` Christoph Hellwig
2020-03-17 7:05 ` [PATCH v2 2/2] xfs: avoid f_bfree overflow Zheng Bin
1 sibling, 1 reply; 4+ messages in thread
From: Zheng Bin @ 2020-03-17 7:05 UTC (permalink / raw)
To: bfoster, dchinner, sandeen, darrick.wong, linux-xfs; +Cc: yi.zhang, houtao1
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>
---
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 fdfe6dc..487961b 100644
--- a/fs/xfs/libxfs/xfs_ag_resv.c
+++ b/fs/xfs/libxfs/xfs_ag_resv.c
@@ -303,10 +303,13 @@ xfs_ag_resv_init(
}
#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 c5513e5..dc41801 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -594,39 +594,6 @@ xfs_check_summary_counts(
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))
- xfs_fs_mark_sick(mp, XFS_SICK_FS_COUNTERS);
-
- /*
- * 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)) &&
- !xfs_fs_has_sickness(mp, XFS_SICK_FS_COUNTERS))
- return 0;
-
return xfs_initialize_perag_data(mp, mp->m_sb.sb_agcount);
}
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] xfs: avoid f_bfree overflow
2020-03-17 7:05 [PATCH v2 0/2] xfs: always init fdblocks in mount and avoid f_bfree overflow Zheng Bin
2020-03-17 7:05 ` [PATCH v2 1/2] xfs: always init fdblocks in mount Zheng Bin
@ 2020-03-17 7:05 ` Zheng Bin
1 sibling, 0 replies; 4+ messages in thread
From: Zheng Bin @ 2020-03-17 7:05 UTC (permalink / raw)
To: bfoster, dchinner, sandeen, darrick.wong, linux-xfs; +Cc: yi.zhang, houtao1
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.
PS: add fdblocks check in mount.
Signed-off-by: Zheng Bin <zhengbin13@huawei.com>
---
fs/xfs/xfs_mount.c | 6 ++++++
fs/xfs/xfs_super.c | 3 ++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index dc41801..a223af4 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -816,6 +816,12 @@ xfs_mountfs(
if (error)
goto out_log_dealloc;
+ if (sbp->sb_fdblocks < mp->m_alloc_set_aside) {
+ xfs_alert(mp, "Corruption detected. Please run xfs_repair.");
+ error = -EFSCORRUPTED;
+ goto out_log_dealloc;
+ }
+
/*
* Get and sanity-check the root inode.
* Save the pointer to it in the mount structure.
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 2094386..9dcf772 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -755,7 +755,8 @@ xfs_fs_statfs(
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 = XFS_FSB_TO_INO(mp, statp->f_bfree);
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] xfs: always init fdblocks in mount
2020-03-17 7:05 ` [PATCH v2 1/2] xfs: always init fdblocks in mount Zheng Bin
@ 2020-03-17 19:01 ` Christoph Hellwig
0 siblings, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2020-03-17 19:01 UTC (permalink / raw)
To: Zheng Bin
Cc: bfoster, dchinner, sandeen, darrick.wong, linux-xfs, yi.zhang, houtao1
So if we can't trust the sb counters on your fuzzed file system,
how can we trust the AG counters?
Also if we decide that we always want to rebuild and thus always read
in the pagf all the pagf_init checks can go away..
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-03-17 19:01 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-17 7:05 [PATCH v2 0/2] xfs: always init fdblocks in mount and avoid f_bfree overflow Zheng Bin
2020-03-17 7:05 ` [PATCH v2 1/2] xfs: always init fdblocks in mount Zheng Bin
2020-03-17 19:01 ` Christoph Hellwig
2020-03-17 7:05 ` [PATCH v2 2/2] xfs: avoid f_bfree overflow Zheng Bin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.