1 From 6b1f72e5b82a5c2a4da4d1ebb8cc01913ddbea21 Mon Sep 17 00:00:00 2001
2 From: Filipe Manana <fdmanana@suse.com>
3 Date: Mon, 20 May 2019 09:55:42 +0100
4 Subject: Btrfs: incremental send, fix file corruption when no-holes feature is enabled
6 From: Filipe Manana <fdmanana@suse.com>
8 commit 6b1f72e5b82a5c2a4da4d1ebb8cc01913ddbea21 upstream.
10 When using the no-holes feature, if we have a file with prealloc extents
11 with a start offset beyond the file's eof, doing an incremental send can
12 cause corruption of the file due to incorrect hole detection. Such case
13 requires that the prealloc extent(s) exist in both the parent and send
14 snapshots, and that a hole is punched into the file that covers all its
15 extents that do not cross the eof boundary.
19 $ mkfs.btrfs -f -O no-holes /dev/sdb
20 $ mount /dev/sdb /mnt/sdb
22 $ xfs_io -f -c "pwrite -S 0xab 0 500K" /mnt/sdb/foobar
23 $ xfs_io -c "falloc -k 1200K 800K" /mnt/sdb/foobar
25 $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/base
27 $ btrfs send -f /tmp/base.snap /mnt/sdb/base
29 $ xfs_io -c "fpunch 0 500K" /mnt/sdb/foobar
31 $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/incr
33 $ btrfs send -p /mnt/sdb/base -f /tmp/incr.snap /mnt/sdb/incr
35 $ md5sum /mnt/sdb/incr/foobar
36 816df6f64deba63b029ca19d880ee10a /mnt/sdb/incr/foobar
38 $ mkfs.btrfs -f /dev/sdc
39 $ mount /dev/sdc /mnt/sdc
41 $ btrfs receive -f /tmp/base.snap /mnt/sdc
42 $ btrfs receive -f /tmp/incr.snap /mnt/sdc
44 $ md5sum /mnt/sdc/incr/foobar
45 cf2ef71f4a9e90c2f6013ba3b2257ed2 /mnt/sdc/incr/foobar
47 --> Different checksum, because the prealloc extent beyond the
48 file's eof confused the hole detection code and it assumed
49 a hole starting at offset 0 and ending at the offset of the
50 prealloc extent (1200Kb) instead of ending at the offset
51 500Kb (the file's size).
53 Fix this by ensuring we never cross the file's size when issuing the
54 write operations for a hole.
56 Fixes: 16e7549f045d33 ("Btrfs: incompatible format change to remove hole extents")
57 CC: stable@vger.kernel.org # 3.14+
58 Signed-off-by: Filipe Manana <fdmanana@suse.com>
59 Signed-off-by: David Sterba <dsterba@suse.com>
60 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
63 fs/btrfs/send.c | 6 ++++++
64 1 file changed, 6 insertions(+)
68 @@ -5021,6 +5021,12 @@ static int send_hole(struct send_ctx *sc
69 if (offset >= sctx->cur_inode_size)
73 + * Don't go beyond the inode's i_size due to prealloc extents that start
76 + end = min_t(u64, end, sctx->cur_inode_size);
78 if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA)
79 return send_update_extent(sctx, offset, end - offset);