linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] xfs: always init fdblocks in mount and avoid f_bfree overflow
@ 2020-03-16 13:07 Zheng Bin
  2020-03-16 13:07 ` [PATCH 1/2] xfs: always init fdblocks in mount Zheng Bin
  2020-03-16 13:07 ` [PATCH 2/2] xfs: avoid f_bfree overflow Zheng Bin
  0 siblings, 2 replies; 10+ messages in thread
From: Zheng Bin @ 2020-03-16 13:07 UTC (permalink / raw)
  To: bfoster, dchinner, sandeen, darrick.wong, linux-xfs; +Cc: yi.zhang, houtao1

Use buffer io to test xfs mount point:
cp file1M /mnt  -->just check fdblocks
sync            -->find suiteable AG, agf->agf_freeblks & agf->agf_longest

fdblocks may not be correct, if hackers use xfs_db to modify it, always
init fdblocks in mount, also avoid f_bfree overflow.

Zheng Bin (2):
  xfs: always init fdblocks in mount
  xfs: avoid f_bfree overflow

 fs/xfs/xfs_mount.c | 39 ++++++---------------------------------
 fs/xfs/xfs_super.c |  3 ++-
 2 files changed, 8 insertions(+), 34 deletions(-)

--
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/2] xfs: always init fdblocks in mount
  2020-03-16 13:07 [PATCH 0/2] xfs: always init fdblocks in mount and avoid f_bfree overflow Zheng Bin
@ 2020-03-16 13:07 ` Zheng Bin
  2020-03-16 15:13   ` Darrick J. Wong
  2020-03-16 18:10   ` Eric Sandeen
  2020-03-16 13:07 ` [PATCH 2/2] xfs: avoid f_bfree overflow Zheng Bin
  1 sibling, 2 replies; 10+ messages in thread
From: Zheng Bin @ 2020-03-16 13:07 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/xfs_mount.c | 33 ---------------------------------
 1 file changed, 33 deletions(-)

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] 10+ messages in thread

* [PATCH 2/2] xfs: avoid f_bfree overflow
  2020-03-16 13:07 [PATCH 0/2] xfs: always init fdblocks in mount and avoid f_bfree overflow Zheng Bin
  2020-03-16 13:07 ` [PATCH 1/2] xfs: always init fdblocks in mount Zheng Bin
@ 2020-03-16 13:07 ` Zheng Bin
  2020-03-17 18:32   ` Christoph Hellwig
  1 sibling, 1 reply; 10+ messages in thread
From: Zheng Bin @ 2020-03-16 13:07 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       13M  -64Z  -32K 100% /mnt

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] 10+ messages in thread

* Re: [PATCH 1/2] xfs: always init fdblocks in mount
  2020-03-16 13:07 ` [PATCH 1/2] xfs: always init fdblocks in mount Zheng Bin
@ 2020-03-16 15:13   ` Darrick J. Wong
  2020-03-17  1:39     ` zhengbin (A)
  2020-03-17  2:22     ` zhengbin (A)
  2020-03-16 18:10   ` Eric Sandeen
  1 sibling, 2 replies; 10+ messages in thread
From: Darrick J. Wong @ 2020-03-16 15:13 UTC (permalink / raw)
  To: Zheng Bin; +Cc: bfoster, dchinner, sandeen, linux-xfs, yi.zhang, houtao1

On Mon, Mar 16, 2020 at 09:07:07PM +0800, Zheng Bin wrote:
> 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.

Uh.... what are you saying here?  That the allocator misbehaves and
loops forever if sb_fdblocks > sum(agf_freeblks) after mount?

Also, uh, what do you mean by "sync not stuck"?  Writeback will fail on
allocation error, right...?  So I think the problem with incorrect AGF
contents (on upstream) is that writeback will fail due to ENOSPC, which
should never happen under normal circumstance?

> 
> 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/xfs_mount.c | 33 ---------------------------------
>  1 file changed, 33 deletions(-)
> 
> 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);

The downside of this is that now we /always/ have to make two trips
around all of the AGs at mount time.  If you're proposing to require a
fresh fdblocks recomputation at mount, could you please refactor all of
the mount-time AG walks into a single loop?  And perhaps use xfs_pwork
so that we don't have to do it serially?

