Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 360440
b: refs/heads/master
c: cb95e7b
h: refs/heads/master
v: v3
  • Loading branch information
Mark Fasheh authored and Josef Bacik committed Feb 20, 2013
1 parent c8c423e commit 7fda23e
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2f697dc6a648d3a16f512fe7a53281d55cce1570
refs/heads/master: cb95e7bf7ba481c3d35b238b1cd671b63f54238a
50 changes: 46 additions & 4 deletions trunk/fs/btrfs/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ struct send_ctx {
u32 send_max_size;
u64 total_send_size;
u64 cmd_send_size[BTRFS_SEND_C_MAX + 1];
u64 flags; /* 'flags' member of btrfs_ioctl_send_args is u64 */

struct vfsmount *mnt;

Expand Down Expand Up @@ -3709,6 +3710,39 @@ verbose_printk("btrfs: send_clone offset=%llu, len=%d, clone_root=%llu, "
return ret;
}

/*
* Send an update extent command to user space.
*/
static int send_update_extent(struct send_ctx *sctx,
u64 offset, u32 len)
{
int ret = 0;
struct fs_path *p;

p = fs_path_alloc(sctx);
if (!p)
return -ENOMEM;

ret = begin_cmd(sctx, BTRFS_SEND_C_UPDATE_EXTENT);
if (ret < 0)
goto out;

ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p);
if (ret < 0)
goto out;

TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p);
TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset);
TLV_PUT_U64(sctx, BTRFS_SEND_A_SIZE, len);

ret = send_cmd(sctx);

tlv_put_failure:
out:
fs_path_free(sctx, p);
return ret;
}

static int send_write_or_clone(struct send_ctx *sctx,
struct btrfs_path *path,
struct btrfs_key *key,
Expand Down Expand Up @@ -3744,7 +3778,11 @@ static int send_write_or_clone(struct send_ctx *sctx,
goto out;
}

if (!clone_root) {
if (clone_root) {
ret = send_clone(sctx, offset, len, clone_root);
} else if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA) {
ret = send_update_extent(sctx, offset, len);
} else {
while (pos < len) {
l = len - pos;
if (l > BTRFS_SEND_READ_SIZE)
Expand All @@ -3757,10 +3795,7 @@ static int send_write_or_clone(struct send_ctx *sctx,
pos += ret;
}
ret = 0;
} else {
ret = send_clone(sctx, offset, len, clone_root);
}

out:
return ret;
}
Expand Down Expand Up @@ -4560,6 +4595,11 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
goto out;
}

if (arg->flags & ~BTRFS_SEND_FLAG_NO_FILE_DATA) {
ret = -EINVAL;
goto out;
}

sctx = kzalloc(sizeof(struct send_ctx), GFP_NOFS);
if (!sctx) {
ret = -ENOMEM;
Expand All @@ -4571,6 +4611,8 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
INIT_RADIX_TREE(&sctx->name_cache, GFP_NOFS);
INIT_LIST_HEAD(&sctx->name_cache_list);

sctx->flags = arg->flags;

sctx->send_filp = fget(arg->send_fd);
if (IS_ERR(sctx->send_filp)) {
ret = PTR_ERR(sctx->send_filp);
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/btrfs/send.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ enum btrfs_send_cmd {
BTRFS_SEND_C_UTIMES,

BTRFS_SEND_C_END,
BTRFS_SEND_C_UPDATE_EXTENT,
__BTRFS_SEND_C_MAX,
};
#define BTRFS_SEND_C_MAX (__BTRFS_SEND_C_MAX - 1)
Expand Down
7 changes: 7 additions & 0 deletions trunk/include/uapi/linux/btrfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,13 @@ struct btrfs_ioctl_received_subvol_args {
__u64 reserved[16]; /* in */
};

/*
* Caller doesn't want file data in the send stream, even if the
* search of clone sources doesn't find an extent. UPDATE_EXTENT
* commands will be sent instead of WRITE commands.
*/
#define BTRFS_SEND_FLAG_NO_FILE_DATA 0x1

struct btrfs_ioctl_send_args {
__s64 send_fd; /* in */
__u64 clone_sources_count; /* in */
Expand Down

0 comments on commit 7fda23e

Please sign in to comment.