Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>

+41 -3
+2 -1
fs/btrfs/ioctl.c
··· 82 82 compat_uptr_t clone_sources; /* in */ 83 83 __u64 parent_root; /* in */ 84 84 __u64 flags; /* in */ 85 - __u64 reserved[4]; /* in */ 85 + __u32 version; /* in */ 86 + __u8 reserved[28]; /* in */ 86 87 } __attribute__ ((__packed__)); 87 88 88 89 #define BTRFS_IOC_SEND_32 _IOW(BTRFS_IOCTL_MAGIC, 38, \
+23
fs/btrfs/send.c
··· 84 84 u64 total_send_size; 85 85 u64 cmd_send_size[BTRFS_SEND_C_MAX + 1]; 86 86 u64 flags; /* 'flags' member of btrfs_ioctl_send_args is u64 */ 87 + /* Protocol version compatibility requested */ 88 + u32 proto; 87 89 88 90 struct btrfs_root *send_root; 89 91 struct btrfs_root *parent_root; ··· 312 310 sctx->send_root->root_key.objectid, 313 311 (sctx->parent_root ? 314 312 sctx->parent_root->root_key.objectid : 0)); 313 + } 314 + 315 + __maybe_unused 316 + static bool proto_cmd_ok(const struct send_ctx *sctx, int cmd) 317 + { 318 + switch (sctx->proto) { 319 + case 1: return cmd < __BTRFS_SEND_C_MAX_V1; 320 + case 2: return cmd < __BTRFS_SEND_C_MAX_V2; 321 + default: return false; 322 + } 315 323 } 316 324 317 325 static int is_waiting_for_move(struct send_ctx *sctx, u64 ino); ··· 7280 7268 INIT_LIST_HEAD(&sctx->name_cache_list); 7281 7269 7282 7270 sctx->flags = arg->flags; 7271 + 7272 + if (arg->flags & BTRFS_SEND_FLAG_VERSION) { 7273 + if (arg->version > BTRFS_SEND_STREAM_VERSION) { 7274 + ret = -EPROTO; 7275 + goto out; 7276 + } 7277 + /* Zero means "use the highest version" */ 7278 + sctx->proto = arg->version ?: BTRFS_SEND_STREAM_VERSION; 7279 + } else { 7280 + sctx->proto = 1; 7281 + } 7283 7282 7284 7283 sctx->send_filp = fget(arg->send_fd); 7285 7284 if (!sctx->send_filp) {
+7
fs/btrfs/send.h
··· 48 48 enum btrfs_send_cmd { 49 49 BTRFS_SEND_C_UNSPEC, 50 50 51 + /* Version 1 */ 51 52 BTRFS_SEND_C_SUBVOL, 52 53 BTRFS_SEND_C_SNAPSHOT, 53 54 ··· 77 76 78 77 BTRFS_SEND_C_END, 79 78 BTRFS_SEND_C_UPDATE_EXTENT, 79 + __BTRFS_SEND_C_MAX_V1, 80 + 81 + /* Version 2 */ 82 + __BTRFS_SEND_C_MAX_V2, 83 + 84 + /* End */ 80 85 __BTRFS_SEND_C_MAX, 81 86 }; 82 87 #define BTRFS_SEND_C_MAX (__BTRFS_SEND_C_MAX - 1)
+9 -2
include/uapi/linux/btrfs.h
··· 771 771 */ 772 772 #define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4 773 773 774 + /* 775 + * Read the protocol version in the structure 776 + */ 777 + #define BTRFS_SEND_FLAG_VERSION 0x8 778 + 774 779 #define BTRFS_SEND_FLAG_MASK \ 775 780 (BTRFS_SEND_FLAG_NO_FILE_DATA | \ 776 781 BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \ 777 - BTRFS_SEND_FLAG_OMIT_END_CMD) 782 + BTRFS_SEND_FLAG_OMIT_END_CMD | \ 783 + BTRFS_SEND_FLAG_VERSION) 778 784 779 785 struct btrfs_ioctl_send_args { 780 786 __s64 send_fd; /* in */ ··· 788 782 __u64 __user *clone_sources; /* in */ 789 783 __u64 parent_root; /* in */ 790 784 __u64 flags; /* in */ 791 - __u64 reserved[4]; /* in */ 785 + __u32 version; /* in */ 786 + __u8 reserved[28]; /* in */ 792 787 }; 793 788 794 789 /*