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.