diff options
author | David P <megver83@parabola.nu> | 2020-02-10 11:32:32 -0300 |
---|---|---|
committer | David P <megver83@parabola.nu> | 2020-02-10 11:32:32 -0300 |
commit | 0da6a95ac24f166b1585d132d7737d333f47bae2 (patch) | |
tree | f4c1c26ad8784874eccd14d5e28b0b961d3604d1 /libre/linux-libre-pae/0004-Btrfs-send-fix-emission-of-invalid-clone-operations-.patch | |
parent | db67d270b3c02f3406cdb213ad8675ca1a92265b (diff) | |
download | abslibre-0da6a95ac24f166b1585d132d7737d333f47bae2.tar.gz abslibre-0da6a95ac24f166b1585d132d7737d333f47bae2.tar.bz2 abslibre-0da6a95ac24f166b1585d132d7737d333f47bae2.zip |
updpkg: libre/linux-libre-pae 5.5.2-1
Signed-off-by: David P <megver83@parabola.nu>
Diffstat (limited to 'libre/linux-libre-pae/0004-Btrfs-send-fix-emission-of-invalid-clone-operations-.patch')
-rw-r--r-- | libre/linux-libre-pae/0004-Btrfs-send-fix-emission-of-invalid-clone-operations-.patch | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/libre/linux-libre-pae/0004-Btrfs-send-fix-emission-of-invalid-clone-operations-.patch b/libre/linux-libre-pae/0004-Btrfs-send-fix-emission-of-invalid-clone-operations-.patch new file mode 100644 index 000000000..26c10a8df --- /dev/null +++ b/libre/linux-libre-pae/0004-Btrfs-send-fix-emission-of-invalid-clone-operations-.patch @@ -0,0 +1,92 @@ +From d0910be3493b40233c513c9ad01ac0878ae26a48 Mon Sep 17 00:00:00 2001 +From: Filipe Manana <fdmanana@suse.com> +Date: Wed, 29 Jan 2020 17:09:53 +0000 +Subject: [PATCH 4/5] Btrfs: send, fix emission of invalid clone operations + within the same file + +When doing an incremental send and a file has extents shared with itself +at different file offsets, it's possible for send to emit clone operations +that will fail at the destination because the source range goes beyond the +file's current size. This happens when the file size has increased in the +send snapshot, there is a hole between the shared extents and both shared +extents are at file offsets which are greater the file's size in the +parent snapshot. + +Example: + + $ mkfs.btrfs -f /dev/sdb + $ mount /dev/sdb /mnt/sdb + + $ xfs_io -f -c "pwrite -S 0xf1 0 64K" /mnt/sdb/foobar + $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/base + $ btrfs send -f /tmp/1.snap /mnt/sdb/base + + # Create a 320K extent at file offset 512K. + $ xfs_io -c "pwrite -S 0xab 512K 64K" /mnt/sdb/foobar + $ xfs_io -c "pwrite -S 0xcd 576K 64K" /mnt/sdb/foobar + $ xfs_io -c "pwrite -S 0xef 640K 64K" /mnt/sdb/foobar + $ xfs_io -c "pwrite -S 0x64 704K 64K" /mnt/sdb/foobar + $ xfs_io -c "pwrite -S 0x73 768K 64K" /mnt/sdb/foobar + + # Clone part of that 320K extent into a lower file offset (192K). + # This file offset is greater than the file's size in the parent + # snapshot (64K). Also the clone range is a bit behind the offset of + # the 320K extent so that we leave a hole between the shared extents. + $ xfs_io -c "reflink /mnt/sdb/foobar 448K 192K 192K" /mnt/sdb/foobar + + $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/incr + $ btrfs send -p /mnt/sdb/base -f /tmp/2.snap /mnt/sdb/incr + + $ mkfs.btrfs -f /dev/sdc + $ mount /dev/sdc /mnt/sdc + + $ btrfs receive -f /tmp/1.snap /mnt/sdc + $ btrfs receive -f /tmp/2.snap /mnt/sdc + ERROR: failed to clone extents to foobar: Invalid argument + +The problem is that after processing the extent at file offset 256K, which +refers to the first 128K of the 320K extent created by the buffered write +operations, we have 'cur_inode_next_write_offset' set to 384K, which +corresponds to the end offset of the partially shared extent (256K + 128K) +and to the current file size in the receiver. Then when we process the +extent at offset 512K, we do extent backreference iteration to figure out +if we can clone the extent from some other inode or from the same inode, +and we consider the extent at offset 256K of the same inode as a valid +source for a clone operation, which is not correct because at that point +the current file size in the receiver is 384K, which corresponds to the +end of last processed extent (at file offset 256K), so using a clone +source range from 256K to 256K + 320K is invalid because that goes past +the current size of the file (384K) - this makes the receiver get an +-EINVAL error when attempting the clone operation. + +So fix this by excluding clone sources that have a range that goes beyond +the current file size in the receiver when iterating extent backreferences. + +A test case for fstests follows soon. + +Fixes: 11f2069c113e02 ("Btrfs: send, allow clone operations within the same file") +CC: stable@vger.kernel.org # 5.5+ +Reviewed-by: Josef Bacik <josef@toxicpanda.com> +Signed-off-by: Filipe Manana <fdmanana@suse.com> +Signed-off-by: David Sterba <dsterba@suse.com> +--- + fs/btrfs/send.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c +index 091e5bc8c7ea..a055b657cb85 100644 +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -1269,7 +1269,8 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_) + * destination of the stream. + */ + if (ino == bctx->cur_objectid && +- offset >= bctx->sctx->cur_inode_next_write_offset) ++ offset + bctx->extent_len > ++ bctx->sctx->cur_inode_next_write_offset) + return 0; + } + +-- +2.25.0 + |