aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/send.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r--fs/btrfs/send.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index d17d75ebc482..f22fdd41ff49 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -1149,6 +1149,7 @@ static int find_extent_clone(struct send_ctx *sctx,
1149 int ret; 1149 int ret;
1150 int extent_type; 1150 int extent_type;
1151 u64 logical; 1151 u64 logical;
1152 u64 disk_byte;
1152 u64 num_bytes; 1153 u64 num_bytes;
1153 u64 extent_item_pos; 1154 u64 extent_item_pos;
1154 struct btrfs_file_extent_item *fi; 1155 struct btrfs_file_extent_item *fi;
@@ -1157,6 +1158,7 @@ static int find_extent_clone(struct send_ctx *sctx,
1157 struct clone_root *cur_clone_root; 1158 struct clone_root *cur_clone_root;
1158 struct btrfs_key found_key; 1159 struct btrfs_key found_key;
1159 struct btrfs_path *tmp_path; 1160 struct btrfs_path *tmp_path;
1161 int compressed;
1160 u32 i; 1162 u32 i;
1161 1163
1162 tmp_path = alloc_path_for_send(); 1164 tmp_path = alloc_path_for_send();
@@ -1186,17 +1188,18 @@ static int find_extent_clone(struct send_ctx *sctx,
1186 ret = -ENOENT; 1188 ret = -ENOENT;
1187 goto out; 1189 goto out;
1188 } 1190 }
1191 compressed = btrfs_file_extent_compression(eb, fi);
1189 1192
1190 num_bytes = btrfs_file_extent_num_bytes(eb, fi); 1193 num_bytes = btrfs_file_extent_num_bytes(eb, fi);
1191 logical = btrfs_file_extent_disk_bytenr(eb, fi); 1194 disk_byte = btrfs_file_extent_disk_bytenr(eb, fi);
1192 if (logical == 0) { 1195 if (disk_byte == 0) {
1193 ret = -ENOENT; 1196 ret = -ENOENT;
1194 goto out; 1197 goto out;
1195 } 1198 }
1196 logical += btrfs_file_extent_offset(eb, fi); 1199 logical = disk_byte + btrfs_file_extent_offset(eb, fi);
1197 1200
1198 ret = extent_from_logical(sctx->send_root->fs_info, 1201 ret = extent_from_logical(sctx->send_root->fs_info,
1199 logical, tmp_path, &found_key); 1202 disk_byte, tmp_path, &found_key);
1200 btrfs_release_path(tmp_path); 1203 btrfs_release_path(tmp_path);
1201 1204
1202 if (ret < 0) 1205 if (ret < 0)
@@ -1234,10 +1237,16 @@ static int find_extent_clone(struct send_ctx *sctx,
1234 /* 1237 /*
1235 * Now collect all backrefs. 1238 * Now collect all backrefs.
1236 */ 1239 */
1240 if (compressed == BTRFS_COMPRESS_NONE)
1241 extent_item_pos = logical - found_key.objectid;
1242 else
1243 extent_item_pos = 0;
1244
1237 extent_item_pos = logical - found_key.objectid; 1245 extent_item_pos = logical - found_key.objectid;
1238 ret = iterate_extent_inodes(sctx->send_root->fs_info, 1246 ret = iterate_extent_inodes(sctx->send_root->fs_info,
1239 found_key.objectid, extent_item_pos, 1, 1247 found_key.objectid, extent_item_pos, 1,
1240 __iterate_backrefs, backref_ctx); 1248 __iterate_backrefs, backref_ctx);
1249
1241 if (ret < 0) 1250 if (ret < 0)
1242 goto out; 1251 goto out;
1243 1252
@@ -1246,8 +1255,8 @@ static int find_extent_clone(struct send_ctx *sctx,
1246 ret = -EIO; 1255 ret = -EIO;
1247 printk(KERN_ERR "btrfs: ERROR did not find backref in " 1256 printk(KERN_ERR "btrfs: ERROR did not find backref in "
1248 "send_root. inode=%llu, offset=%llu, " 1257 "send_root. inode=%llu, offset=%llu, "
1249 "logical=%llu\n", 1258 "disk_byte=%llu found extent=%llu\n",
1250 ino, data_offset, logical); 1259 ino, data_offset, disk_byte, found_key.objectid);
1251 goto out; 1260 goto out;
1252 } 1261 }
1253 1262
@@ -3678,10 +3687,17 @@ static int send_write_or_clone(struct send_ctx *sctx,
3678 ei = btrfs_item_ptr(path->nodes[0], path->slots[0], 3687 ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
3679 struct btrfs_file_extent_item); 3688 struct btrfs_file_extent_item);
3680 type = btrfs_file_extent_type(path->nodes[0], ei); 3689 type = btrfs_file_extent_type(path->nodes[0], ei);
3681 if (type == BTRFS_FILE_EXTENT_INLINE) 3690 if (type == BTRFS_FILE_EXTENT_INLINE) {
3682 len = btrfs_file_extent_inline_len(path->nodes[0], ei); 3691 len = btrfs_file_extent_inline_len(path->nodes[0], ei);
3683 else 3692 /*
3693 * it is possible the inline item won't cover the whole page,
3694 * but there may be items after this page. Make
3695 * sure to send the whole thing
3696 */
3697 len = PAGE_CACHE_ALIGN(len);
3698 } else {
3684 len = btrfs_file_extent_num_bytes(path->nodes[0], ei); 3699 len = btrfs_file_extent_num_bytes(path->nodes[0], ei);
3700 }
3685 3701
3686 if (offset + len > sctx->cur_inode_size) 3702 if (offset + len > sctx->cur_inode_size)
3687 len = sctx->cur_inode_size - offset; 3703 len = sctx->cur_inode_size - offset;
@@ -3729,6 +3745,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
3729 u64 left_offset_fixed; 3745 u64 left_offset_fixed;
3730 u64 left_len; 3746 u64 left_len;
3731 u64 right_len; 3747 u64 right_len;
3748 u64 left_gen;
3749 u64 right_gen;
3732 u8 left_type; 3750 u8 left_type;
3733 u8 right_type; 3751 u8 right_type;
3734 3752
@@ -3738,17 +3756,17 @@ static int is_extent_unchanged(struct send_ctx *sctx,
3738 3756
3739 eb = left_path->nodes[0]; 3757 eb = left_path->nodes[0];
3740 slot = left_path->slots[0]; 3758 slot = left_path->slots[0];
3741
3742 ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); 3759 ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
3743 left_type = btrfs_file_extent_type(eb, ei); 3760 left_type = btrfs_file_extent_type(eb, ei);
3744 left_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
3745 left_len = btrfs_file_extent_num_bytes(eb, ei);
3746 left_offset = btrfs_file_extent_offset(eb, ei);
3747 3761
3748 if (left_type != BTRFS_FILE_EXTENT_REG) { 3762 if (left_type != BTRFS_FILE_EXTENT_REG) {
3749 ret = 0; 3763 ret = 0;
3750 goto out; 3764 goto out;
3751 } 3765 }
3766 left_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
3767 left_len = btrfs_file_extent_num_bytes(eb, ei);
3768 left_offset = btrfs_file_extent_offset(eb, ei);
3769 left_gen = btrfs_file_extent_generation(eb, ei);
3752 3770
3753 /* 3771 /*
3754 * Following comments will refer to these graphics. L is the left 3772 * Following comments will refer to these graphics. L is the left
@@ -3804,6 +3822,7 @@ static int is_extent_unchanged(struct send_ctx *sctx,
3804 right_disknr = btrfs_file_extent_disk_bytenr(eb, ei); 3822 right_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
3805 right_len = btrfs_file_extent_num_bytes(eb, ei); 3823 right_len = btrfs_file_extent_num_bytes(eb, ei);
3806 right_offset = btrfs_file_extent_offset(eb, ei); 3824 right_offset = btrfs_file_extent_offset(eb, ei);
3825 right_gen = btrfs_file_extent_generation(eb, ei);
3807 3826
3808 if (right_type != BTRFS_FILE_EXTENT_REG) { 3827 if (right_type != BTRFS_FILE_EXTENT_REG) {
3809 ret = 0; 3828 ret = 0;
@@ -3832,7 +3851,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
3832 * Check if we have the same extent. 3851 * Check if we have the same extent.
3833 */ 3852 */
3834 if (left_disknr != right_disknr || 3853 if (left_disknr != right_disknr ||
3835 left_offset_fixed != right_offset) { 3854 left_offset_fixed != right_offset ||
3855 left_gen != right_gen) {
3836 ret = 0; 3856 ret = 0;
3837 goto out; 3857 goto out;
3838 } 3858 }