compat_uptr_t clone_sources;    /* in */
        __u64 parent_root;              /* in */
        __u64 flags;                    /* in */
-       __u64 reserved[4];              /* in */
+       __u32 version;                  /* in */
+       __u8  reserved[28];             /* in */
 } __attribute__ ((__packed__));
 
 #define BTRFS_IOC_SEND_32 _IOW(BTRFS_IOCTL_MAGIC, 38, \
 
        u64 total_send_size;
        u64 cmd_send_size[BTRFS_SEND_C_MAX + 1];
        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 *parent_root;
                   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 struct waiting_dir_move *
 
        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);
        if (!sctx->send_filp) {
                ret = -EBADF;
 
 enum btrfs_send_cmd {
        BTRFS_SEND_C_UNSPEC,
 
+       /* Version 1 */
        BTRFS_SEND_C_SUBVOL,
        BTRFS_SEND_C_SNAPSHOT,
 
 
        BTRFS_SEND_C_END,
        BTRFS_SEND_C_UPDATE_EXTENT,
+       __BTRFS_SEND_C_MAX_V1,
+
+       /* Version 2 */
+       __BTRFS_SEND_C_MAX_V2,
+
+       /* End */
        __BTRFS_SEND_C_MAX,
 };
 #define BTRFS_SEND_C_MAX (__BTRFS_SEND_C_MAX - 1)
 
  */
 #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 \
        (BTRFS_SEND_FLAG_NO_FILE_DATA | \
         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 {
        __s64 send_fd;                  /* in */
        __u64 __user *clone_sources;    /* in */
        __u64 parent_root;              /* in */
        __u64 flags;                    /* in */
-       __u64 reserved[4];              /* in */
+       __u32 version;                  /* in */
+       __u8  reserved[28];             /* in */
 };
 
 /*