Message ID | 20190520085542.29282-1-fdmanana@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Btrfs: incremental send, fix file corruption when no-holes feature is enabled | expand |
Hi, [This is an automated email] This commit has been processed because it contains a "Fixes:" tag, fixing commit: 16e7549f045d Btrfs: incompatible format change to remove hole extents. The bot has tested the following trees: v5.1.3, v5.0.17, v4.19.44, v4.14.120, v4.9.177, v4.4.180, v3.18.140. v5.1.3: Build OK! v5.0.17: Build OK! v4.19.44: Build OK! v4.14.120: Failed to apply! Possible dependencies: 22d3151c2c4c ("Btrfs: send, fix incorrect file layout after hole punching beyond eof") v4.9.177: Failed to apply! Possible dependencies: 22d3151c2c4c ("Btrfs: send, fix incorrect file layout after hole punching beyond eof") v4.4.180: Failed to apply! Possible dependencies: 22d3151c2c4c ("Btrfs: send, fix incorrect file layout after hole punching beyond eof") v3.18.140: Failed to apply! Possible dependencies: 22d3151c2c4c ("Btrfs: send, fix incorrect file layout after hole punching beyond eof") How should we proceed with this patch? -- Thanks, Sasha
On Mon, May 20, 2019 at 09:55:42AM +0100, fdmanana@kernel.org wrote: > From: Filipe Manana <fdmanana@suse.com> > > When using the no-holes feature, if we have a file with prealloc extents > with a start offset beyond the file's eof, doing an incremental send can > cause corruption of the file due to incorrect hole detection. Such case > requires that the prealloc extent(s) exist in both the parent and send > snapshots, and that a hole is punched into the file that covers all its > extents that do not cross the eof boundary. > > Example reproducer: > > $ mkfs.btrfs -f -O no-holes /dev/sdb > $ mount /dev/sdb /mnt/sdb > > $ xfs_io -f -c "pwrite -S 0xab 0 500K" /mnt/sdb/foobar > $ xfs_io -c "falloc -k 1200K 800K" /mnt/sdb/foobar > > $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/base > > $ btrfs send -f /tmp/base.snap /mnt/sdb/base > > $ xfs_io -c "fpunch 0 500K" /mnt/sdb/foobar > > $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/incr > > $ btrfs send -p /mnt/sdb/base -f /tmp/incr.snap /mnt/sdb/incr > > $ md5sum /mnt/sdb/incr/foobar > 816df6f64deba63b029ca19d880ee10a /mnt/sdb/incr/foobar > > $ mkfs.btrfs -f /dev/sdc > $ mount /dev/sdc /mnt/sdc > > $ btrfs receive -f /tmp/base.snap /mnt/sdc > $ btrfs receive -f /tmp/incr.snap /mnt/sdc > > $ md5sum /mnt/sdc/incr/foobar > cf2ef71f4a9e90c2f6013ba3b2257ed2 /mnt/sdc/incr/foobar > > --> Different checksum, because the prealloc extent beyond the > file's eof confused the hole detection code and it assumed > a hole starting at offset 0 and ending at the offset of the > prealloc extent (1200Kb) instead of ending at the offset > 500Kb (the file's size). > > Fix this by ensuring we never cross the file's size when issuing the > write operations for a hole. > > Fixes: 16e7549f045d33 ("Btrfs: incompatible format change to remove hole extents") > CC: stable@vger.kernel.org # 3.14+ > Signed-off-by: Filipe Manana <fdmanana@suse.com> Queued for 5.2-rc, thanks.
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index c5184691d7f2..1549d0639b57 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -4999,6 +4999,12 @@ static int send_hole(struct send_ctx *sctx, u64 end) if (offset >= sctx->cur_inode_size) return 0; + /* + * Don't go beyond the inode's i_size due to prealloc extents that start + * after the i_size. + */ + end = min_t(u64, end, sctx->cur_inode_size); + if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA) return send_update_extent(sctx, offset, end - offset);