On Tue, Feb 16, 2021 at 03:43:22PM -0500, Josef Bacik wrote:
> The tree checker checks the extent ref hash at read and write time to
> make sure we do not corrupt the file system.  Generally extent
> references go inline, but if we have enough of them we need to make an
> item, which looks like
> 
> key.objectid  = <bytenr>
> key.type      = <BTRFS_EXTENT_DATA_REF_KEY|BTRFS_TREE_BLOCK_REF_KEY>
> key.offset    = hash(tree, owner, offset)
> 
> However if key.offset collide with an unrelated extent reference we'll
> simply key.offset++ until we get something that doesn't collide.
> Obviously this doesn't match at tree checker time, and thus we error
> while writing out the transaction.  This is relatively easy to
> reproduce, simply do something like the following
> 
> xfs_io -f -c "pwrite 0 1M" file
> offset=2
> 
> for i in {0..10000}
> do
>       xfs_io -c "reflink file 0 ${offset}M 1M" file
>       offset=$(( offset + 2 ))
> done
> 
> xfs_io -c "reflink file 0 17999258914816 1M" file
> xfs_io -c "reflink file 0 35998517829632 1M" file
> xfs_io -c "reflink file 0 53752752058368 1M" file
> 
> btrfs filesystem sync
> 
> And the sync will error out because we'll abort the transaction.  The
> magic values above are used because they generate hash collisions with
> the first file in the main subvol.
> 
> The fix for this is to remove the hash value check from tree checker, as
> we have no idea which offset ours should belong to.
> 
> Reported-by: Tuomas Lähdekorpi <tuomas.lahdeko...@gmail.com>
> Signed-off-by: Josef Bacik <jo...@toxicpanda.com>

Thanks, I've added a comment stating that we can't check the hash there.

Reply via email to