diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c index 4a5f2c35c034..a4a00db9d547 100644 --- a/fs/btrfs/reflink.c +++ b/fs/btrfs/reflink.c @@ -780,6 +780,13 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in, /* Don't make the dst file partly checksummed */ if ((BTRFS_I(inode_in)->flags & BTRFS_INODE_NODATASUM) != (BTRFS_I(inode_out)->flags & BTRFS_INODE_NODATASUM)) { + if (!(remap_flags & REMAP_FILE_DEDUP)) { + struct btrfs_fs_info *fs_info = BTRFS_I(inode_in)->root->fs_info; + + btrfs_info(fs_info, "clone: nodatasum mismatch, src %llu (root %llu) dst %llu (root %llu)", + btrfs_ino(BTRFS_I(inode_in)), BTRFS_I(inode_in)->root->root_key.objectid, + btrfs_ino(BTRFS_I(inode_out)), BTRFS_I(inode_out)->root->root_key.objectid); + } return -EINVAL; } @@ -863,9 +870,16 @@ loff_t btrfs_remap_file_range(struct file *src_file, loff_t off, struct inode *dst_inode = file_inode(dst_file); bool same_inode = dst_inode == src_inode; int ret; - - if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) + struct btrfs_fs_info *fs_info = BTRFS_I(src_inode)->root->fs_info; + const loff_t olen = len; + + if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) { + btrfs_info(fs_info, "clone: -EINVAL flags, src %llu (root %llu) dst %llu (root %llu), off %lld destoff %lld len %lld olen %lld, src i_size %lld dst i_size %lld bs %lu remap_flags %u", + btrfs_ino(BTRFS_I(src_inode)), BTRFS_I(src_inode)->root->root_key.objectid, + btrfs_ino(BTRFS_I(dst_inode)), BTRFS_I(dst_inode)->root->root_key.objectid, + off, destoff, len, olen, i_size_read(src_inode), i_size_read(dst_inode), dst_inode->i_sb->s_blocksize, remap_flags); return -EINVAL; + } if (same_inode) { btrfs_inode_lock(src_inode, BTRFS_ILOCK_MMAP); @@ -876,6 +890,11 @@ loff_t btrfs_remap_file_range(struct file *src_file, loff_t off, ret = btrfs_remap_file_range_prep(src_file, off, dst_file, destoff, &len, remap_flags); + if (ret == -EINVAL && !(remap_flags & REMAP_FILE_DEDUP)) + btrfs_info(fs_info, "clone: -EINVAL other, src %llu (root %llu) dst %llu (root %llu), off %lld destoff %lld len %lld olen %lld, src i_size %lld dst i_size %lld bs %lu remap_flags %u", + btrfs_ino(BTRFS_I(src_inode)), BTRFS_I(src_inode)->root->root_key.objectid, + btrfs_ino(BTRFS_I(dst_inode)), BTRFS_I(dst_inode)->root->root_key.objectid, + off, destoff, len, olen, i_size_read(src_inode), i_size_read(dst_inode), dst_inode->i_sb->s_blocksize, remap_flags); if (ret < 0 || len == 0) goto out_unlock; diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index afdcbe7844e0..f0b0b785a3e2 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -5044,6 +5044,10 @@ static int send_clone(struct send_ctx *sctx, offset, len, clone_root->root->root_key.objectid, clone_root->ino, clone_root->offset); + WARN_ON(clone_root->root == sctx->send_root && + clone_root->ino == sctx->cur_ino && + clone_root->offset == offset); + p = fs_path_alloc(); if (!p) return -ENOMEM; @@ -5280,6 +5284,7 @@ static int clone_range(struct send_ctx *sctx, struct btrfs_key key; int ret; u64 clone_src_i_size = 0; + struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; /* * Prevent cloning from a zero offset with a length matching the sector @@ -5349,6 +5354,10 @@ static int clone_range(struct send_ctx *sctx, path->slots[0]--; } + btrfs_info(fs_info, "send: clone_range() start ino %llu offset %llu send root %llu, clone root %llu ino %llu offset %llu data_offset %llu len %llu disk_byte %llu clone_src_i_size %llu next_write_offset %llu", + sctx->cur_ino, offset, sctx->send_root->root_key.objectid, clone_root->root->root_key.objectid, clone_root->ino, clone_root->offset, data_offset, len, + disk_byte, clone_src_i_size, sctx->cur_inode_next_write_offset); + while (true) { struct extent_buffer *leaf = path->nodes[0]; int slot = path->slots[0]; @@ -5417,6 +5426,11 @@ static int clone_range(struct send_ctx *sctx, ext_len = clone_src_i_size - key.offset; clone_data_offset = btrfs_file_extent_offset(leaf, ei); + + btrfs_info(fs_info, "send: clone_range() step 1 ino %llu offset %llu, root offset %llu ino %llu data_offset %llu len %llu, key.offset %llu ext_len %llu clone_data_offset %llu found disk_byte %llu next_write_offset %llu", + sctx->cur_ino, offset, clone_root->offset, clone_root->ino, data_offset, len, key.offset, ext_len, clone_data_offset, btrfs_file_extent_disk_bytenr(leaf, ei), + sctx->cur_inode_next_write_offset); + if (btrfs_file_extent_disk_bytenr(leaf, ei) == disk_byte) { clone_root->offset = key.offset; if (clone_data_offset < data_offset && @@ -5462,6 +5476,9 @@ static int clone_range(struct send_ctx *sctx, slen = ALIGN_DOWN(src_end - clone_root->offset, sectorsize); + btrfs_info(fs_info, "send: clone_range() step 2-1-1 ino %llu offset %llu, root offset %llu ino %llu data_offset %llu len %llu, clone_len %llu src_end %llu slen %llu", + sctx->cur_ino, offset, clone_root->offset, clone_root->ino, data_offset, len, clone_len, src_end, slen); + if (slen > 0) { ret = send_clone(sctx, offset, slen, clone_root); @@ -5471,10 +5488,15 @@ static int clone_range(struct send_ctx *sctx, ret = send_extent_data(sctx, offset + slen, clone_len - slen); } else { + btrfs_info(fs_info, "send: clone_range() step 2-1-2 ino %llu offset %llu, root offset %llu ino %llu data_offset %llu len %llu, clone_len %llu", + sctx->cur_ino, offset, clone_root->offset, clone_root->ino, data_offset, len, clone_len); + ret = send_clone(sctx, offset, clone_len, clone_root); } } else { + btrfs_info(fs_info, "send: clone_range() step 2-2 ino %llu offset %llu, root offset %llu ino %llu data_offset %llu len %llu clone_len %llu", + sctx->cur_ino, offset, clone_root->offset, clone_root->ino, data_offset, len, clone_len); ret = send_extent_data(sctx, offset, clone_len); } @@ -5511,6 +5533,10 @@ static int clone_range(struct send_ctx *sctx, else ret = 0; out: + btrfs_info(fs_info, "send: clone_range() end ino %llu offset %llu send root %llu, clone root %llu ino %llu offset %llu data_offset %llu len %llu disk_byte %llu clone_src_i_size %llu next_write_offset %llu ret %d", + sctx->cur_ino, offset, sctx->send_root->root_key.objectid, clone_root->root->root_key.objectid, clone_root->ino, clone_root->offset, data_offset, len, + disk_byte, clone_src_i_size, sctx->cur_inode_next_write_offset, ret); + btrfs_free_path(path); return ret; }