summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--0003-btrfs-send-fix-emission-of-invalid-clone-operations-within-the-same.patch114
-rw-r--r--PKGBUILD9
-rw-r--r--config2
3 files changed, 122 insertions, 3 deletions
diff --git a/0003-btrfs-send-fix-emission-of-invalid-clone-operations-within-the-same.patch b/0003-btrfs-send-fix-emission-of-invalid-clone-operations-within-the-same.patch
new file mode 100644
index 0000000..496cc6f
--- /dev/null
+++ b/0003-btrfs-send-fix-emission-of-invalid-clone-operations-within-the-same.patch
@@ -0,0 +1,114 @@
+From 693469a2b9d6d27282c06ed55cb70ff648740efd Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 24 Jan 2020 11:52:04 +0000
+Subject: 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 192K, send
+does not issue a write operation full of zeroes for the hole between that
+extent and the extent starting at file offset 520K (hole range from 384K
+to 512K), this is because the hole is at an offset larger the size of the
+file in the parent snapshot (384K > 64K). As a consequence the field
+'cur_inode_next_write_offset' of the send context remains with a value of
+384K when we start to process the extent at file offset 512K, which is the
+value set after processing the extent at offset 192K.
+
+This screws up the lookup of possible extents to clone because due to an
+incorrect value of 'cur_inode_next_write_offset' we can now consider
+extents for cloning, in the same inode, that lie beyond the current size
+of the file in the receiver of the send stream. Also, when checking if
+an extent in the same file can be used for cloning, we must also check
+that not only its start offset doesn't start at or beyond the current eof
+of the file in the receiver but that the source range doesn't go beyond
+current eof, that is we must check offset + length does not cross the
+current eof, as that makes clone operations fail with -EINVAL.
+
+So fix this by updating 'cur_inode_next_write_offset' whenever we start
+processing an extent and checking an extent's offset and length when
+considering it for cloning operations.
+
+A test case for fstests follows soon.
+
+Fixes: 11f2069c113e02 ("Btrfs: send, allow clone operations within the same file")
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+---
+ fs/btrfs/send.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
+index 091e5bc8c7ea..0b42dac8a35f 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;
+ }
+
+@@ -5804,6 +5805,18 @@ static int process_extent(struct send_ctx *sctx,
+ }
+ }
+
++ /*
++ * There might be a hole between the end of the last processed extent
++ * and this extent, and we may have not sent a write operation for that
++ * hole because it was not needed (range is beyond eof in the parent
++ * snapshot). So adjust the next write offset to the offset of this
++ * extent, as we want to make sure we don't do mistakes when checking if
++ * we can clone this extent from some other offset in this inode or when
++ * detecting if we need to issue a truncate operation when finishing the
++ * processing this inode.
++ */
++ sctx->cur_inode_next_write_offset = key->offset;
++
+ ret = find_extent_clone(sctx, path, key->objectid, key->offset,
+ sctx->cur_inode_size, &found_clone);
+ if (ret != -ENOENT && ret < 0)
+--
+cgit v1.2.1-1-g437b
+
diff --git a/PKGBUILD b/PKGBUILD
index 64e8398..e8ed15a 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -13,7 +13,7 @@
pkgbase=linux-libre
_supver=5
_majver=5
-_minver=0
+_minver=1
_gccpatchver='20191217'
if [ "$_minver" == "0" ]; then
pkgver=${_supver}.${_majver}
@@ -38,6 +38,7 @@ source=(
https://linux-libre.fsfla.org/pub/linux-libre/releases/${_gnumajver}/linux-libre-${_gnumajver}.tar.xz{,.sign}
0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch
0002-iwlwifi-pcie-restore-support-for-Killer-Qu-C0-NICs.patch
+ 0003-btrfs-send-fix-emission-of-invalid-clone-operations-within-the-same.patch
graysky_bdver2-hotfix.patch
kernel_gcc_patch-${_gccpatchver}.tar.gz::https://github.com/graysky2/kernel_gcc_patch/archive/${_gccpatchver}.tar.gz
ath9k-regdom-hack.patch
@@ -54,11 +55,14 @@ b2sums=('a4d4c927af24f61aba451cc21117c5a508ab2037b81ca6add19b4838940f8f321c8bf14
'SKIP'
'ab1fb19c67d4c107f75767581c33d9c1458b4d9fdb88f4adb41d30a36f5a2f95f1c48ef079eb87e1e6e8ce2f98b293195cb2c0f2a8ec975aa817453289158c6e'
'2e822cf7d4ff8b7458e22d3ce110fd8534e17a9aac2feace41c591f70697e1fab7bd9ce307c60a6361fbe525d10dab74c8b76fcb5276cd27f6e945f8fdfcc25c'
+ 'b3f2c12f0d298ffec1a0d8237de80741d935af7b64f967f6ea2473741fbe4616edb7c321dc7a69c57b50d2313330a581b1f3086f64b15a10b2b640e26af659c4'
'1892bd22775eac3bcc4d37f4fd30c95346bf3a0888cbbff57fd614973b525390dff2e315ce35b2e498523cceaab94ff21a80475dee8df3de4dd8fc0fab07d74e'
'd76bd0bf237ea2bb7999fd3715cb664d89148cb0ade8057d57cdb40bc0a7954336e50ee077312e5e192398b0f35f055786deb98af9130d57e60f2ea040fbb66f'
'2e58bb89b247b1678355368956e67c1de51fcde97a227b2162f6771e30f17fa5520faafe7be4b6816a542e7ae10d05f64c6b6354f352c12746d4b8da632936dd'
'fde132f3705d908e6f2147c78a2193289916d72304ca5efa2229d79fc3e57a857314ce94e71425caef2f7f7b6cf87f05ef86335dc8bd4be78e7035afe608005a'
- 'fbfdad1242231dfb81c513dcfd704f384e6d80223ebb0f36dee50dd6b7eb8c4815afe61a9c769296a0afc67f74926a55f07bf2a8e07a51a0fadb117b00df2a78')
+ 'ca3cff10d6d000006562df14bc2cb0742721a3a9f6b8a04cc918ada905823fe623d5e21f95fb44967e018276d18b35816ec7e5588a4a71dbd7b2d688699fa70f'
+ '6cd2f10e0aed1bc94abe3fd4b7646509d442a86e4796608f7b62025273e7443581a0daacae7bd0abf22efa206d1ed4d9028813d525ed02bf50c7254c32cff5aa'
+ 'SKIP')
#export KBUILD_BUILD_HOST=arc4linux
export KBUILD_BUILD_USER=$pkgbase
@@ -78,6 +82,7 @@ prepare() {
echo "Applying hotfixes"
patch -p1 -i ../0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch
patch -p1 -i ../0002-iwlwifi-pcie-restore-support-for-Killer-Qu-C0-NICs.patch
+ patch -p1 -i ../0003-btrfs-send-fix-emission-of-invalid-clone-operations-within-the-same.patch
# graysky gcc hotfixes
diff --git a/config b/config
index 93729a6..098d813 100644
--- a/config
+++ b/config
@@ -8720,7 +8720,7 @@ CONFIG_AMD_IOMMU_V2=y
CONFIG_DMAR_TABLE=y
CONFIG_INTEL_IOMMU=y
CONFIG_INTEL_IOMMU_SVM=y
-# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
+CONFIG_INTEL_IOMMU_DEFAULT_ON=y
CONFIG_INTEL_IOMMU_FLOPPY_WA=y
CONFIG_IRQ_REMAP=y
CONFIG_HYPERV_IOMMU=y