Commit e77fbf99 authored by David Sterba's avatar David Sterba

btrfs: send: prepare for v2 protocol

This is preparatory work for send protocol update to version 2 and
higher.

We have many pending protocol update requests but still don't have the
basic protocol rev in place, the first thing that must happen is to do
the actual versioning support.

The protocol version is u32 and is a new member in the send ioctl
struct. Validity of the version field is backed by a new flag bit. Old
kernels would fail when a higher version is requested. Version protocol
0 will pick the highest supported version, BTRFS_SEND_STREAM_VERSION,
  that's also exported in sysfs.

The version is still unchanged and will be increased once we have new
incompatible commands or stream updates.
Reviewed-by: default avatarNikolay Borisov <nborisov@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 50780d9b
...@@ -82,7 +82,8 @@ struct btrfs_ioctl_send_args_32 { ...@@ -82,7 +82,8 @@ struct btrfs_ioctl_send_args_32 {
compat_uptr_t clone_sources; /* in */ compat_uptr_t clone_sources; /* in */
__u64 parent_root; /* in */ __u64 parent_root; /* in */
__u64 flags; /* in */ __u64 flags; /* in */
__u64 reserved[4]; /* in */ __u32 version; /* in */
__u8 reserved[28]; /* in */
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
#define BTRFS_IOC_SEND_32 _IOW(BTRFS_IOCTL_MAGIC, 38, \ #define BTRFS_IOC_SEND_32 _IOW(BTRFS_IOCTL_MAGIC, 38, \
......
...@@ -84,6 +84,8 @@ struct send_ctx { ...@@ -84,6 +84,8 @@ struct send_ctx {
u64 total_send_size; u64 total_send_size;
u64 cmd_send_size[BTRFS_SEND_C_MAX + 1]; u64 cmd_send_size[BTRFS_SEND_C_MAX + 1];
u64 flags; /* 'flags' member of btrfs_ioctl_send_args is u64 */ u64 flags; /* 'flags' member of btrfs_ioctl_send_args is u64 */
/* Protocol version compatibility requested */
u32 proto;
struct btrfs_root *send_root; struct btrfs_root *send_root;
struct btrfs_root *parent_root; struct btrfs_root *parent_root;
...@@ -312,6 +314,16 @@ static void inconsistent_snapshot_error(struct send_ctx *sctx, ...@@ -312,6 +314,16 @@ static void inconsistent_snapshot_error(struct send_ctx *sctx,
sctx->parent_root->root_key.objectid : 0)); sctx->parent_root->root_key.objectid : 0));
} }
__maybe_unused
static bool proto_cmd_ok(const struct send_ctx *sctx, int cmd)
{
switch (sctx->proto) {
case 1: return cmd < __BTRFS_SEND_C_MAX_V1;
case 2: return cmd < __BTRFS_SEND_C_MAX_V2;
default: return false;
}
}
static int is_waiting_for_move(struct send_ctx *sctx, u64 ino); static int is_waiting_for_move(struct send_ctx *sctx, u64 ino);
static struct waiting_dir_move * static struct waiting_dir_move *
...@@ -7269,6 +7281,17 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7269,6 +7281,17 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
sctx->flags = arg->flags; sctx->flags = arg->flags;
if (arg->flags & BTRFS_SEND_FLAG_VERSION) {
if (arg->version > BTRFS_SEND_STREAM_VERSION) {
ret = -EPROTO;
goto out;
}
/* Zero means "use the highest version" */
sctx->proto = arg->version ?: BTRFS_SEND_STREAM_VERSION;
} else {
sctx->proto = 1;
}
sctx->send_filp = fget(arg->send_fd); sctx->send_filp = fget(arg->send_fd);
if (!sctx->send_filp) { if (!sctx->send_filp) {
ret = -EBADF; ret = -EBADF;
......
...@@ -48,6 +48,7 @@ struct btrfs_tlv_header { ...@@ -48,6 +48,7 @@ struct btrfs_tlv_header {
enum btrfs_send_cmd { enum btrfs_send_cmd {
BTRFS_SEND_C_UNSPEC, BTRFS_SEND_C_UNSPEC,
/* Version 1 */
BTRFS_SEND_C_SUBVOL, BTRFS_SEND_C_SUBVOL,
BTRFS_SEND_C_SNAPSHOT, BTRFS_SEND_C_SNAPSHOT,
...@@ -76,6 +77,12 @@ enum btrfs_send_cmd { ...@@ -76,6 +77,12 @@ enum btrfs_send_cmd {
BTRFS_SEND_C_END, BTRFS_SEND_C_END,
BTRFS_SEND_C_UPDATE_EXTENT, BTRFS_SEND_C_UPDATE_EXTENT,
__BTRFS_SEND_C_MAX_V1,
/* Version 2 */
__BTRFS_SEND_C_MAX_V2,
/* End */
__BTRFS_SEND_C_MAX, __BTRFS_SEND_C_MAX,
}; };
#define BTRFS_SEND_C_MAX (__BTRFS_SEND_C_MAX - 1) #define BTRFS_SEND_C_MAX (__BTRFS_SEND_C_MAX - 1)
......
...@@ -771,10 +771,16 @@ struct btrfs_ioctl_received_subvol_args { ...@@ -771,10 +771,16 @@ struct btrfs_ioctl_received_subvol_args {
*/ */
#define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4 #define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4
/*
* Read the protocol version in the structure
*/
#define BTRFS_SEND_FLAG_VERSION 0x8
#define BTRFS_SEND_FLAG_MASK \ #define BTRFS_SEND_FLAG_MASK \
(BTRFS_SEND_FLAG_NO_FILE_DATA | \ (BTRFS_SEND_FLAG_NO_FILE_DATA | \
BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \ BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \
BTRFS_SEND_FLAG_OMIT_END_CMD) BTRFS_SEND_FLAG_OMIT_END_CMD | \
BTRFS_SEND_FLAG_VERSION)
struct btrfs_ioctl_send_args { struct btrfs_ioctl_send_args {
__s64 send_fd; /* in */ __s64 send_fd; /* in */
...@@ -782,7 +788,8 @@ struct btrfs_ioctl_send_args { ...@@ -782,7 +788,8 @@ struct btrfs_ioctl_send_args {
__u64 __user *clone_sources; /* in */ __u64 __user *clone_sources; /* in */
__u64 parent_root; /* in */ __u64 parent_root; /* in */
__u64 flags; /* in */ __u64 flags; /* in */
__u64 reserved[4]; /* in */ __u32 version; /* in */
__u8 reserved[28]; /* in */
}; };
/* /*
......
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