diff options
author | Josef Bacik <jbacik@fusionio.com> | 2013-08-20 15:55:39 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-09-01 08:16:21 -0400 |
commit | 57cfd4627046efc43081d26b5db77dbfb7595caa (patch) | |
tree | a6b3e4b5c665d064ded9e996da5487a7fbaedefc /fs/btrfs/send.c | |
parent | bdab49d760c14dd7d5a8f64dbfedd7a3f1121e9b (diff) |
Btrfs: fix send to deal with sparse files properly
Send was just sending everything it found, even if the extent was a hole. This
is unpleasant for users, so just skip holes when we are sending. This will also
skip sending prealloc extents since the send spec doesn't have a prealloc
command. Eventually we will add a prealloc command and rev the send version so
we can send down the prealloc info. Thanks,
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index db7da682f0d2..cbe92da5f33b 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -3920,7 +3920,8 @@ static int is_extent_unchanged(struct send_ctx *sctx, | |||
3920 | btrfs_item_key_to_cpu(eb, &found_key, slot); | 3920 | btrfs_item_key_to_cpu(eb, &found_key, slot); |
3921 | if (found_key.objectid != key.objectid || | 3921 | if (found_key.objectid != key.objectid || |
3922 | found_key.type != key.type) { | 3922 | found_key.type != key.type) { |
3923 | ret = 0; | 3923 | /* If we're a hole then just pretend nothing changed */ |
3924 | ret = (left_disknr) ? 0 : 1; | ||
3924 | goto out; | 3925 | goto out; |
3925 | } | 3926 | } |
3926 | 3927 | ||
@@ -3946,7 +3947,8 @@ static int is_extent_unchanged(struct send_ctx *sctx, | |||
3946 | * This may only happen on the first iteration. | 3947 | * This may only happen on the first iteration. |
3947 | */ | 3948 | */ |
3948 | if (found_key.offset + right_len <= ekey->offset) { | 3949 | if (found_key.offset + right_len <= ekey->offset) { |
3949 | ret = 0; | 3950 | /* If we're a hole just pretend nothing changed */ |
3951 | ret = (left_disknr) ? 0 : 1; | ||
3950 | goto out; | 3952 | goto out; |
3951 | } | 3953 | } |
3952 | 3954 | ||
@@ -4011,8 +4013,8 @@ static int process_extent(struct send_ctx *sctx, | |||
4011 | struct btrfs_path *path, | 4013 | struct btrfs_path *path, |
4012 | struct btrfs_key *key) | 4014 | struct btrfs_key *key) |
4013 | { | 4015 | { |
4014 | int ret = 0; | ||
4015 | struct clone_root *found_clone = NULL; | 4016 | struct clone_root *found_clone = NULL; |
4017 | int ret = 0; | ||
4016 | 4018 | ||
4017 | if (S_ISLNK(sctx->cur_inode_mode)) | 4019 | if (S_ISLNK(sctx->cur_inode_mode)) |
4018 | return 0; | 4020 | return 0; |
@@ -4025,6 +4027,32 @@ static int process_extent(struct send_ctx *sctx, | |||
4025 | ret = 0; | 4027 | ret = 0; |
4026 | goto out; | 4028 | goto out; |
4027 | } | 4029 | } |
4030 | } else { | ||
4031 | struct btrfs_file_extent_item *ei; | ||
4032 | u8 type; | ||
4033 | |||
4034 | ei = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
4035 | struct btrfs_file_extent_item); | ||
4036 | type = btrfs_file_extent_type(path->nodes[0], ei); | ||
4037 | if (type == BTRFS_FILE_EXTENT_PREALLOC || | ||
4038 | type == BTRFS_FILE_EXTENT_REG) { | ||
4039 | /* | ||
4040 | * The send spec does not have a prealloc command yet, | ||
4041 | * so just leave a hole for prealloc'ed extents until | ||
4042 | * we have enough commands queued up to justify rev'ing | ||
4043 | * the send spec. | ||
4044 | */ | ||
4045 | if (type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
4046 | ret = 0; | ||
4047 | goto out; | ||
4048 | } | ||
4049 | |||
4050 | /* Have a hole, just skip it. */ | ||
4051 | if (btrfs_file_extent_disk_bytenr(path->nodes[0], ei) == 0) { | ||
4052 | ret = 0; | ||
4053 | goto out; | ||
4054 | } | ||
4055 | } | ||
4028 | } | 4056 | } |
4029 | 4057 | ||
4030 | ret = find_extent_clone(sctx, path, key->objectid, key->offset, | 4058 | ret = find_extent_clone(sctx, path, key->objectid, key->offset, |