--D

>  }
> 
> --
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] xfs: always init fdblocks in mount
  2020-03-16 13:07 ` [PATCH 1/2] xfs: always init fdblocks in mount Zheng Bin
  2020-03-16 15:13   ` Darrick J. Wong
@ 2020-03-16 18:10   ` Eric Sandeen
  1 sibling, 0 replies; 10+ messages in thread
From: Eric Sandeen @ 2020-03-16 18:10 UTC (permalink / raw)
  To: Zheng Bin, bfoster, dchinner, darrick.wong, linux-xfs; +Cc: yi.zhang, houtao1

On 3/16/20 8:07 AM, Zheng Bin wrote:
> 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.

Is there any observable problem on linux-next?  I can't tell.  Can you
provide an image that demonstrates this problem?

-Eric

> 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/xfs_mount.c | 33 ---------------------------------
>  1 file changed, 33 deletions(-)
> 
> 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	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] xfs: always init fdblocks in mount
  2020-03-16 15:13   ` Darrick J. Wong
@ 2020-03-17  1:39     ` zhengbin (A)
  2020-03-17  2:22     ` zhengbin (A)
  1 sibling, 0 replies; 10+ messages in thread
From: zhengbin (A) @ 2020-03-17  1:39 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: bfoster, dchinner, sandeen, linux-xfs, yi.zhang, houtao1


On 2020/3/16 23:13, Darrick J. Wong wrote:
> On Mon, Mar 16, 2020 at 09:07:07PM +0800, Zheng Bin wrote:
>> 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.
> Uh.... what are you saying here?  That the allocator misbehaves and
> loops forever if sb_fdblocks > sum(agf_freeblks) after mount?
>
> Also, uh, what do you mean by "sync not stuck"?  Writeback will fail on
> allocation error, right...?  So I think the problem with incorrect AGF
> contents (on upstream) is that writeback will fail due to ENOSPC, which
> should never happen under normal circumstance?

Yes, see commit d0c7feaf8767 ("xfs: add agf freeblocks verify in xfs_agf_verify")

4.19-stable loops forerver, while linux-next will fail due to ENOSPC, cause commit

c2b3164320b5 ("xfs: use the latest extent at writeback delalloc conversion time") remove
the above while, dmesg is as follows:
[   55.250114] XFS (loop0): page discard on page ffffea0008bc7380, inode 0x1b0c, offset 0.


@sandeen, 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
agf 0
write freeblks 0
write longest 0
quit

>> 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/xfs_mount.c | 33 ---------------------------------
>>  1 file changed, 33 deletions(-)
>>
>> 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);
> The downside of this is that now we /always/ have to make two trips
> around all of the AGs at mount time.  If you're proposing to require a
> fresh fdblocks recomputation at mount, could you please refactor all of
> the mount-time AG walks into a single loop?  And perhaps use xfs_pwork
> so that we don't have to do it serially?
>
> --D
>
>>  }
>>
>> --
>> 2.7.4
>>
> .
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] xfs: always init fdblocks in mount
  2020-03-16 15:13   ` Darrick J. Wong
  2020-03-17  1:39     ` zhengbin (A)
@ 2020-03-17  2:22     ` zhengbin (A)
  2020-03-17  3:55       ` Darrick J. Wong
  1 sibling, 1 reply; 10+ messages in thread
From: zhengbin (A) @ 2020-03-17  2:22 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: bfoster, dchinner, sandeen, linux-xfs, yi.zhang, houtao1


