]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.19/btrfs-incremental-send-fix-file-corruption-when-no-holes-feature-is-enabled.patch
fixes for 4.19
[thirdparty/kernel/stable-queue.git] / queue-4.19 / btrfs-incremental-send-fix-file-corruption-when-no-holes-feature-is-enabled.patch
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
5
6 From: Filipe Manana <fdmanana@suse.com>
7
8 commit 6b1f72e5b82a5c2a4da4d1ebb8cc01913ddbea21 upstream.
9
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.
16
17 Example reproducer:
18
19 $ mkfs.btrfs -f -O no-holes /dev/sdb
20 $ mount /dev/sdb /mnt/sdb
21
22 $ xfs_io -f -c "pwrite -S 0xab 0 500K" /mnt/sdb/foobar
23 $ xfs_io -c "falloc -k 1200K 800K" /mnt/sdb/foobar
24
25 $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/base
26
27 $ btrfs send -f /tmp/base.snap /mnt/sdb/base
28
29 $ xfs_io -c "fpunch 0 500K" /mnt/sdb/foobar
30
31 $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/incr
32
33 $ btrfs send -p /mnt/sdb/base -f /tmp/incr.snap /mnt/sdb/incr
34
35 $ md5sum /mnt/sdb/incr/foobar
36 816df6f64deba63b029ca19d880ee10a /mnt/sdb/incr/foobar
37
38 $ mkfs.btrfs -f /dev/sdc
39 $ mount /dev/sdc /mnt/sdc
40
41 $ btrfs receive -f /tmp/base.snap /mnt/sdc
42 $ btrfs receive -f /tmp/incr.snap /mnt/sdc
43
44 $ md5sum /mnt/sdc/incr/foobar
45 cf2ef71f4a9e90c2f6013ba3b2257ed2 /mnt/sdc/incr/foobar
46
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).
52
53 Fix this by ensuring we never cross the file's size when issuing the
54 write operations for a hole.
55
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>
61
62 ---
63 fs/btrfs/send.c | 6 ++++++
64 1 file changed, 6 insertions(+)
65
66 --- a/fs/btrfs/send.c
67 +++ b/fs/btrfs/send.c
68 @@ -5021,6 +5021,12 @@ static int send_hole(struct send_ctx *sc
69 if (offset >= sctx->cur_inode_size)
70 return 0;
71
72 + /*
73 + * Don't go beyond the inode's i_size due to prealloc extents that start
74 + * after the i_size.
75 + */
76 + end = min_t(u64, end, sctx->cur_inode_size);
77 +
78 if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA)
79 return send_update_extent(sctx, offset, end - offset);
80