]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-4.19/btrfs-incremental-send-fix-file-corruption-when-no-holes-feature-is-enabled.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.19 / btrfs-incremental-send-fix-file-corruption-when-no-holes-feature-is-enabled.patch
CommitLineData
14e9555d
GKH
1From 6b1f72e5b82a5c2a4da4d1ebb8cc01913ddbea21 Mon Sep 17 00:00:00 2001
2From: Filipe Manana <fdmanana@suse.com>
3Date: Mon, 20 May 2019 09:55:42 +0100
4Subject: Btrfs: incremental send, fix file corruption when no-holes feature is enabled
5
6From: Filipe Manana <fdmanana@suse.com>
7
8commit 6b1f72e5b82a5c2a4da4d1ebb8cc01913ddbea21 upstream.
9
10When using the no-holes feature, if we have a file with prealloc extents
11with a start offset beyond the file's eof, doing an incremental send can
12cause corruption of the file due to incorrect hole detection. Such case
13requires that the prealloc extent(s) exist in both the parent and send
14snapshots, and that a hole is punched into the file that covers all its
15extents that do not cross the eof boundary.
16
17Example 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
53Fix this by ensuring we never cross the file's size when issuing the
54write operations for a hole.
55
56Fixes: 16e7549f045d33 ("Btrfs: incompatible format change to remove hole extents")
57CC: stable@vger.kernel.org # 3.14+
58Signed-off-by: Filipe Manana <fdmanana@suse.com>
59Signed-off-by: David Sterba <dsterba@suse.com>
60Signed-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