On 2020/3/16 23:13, Darrick J. Wong wrote:
> On Mon, Mar 16, 2020 at 09:07:07PM +0800, Zheng Bin wrote:
>> 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.
> Uh.... what are you saying here?  That the allocator misbehaves and
> loops forever if sb_fdblocks > sum(agf_freeblks) after mount?
>
> Also, uh, what do you mean by "sync not stuck"?  Writeback will fail on
> allocation error, right...?  So I think the problem with incorrect AGF
> contents (on upstream) is that writeback will fail due to ENOSPC, which
> should never happen under normal circumstance?
>
>> 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/xfs_mount.c | 33 ---------------------------------
>>  1 file changed, 33 deletions(-)
>>
>> 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);
> The downside of this is that now we /always/ have to make two trips
> around all of the AGs at mount time.  If you're proposing to require a
> fresh fdblocks recomputation at mount, could you please refactor all of
> the mount-time AG walks into a single loop?  And perhaps use xfs_pwork
> so that we don't have to do it serially?
xfs_mountfs
  xfs_initialize_perag         -->just alloc memory
  xfs_check_summary_counts
    xfs_initialize_perag_data  -->read agf,agi from disk
      for (index = 0; index < agcount; index++)
        error = xfs_alloc_pagf_init(mp, NULL, index, 0)
        error = xfs_ialloc_pagi_init(mp, NULL, index)
  xfs_fs_reserve_ag_blocks
    for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
      xfs_ag_resv_init
        #ifdef DEBUG  -->read agf
          error = xfs_alloc_pagf_init(pag->pag_mount, tp, pag->pag_agno, 0)
        #endif

Is this? if enable XFS_DEBUG, xfs_initialize_perag_data read agf, xfs_ag_resv_init

also read agf?

>
> --D
>
>>  }
>>
>> --
>> 2.7.4
>>
> .
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] xfs: always init fdblocks in mount
  2020-03-17  2:22     ` zhengbin (A)
@ 2020-03-17  3:55       ` Darrick J. Wong
  2020-03-17  4:18         ` zhengbin (A)
  0 siblings, 1 reply; 10+ messages in thread
From: Darrick J. Wong @ 2020-03-17  3:55 UTC (permalink / raw)
  To: zhengbin (A); +Cc: bfoster, dchinner, sandeen, linux-xfs, yi.zhang, houtao1

On Tue, Mar 17, 2020 at 10:22:33AM +0800, zhengbin (A) wrote:
> 
> On 2020/3/16 23:13, Darrick J. Wong wrote:
> > On Mon, Mar 16, 2020 at 09:07:07PM +0800, Zheng Bin wrote:
> >> 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.
> > Uh.... what are you saying here?  That the allocator misbehaves and
> > loops forever if sb_fdblocks > sum(agf_freeblks) after mount?
> >
> > Also, uh, what do you mean by "sync not stuck"?  Writeback will fail on
> > allocation error, right...?  So I think the problem with incorrect AGF
> > contents (on upstream) is that writeback will fail due to ENOSPC, which
> > should never happen under normal circumstance?
> >
> >> 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/xfs_mount.c | 33 ---------------------------------
> >>  1 file changed, 33 deletions(-)
> >>
> >> 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);
> > The downside of this is that now we /always/ have to make two trips
> > around all of the AGs at mount time.  If you're proposing to require a
> > fresh fdblocks recomputation at mount, could you please refactor all of
> > the mount-time AG walks into a single loop?  And perhaps use xfs_pwork
> > so that we don't have to do it serially?
> xfs_mountfs
>   xfs_initialize_perag         -->just alloc memory
>   xfs_check_summary_counts
>     xfs_initialize_perag_data  -->read agf,agi from disk
>       for (index = 0; index < agcount; index++)
>         error = xfs_alloc_pagf_init(mp, NULL, index, 0)
>         error = xfs_ialloc_pagi_init(mp, NULL, index)
>   xfs_fs_reserve_ag_blocks
>     for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
>       xfs_ag_resv_init
>         #ifdef DEBUG  -->read agf
>           error = xfs_alloc_pagf_init(pag->pag_mount, tp, pag->pag_agno, 0)
>         #endif
> 
> Is this? if enable XFS_DEBUG, xfs_initialize_perag_data read agf, xfs_ag_resv_init
> 
> also read agf?

Yes, that's the other AG-walker that I was referring to.

--D

> 
> >
> > --D
> >
> >>  }
> >>
> >> --
> >> 2.7.4
> >>
> > .
> >
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] xfs: always init fdblocks in mount
  2020-03-17  3:55       ` Darrick J. Wong
