FS/XFS testing framework
 help / color / mirror / Atom feed
From: m00nb1rd lin <ljp1205831794@gmail.com>
To: "Darrick J. Wong" <djwong@kernel.org>
Cc: zlang@kernel.org, hch@lst.de, linux-xfs@vger.kernel.org,
	fstests@vger.kernel.org, jiapenglin@tencent.com
Subject: Re: [PATCH] xfs/842: verify CoW after exchangerange with FILE1_WRITTEN on shared extents
Date: Wed, 29 Jul 2026 10:12:43 +0800	[thread overview]
Message-ID: <dbdc8374-7eb2-44b1-9678-a5627d2cb5b5@gmail.com> (raw)
In-Reply-To: <20260728145946.GK2901224@frogsfrogsfrogs>



On 2026/7/28 22:59, Darrick J. Wong Wrote:
> On Tue, Jul 28, 2026 at 03:16:20PM +0800, Lin Jiapeng wrote:
>> When a full-file exchangerange is requested with FILE1_WRITTEN for a
>> fully sparse donor file, every mapping pair is skipped, so no extents
>> actually move.  However, the kernel decides to swap the reflink inode
>> flag based on the request geometry alone, so the target file used to
>> lose its reflink flag while still owning shared extents.  A subsequent
>> write then took the non-reflink write path and modified the shared
>> physical blocks in place, silently corrupting the other file sharing
>> them:
>>
>>   --- tests/xfs/842.out
>>   +++ results/xfs/842.out.bad
>>   @@ -1,2 +1,3 @@
>>    QA output created by 842
>>   +orig changed: md5 e6065c4aa2ab1603008fc18410f579d4 -> 32c5189478e6bafa1cc76423f06c88f2 (write hit shared blocks in place)
>>    Silence is golden
>>
>> This test clones a file so that both share extents, swaps the clone
>> against a sparse donor with FILE1_WRITTEN, writes to the clone, and
>> verifies after a mount cycle that the original file's data is intact,
>> i.e. the write was redirected through CoW.
>>
>> The kernel fix "xfs: fix exchange-range reflink flag clearing issue
>> with INO1_WRITTEN" refuses the reflink flag exchange whenever
>> FILE1_WRITTEN is requested, which makes this test pass.
>>
>> Reported-by: Lin Jiapeng(TencentOS Red Team) <jiapenglin@tencent.com>
>> Link: https://lore.kernel.org/r/amgekiNKKoAdACnc@infradead.org
>> Suggested-by: Christoph Hellwig <hch@lst.de>
>> Signed-off-by: Lin Jiapeng <jiapenglin@tencent.com>
>> ---
>>   tests/xfs/842     | 55 +++++++++++++++++++++++++++++++++++++++++++++++
>>   tests/xfs/842.out |  2 ++
>>   2 files changed, 57 insertions(+)
>>   create mode 100755 tests/xfs/842
>>   create mode 100644 tests/xfs/842.out
>>
>> diff --git a/tests/xfs/842 b/tests/xfs/842
>> new file mode 100755
>> index 0000000..6d5bcab
>> --- /dev/null
>> +++ b/tests/xfs/842
>> @@ -0,0 +1,55 @@
>> +#! /bin/bash
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +# Copyright (c) 2026 Tencent.  All Rights Reserved.
>> +#
>> +# FS QA Test No. 842
>> +#
>> +# Make sure that a full-file exchangerange under FILE1_WRITTEN does not strip
>> +# the reflink flag from a file that still owns shared extents.  When the
>> +# donor file is fully sparse, every mapping pair is skipped, so no extents
>> +# actually move; the target file must keep its reflink flag, and a later
>> +# write must go through CoW instead of modifying the shared blocks in place.
>> +
>> +. ./common/preamble
>> +_begin_fstest auto quick fiexchange
>> +
>> +# Import common functions.
>> +. ./common/filter
>> +. ./common/reflink
>> +
>> +_require_xfs_io_command exchangerange
>> +_require_scratch_reflink
>> +_require_scratch
>> +
>> +_scratch_mkfs >> $seqres.full
>> +_scratch_mount
>> +
>> +# Create the original file with a known pattern and clone it, so that both
>> +# files share the same extents.
>> +_pwrite_byte 0x41 0 1m $SCRATCH_MNT/orig >> $seqres.full
>> +_reflink $SCRATCH_MNT/orig $SCRATCH_MNT/clone >> $seqres.full
>> +
>> +# Create a fully sparse donor file of the same size.
>> +$XFS_IO_PROG -f -c 'truncate 1m' $SCRATCH_MNT/donor
> 
> Hehe, this is exactly the same sequence as the testcase I wrote
> yesterday afternoon, so the review is easy;
> 
> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
> 
> (For extra clarity I also had done:
> 
> # Check reflink flags
> _scratch_unmount
> _scratch_xfs_db -c "path /orig" -c 'print' -c "path /donor" -c 'print' | grep reflink
> _scratch_mount
> 
> for direct confirmation of the incorrect inode flag state, but the
> md5sum failure suffices to prove the defect.)
> 
> --D
> 
>> +
>> +md5_before=$(md5sum $SCRATCH_MNT/orig | awk '{print $1}')
>> +
>> +# Swap the clone against the sparse donor, claiming the donor is fully
>> +# written (-w).  Every donor mapping is a hole, so all pairs are skipped
>> +# and the clone keeps its shared extents in place.
>> +$XFS_IO_PROG -c "exchangerange -f -w $SCRATCH_MNT/donor" $SCRATCH_MNT/clone \
>> +	>> $seqres.full
>> +
>> +# Overwrite part of the clone.  With the reflink flag correctly retained,
>> +# this must go through CoW and leave the shared blocks of orig untouched.
>> +_pwrite_byte 0x42 0 64k $SCRATCH_MNT/clone >> $seqres.full
>> +_scratch_cycle_mount
>> +
>> +md5_after=$(md5sum $SCRATCH_MNT/orig | awk '{print $1}')
>> +
>> +test "$md5_before" != "$md5_after" && \
>> +	echo "orig changed: md5 $md5_before -> $md5_after (write hit shared blocks in place)"
>> +
>> +echo Silence is golden
>> +status=0
>> +exit
>> diff --git a/tests/xfs/842.out b/tests/xfs/842.out
>> new file mode 100644
>> index 0000000..643d052
>> --- /dev/null
>> +++ b/tests/xfs/842.out
>> @@ -0,0 +1,2 @@
>> +QA output created by 842
>> +Silence is golden
>> -- 
>> 2.50.1 (Apple Git-155)
>>
>>
Good idea! I will add direct confirmation of the incorrect inode flag 
state in Patch v2.

      reply	other threads:[~2026-07-29  2:12 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-28  7:16 [PATCH] xfs/842: verify CoW after exchangerange with FILE1_WRITTEN on shared extents Lin Jiapeng
2026-07-28 14:59 ` Darrick J. Wong
2026-07-29  2:12   ` m00nb1rd lin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dbdc8374-7eb2-44b1-9678-a5627d2cb5b5@gmail.com \
    --to=ljp1205831794@gmail.com \
    --cc=djwong@kernel.org \
    --cc=fstests@vger.kernel.org \
    --cc=hch@lst.de \
    --cc=jiapenglin@tencent.com \
    --cc=linux-xfs@vger.kernel.org \
    --cc=zlang@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox