|
@@ -4992,6 +4992,25 @@ static int clone_range(struct send_ctx *sctx,
|
|
|
struct btrfs_key key;
|
|
|
int ret;
|
|
|
|
|
|
+ /*
|
|
|
+ * Prevent cloning from a zero offset with a length matching the sector
|
|
|
+ * size because in some scenarios this will make the receiver fail.
|
|
|
+ *
|
|
|
+ * For example, if in the source filesystem the extent at offset 0
|
|
|
+ * has a length of sectorsize and it was written using direct IO, then
|
|
|
+ * it can never be an inline extent (even if compression is enabled).
|
|
|
+ * Then this extent can be cloned in the original filesystem to a non
|
|
|
+ * zero file offset, but it may not be possible to clone in the
|
|
|
+ * destination filesystem because it can be inlined due to compression
|
|
|
+ * on the destination filesystem (as the receiver's write operations are
|
|
|
+ * always done using buffered IO). The same happens when the original
|
|
|
+ * filesystem does not have compression enabled but the destination
|
|
|
+ * filesystem has.
|
|
|
+ */
|
|
|
+ if (clone_root->offset == 0 &&
|
|
|
+ len == sctx->send_root->fs_info->sectorsize)
|
|
|
+ return send_extent_data(sctx, offset, len);
|
|
|
+
|
|
|
path = alloc_path_for_send();
|
|
|
if (!path)
|
|
|
return -ENOMEM;
|