@ 2020-03-17  4:18         ` zhengbin (A)
  0 siblings, 0 replies; 10+ messages in thread
From: zhengbin (A) @ 2020-03-17  4:18 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: bfoster, dchinner, sandeen, linux-xfs, yi.zhang, houtao1


On 2020/3/17 11:55, Darrick J. Wong wrote:
> On Tue, Mar 17, 2020 at 10:22:33AM +0800, zhengbin (A) wrote:
>> On 2020/3/16 23:13, Darrick J. Wong wrote:
>>> On Mon, Mar 16, 2020 at 09:07:07PM +0800, Zheng Bin wrote:
>>>> 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.
>>> Uh.... what are you saying here?  That the allocator misbehaves and
>>> loops forever if sb_fdblocks > sum(agf_freeblks) after mount?
>>>
>>> Also, uh, what do you mean by "sync not stuck"?  Writeback will fail on
>>> allocation error, right...?  So I think the problem with incorrect AGF
>>> contents (on upstream) is that writeback will fail due to ENOSPC, which
>>> should never happen under normal circumstance?
>>>
>>>> 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/xfs_mount.c | 33 ---------------------------------
>>>>  1 file changed, 33 deletions(-)
>>>>
>>>> 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);
>>> The downside of this is that now we /always/ have to make two trips
>>> around all of the AGs at mount time.  If you're proposing to require a
>>> fresh fdblocks recomputation at mount, could you please refactor all of
>>> the mount-time AG walks into a single loop?  And perhaps use xfs_pwork
>>> so that we don't have to do it serially?
>> xfs_mountfs
>>   xfs_initialize_perag         -->just alloc memory
>>   xfs_check_summary_counts
>>     xfs_initialize_perag_data  -->read agf,agi from disk
>>       for (index = 0; index < agcount; index++)
>>         error = xfs_alloc_pagf_init(mp, NULL, index, 0)
>>         error = xfs_ialloc_pagi_init(mp, NULL, index)
>>   xfs_fs_reserve_ag_blocks
>>     for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
>>       xfs_ag_resv_init
>>         #ifdef DEBUG  -->read agf
>>           error = xfs_alloc_pagf_init(pag->pag_mount, tp, pag->pag_agno, 0)
>>         #endif
>>
>> Is this? if enable XFS_DEBUG, xfs_initialize_perag_data read agf, xfs_ag_resv_init
>>
>> also read agf?
> Yes, that's the other AG-walker that I was referring to.

Maybe we can judge if (!pag->pagf_init) in xfs_ag_resv_init?

xfs_fs_reserve_ag_blocks
  for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
    xfs_ag_resv_init
      #ifdef DEBUG  -->read agf
      if (!pag->pagf_init) {
        error = xfs_alloc_pagf_init(pag->pag_mount, tp, pag->pag_agno, 0)
      }
>
> --D
>
>>> --D
>>>
>>>>  }
>>>>
>>>> --
>>>> 2.7.4
>>>>
>>> .
>>>
> .
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] xfs: avoid f_bfree overflow
  2020-03-16 13:07 ` [PATCH 2/2] xfs: avoid f_bfree overflow Zheng Bin
@ 2020-03-17 18:32   ` Christoph Hellwig
  0 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2020-03-17 18:32 UTC (permalink / raw)
  To: Zheng Bin
  Cc: bfoster, dchinner, sandeen, darrick.wong, linux-xfs, yi.zhang,
	houtao1

> +	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);

How can this happen with the above hunk applies?  And even if we'd
need to do the sanity chck it shold be two separate patches.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-03-17 18:32 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-03-16 13:07 [PATCH 0/2] xfs: always init fdblocks in mount and avoid f_bfree overflow Zheng Bin
2020-03-16 13:07 ` [PATCH 1/2] xfs: always init fdblocks in mount Zheng Bin
2020-03-16 15:13   ` Darrick J. Wong
2020-03-17  1:39     ` zhengbin (A)
2020-03-17  2:22     ` zhengbin (A)
2020-03-17  3:55       ` Darrick J. Wong
2020-03-17  4:18         ` zhengbin (A)
2020-03-16 18:10   ` Eric Sandeen
2020-03-16 13:07 ` [PATCH 2/2] xfs: avoid f_bfree overflow Zheng Bin
2020-03-17 18:32   ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).