diff options
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 46 |
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 | } |