Commit 57cfd462 authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

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: default avatarJosef Bacik <jbacik@fusionio.com>
Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
parent bdab49d7
...@@ -3920,7 +3920,8 @@ static int is_extent_unchanged(struct send_ctx *sctx, ...@@ -3920,7 +3920,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
btrfs_item_key_to_cpu(eb, &found_key, slot); btrfs_item_key_to_cpu(eb, &found_key, slot);
if (found_key.objectid != key.objectid || if (found_key.objectid != key.objectid ||
found_key.type != key.type) { found_key.type != key.type) {
ret = 0; /* If we're a hole then just pretend nothing changed */
ret = (left_disknr) ? 0 : 1;
goto out; goto out;
} }
...@@ -3946,7 +3947,8 @@ static int is_extent_unchanged(struct send_ctx *sctx, ...@@ -3946,7 +3947,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
* This may only happen on the first iteration. * This may only happen on the first iteration.
*/ */
if (found_key.offset + right_len <= ekey->offset) { if (found_key.offset + right_len <= ekey->offset) {
ret = 0; /* If we're a hole just pretend nothing changed */
ret = (left_disknr) ? 0 : 1;
goto out; goto out;
} }
...@@ -4011,8 +4013,8 @@ static int process_extent(struct send_ctx *sctx, ...@@ -4011,8 +4013,8 @@ static int process_extent(struct send_ctx *sctx,
struct btrfs_path *path, struct btrfs_path *path,
struct btrfs_key *key) struct btrfs_key *key)
{ {
int ret = 0;
struct clone_root *found_clone = NULL; struct clone_root *found_clone = NULL;
int ret = 0;
if (S_ISLNK(sctx->cur_inode_mode)) if (S_ISLNK(sctx->cur_inode_mode))
return 0; return 0;
...@@ -4025,6 +4027,32 @@ static int process_extent(struct send_ctx *sctx, ...@@ -4025,6 +4027,32 @@ static int process_extent(struct send_ctx *sctx,
ret = 0; ret = 0;
goto out; goto out;
} }
} else {
struct btrfs_file_extent_item *ei;
u8 type;
ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_file_extent_item);
type = btrfs_file_extent_type(path->nodes[0], ei);
if (type == BTRFS_FILE_EXTENT_PREALLOC ||
type == BTRFS_FILE_EXTENT_REG) {
/*
* The send spec does not have a prealloc command yet,
* so just leave a hole for prealloc'ed extents until
* we have enough commands queued up to justify rev'ing
* the send spec.
*/
if (type == BTRFS_FILE_EXTENT_PREALLOC) {
ret = 0;
goto out;
}
/* Have a hole, just skip it. */
if (btrfs_file_extent_disk_bytenr(path->nodes[0], ei) == 0) {
ret = 0;
goto out;
}
}
} }
ret = find_extent_clone(sctx, path, key->objectid, key->offset, ret = find_extent_clone(sctx, path, key->objectid, key->offset,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment