diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index e3bfe78774..a29ce6b69d 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -209,6 +209,14 @@
 #ifdef BTRFS_IOC_DEFAULT_SUBVOL
      IOCTL(BTRFS_IOC_DEFAULT_SUBVOL, IOC_W, MK_PTR(TYPE_ULONGLONG))
 #endif
+#ifdef BTRFS_IOC_SNAP_CREATE_V2
+     IOCTL(BTRFS_IOC_SNAP_CREATE_V2, IOC_W,
+           MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args_v2)))
+#endif
+#ifdef BTRFS_IOC_SUBVOL_CREATE_V2
+     IOCTL(BTRFS_IOC_SUBVOL_CREATE_V2, IOC_W,
+           MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args_v2)))
+#endif
 #ifdef BTRFS_IOC_SUBVOL_GETFLAGS
      IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG))
 #endif
@@ -281,6 +289,10 @@
      IOCTL(BTRFS_IOC_GET_SUPPORTED_FEATURES, IOC_R,
            MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags), 3)))
 #endif
+#ifdef BTRFS_IOC_RM_DEV_V2
+     IOCTL(BTRFS_IOC_RM_DEV_V2, IOC_W,
+           MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args_v2)))
+#endif
 #ifdef BTRFS_IOC_LOGICAL_INO_V2
      IOCTL(BTRFS_IOC_LOGICAL_INO_V2, IOC_RW,
            MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_logical_ino_args)))
@@ -297,6 +309,10 @@
      IOCTL(BTRFS_IOC_INO_LOOKUP_USER, IOC_RW,
            MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_user_args)))
 #endif
+#ifdef BTRFS_IOC_SNAP_DESTROY_V2
+     IOCTL(BTRFS_IOC_SNAP_DESTROY_V2, IOC_W,
+           MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args_v2)))
+#endif
 
 #ifdef CONFIG_USBFS
   /* USB ioctls */
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index a69a0bd347..4add164673 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -708,6 +708,11 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
 
 void print_termios(void *arg);
 
+#if defined(BTRFS_IOC_SUBVOL_CREATE_V2) || defined(BTRFS_IOC_SNAP_CREATE_V2) \
+ || defined(BTRFS_IOC_SNAP_DESTROY_V2)  || defined(BTRFS_IOC_RM_DEV_V2)
+void print_btrfs_ioctl_vol_args_v2(void *arg);
+#endif
+
 /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
 #ifdef TARGET_ARM
 static inline int regpairs_aligned(void *cpu_env, int num)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index b9ba39ce6e..04fe38a846 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -9,6 +9,9 @@
 #include <netinet/tcp.h>
 #include <linux/if_packet.h>
 #include <linux/netlink.h>
+#ifdef CONFIG_BTRFS
+#include <linux/btrfs.h>
+#endif
 #include <sched.h>
 #include "qemu.h"
 
@@ -1434,6 +1437,22 @@ UNUSED static struct enums itimer_types[] = {
     ENUM_END,
 };
 
+UNUSED static struct flags btrfs_args_vol_v2_flags[] = {
+#ifdef BTRFS_SUBVOL_RDONLY
+    FLAG_GENERIC(BTRFS_SUBVOL_RDONLY),
+#endif
+#ifdef BTRFS_SUBVOL_QGROUP_INHERIT
+    FLAG_GENERIC(BTRFS_SUBVOL_QGROUP_INHERIT),
+#endif
+#ifdef BTRFS_DEVICE_SPEC_BY_ID
+    FLAG_GENERIC(BTRFS_DEVICE_SPEC_BY_ID),
+#endif
+#ifdef BTRFS_SUBVOL_SPEC_BY_ID
+    FLAG_GENERIC(BTRFS_SUBVOL_SPEC_BY_ID),
+#endif
+    FLAG_END,
+};
+
 /*
  * print_xxx utility functions.  These are used to print syscall
  * parameters in certain format.  All of these have parameter
@@ -1774,6 +1793,82 @@ print_termios(void *arg)
     qemu_log("}");
 }
 
+#if defined(BTRFS_IOC_SUBVOL_CREATE_V2) || defined(BTRFS_IOC_SNAP_CREATE_V2) \
+ || defined(BTRFS_IOC_SNAP_DESTROY_V2)  || defined(BTRFS_IOC_RM_DEV_V2)
+void
+print_btrfs_ioctl_vol_args_v2(void *arg)
+{
+    struct target_btrfs_ioctl_vol_args_v2 *target_args_v2 = arg;
+    uint64_t flags = tswap64(target_args_v2->flags);
+    int device_spec_by_id = 0;
+    int subvol_spec_by_id = 0;
+
+    qemu_log("{fd = %" PRId64 ", flags = ", tswap64(target_args_v2->fd));
+    print_flags(btrfs_args_vol_v2_flags, flags, 0);
+    qemu_log(" transid = %" PRIu64 ",", tswap64(target_args_v2->transid));
+
+#ifdef BTRFS_SUBVOL_QGROUP_INHERIT
+    if (flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
+
+        struct btrfs_qgroup_inherit *target_inherit;
+        abi_long inherit_addr = tswapal(target_args_v2->qgroup_inherit);
+
+        target_inherit = lock_user(VERIFY_READ, inherit_addr,
+                                   sizeof(*target_inherit), 1);
+
+        if (target_inherit) {
+            qemu_log(" size = %" PRIu64,
+                     tswap64(target_args_v2->size));
+            qemu_log(", qgroup_inherit = {");
+
+            qemu_log("flags = %" PRIu64,
+                     tswap64(target_inherit->flags));
+            qemu_log(", num_qgroups = %" PRIu64,
+                     tswap64(target_inherit->num_qgroups));
+            qemu_log(", num_ref_copies = %" PRIu64,
+                     tswap64(target_inherit->num_ref_copies));
+            qemu_log(", num_excl_copies = %" PRIu64,
+                     tswap64(target_inherit->num_excl_copies));
+
+            qemu_log(", lim = {");
+            qemu_log("lim.flags = %" PRIu64,
+                     tswap64(target_inherit->lim.flags));
+            qemu_log(", lim.max_rfer = %" PRIu64,
+                     tswap64(target_inherit->lim.max_rfer));
+            qemu_log(", lim.max_excl = %" PRIu64,
+                     tswap64(target_inherit->lim.max_excl));
+            qemu_log(", lim.rsv_rfer = %" PRIu64,
+                     tswap64(target_inherit->lim.rsv_rfer));
+            qemu_log(", lim.rsv_excl = %" PRIu64 "}",
+                     tswap64(target_inherit->lim.rsv_excl));
+
+            qemu_log(", ...}, ");
+        }
+
+        unlock_user(target_inherit, inherit_addr, 0);
+    }
+#endif
+
+#ifdef BTRFS_DEVICE_SPEC_BY_ID
+    if (flags & BTRFS_DEVICE_SPEC_BY_ID) {
+        qemu_log(" devid = %" PRIu64, tswap64(target_args_v2->devid));
+        device_spec_by_id = 1;
+    }
+#endif
+#ifdef BTRFS_SUBVOL_SPEC_BY_ID
+    if (flags & BTRFS_SUBVOL_SPEC_BY_ID) {
+        qemu_log(" subvolid = %" PRIu64, tswap64(target_args_v2->subvolid));
+        subvol_spec_by_id = 1;
+    }
+#endif
+    if (!device_spec_by_id && !subvol_spec_by_id) {
+        qemu_log(" name = \"%s\"", target_args_v2->name);
+    }
+
+    qemu_log("}");
+}
+#endif
+
 #undef UNUSED
 
 #ifdef TARGET_NR_accept
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b58098b5bb..78d7106b80 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5668,6 +5668,83 @@ static const StructEntry struct_termios_def = {
     .print = print_termios,
 };
 
+#if defined(BTRFS_IOC_SUBVOL_CREATE_V2) || defined(BTRFS_IOC_SNAP_CREATE_V2) \
+ || defined(BTRFS_SNAP_DESTROY_V2)      || defined(BTRFS_RM_DEV_V2)
+static void target_to_host_btrfs_ioctl_vol_args_v2(void *dst, const void *src)
+{
+    struct btrfs_ioctl_vol_args_v2 *host_args_v2 = dst;
+    const struct target_btrfs_ioctl_vol_args_v2 *target_args_v2 = src;
+    int device_spec_by_id = 0;
+    int subvol_spec_by_id = 0;
+
+    __get_user(host_args_v2->fd, &target_args_v2->fd);
+    __get_user(host_args_v2->flags, &target_args_v2->flags);
+    __get_user(host_args_v2->transid, &target_args_v2->transid);
+
+    if (host_args_v2->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
+        struct btrfs_qgroup_inherit *target_inherit;
+        abi_long inherit_addr = tswapal(target_args_v2->qgroup_inherit);
+
+        target_inherit = lock_user(VERIFY_READ, inherit_addr,
+                                   sizeof(*target_inherit), 1);
+
+        host_args_v2->qgroup_inherit = g_new(struct btrfs_qgroup_inherit, 1);
+
+        if (!target_inherit) {
+            host_args_v2->qgroup_inherit = NULL;
+        } else {
+            __get_user(host_args_v2->qgroup_inherit->flags,
+                       &target_inherit->flags);
+            __get_user(host_args_v2->qgroup_inherit->num_qgroups,
+                       &target_inherit->num_qgroups);
+            __get_user(host_args_v2->qgroup_inherit->num_ref_copies,
+                       &target_inherit->num_ref_copies);
+            __get_user(host_args_v2->qgroup_inherit->num_excl_copies,
+                       &target_inherit->num_excl_copies);
+            __get_user(host_args_v2->qgroup_inherit->lim.flags,
+                       &target_inherit->lim.flags);
+            __get_user(host_args_v2->qgroup_inherit->lim.max_rfer,
+                       &target_inherit->lim.max_rfer);
+            __get_user(host_args_v2->qgroup_inherit->lim.max_excl,
+                       &target_inherit->lim.max_excl);
+            __get_user(host_args_v2->qgroup_inherit->lim.rsv_rfer,
+                       &target_inherit->lim.rsv_rfer);
+            __get_user(host_args_v2->qgroup_inherit->lim.rsv_excl,
+                       &target_inherit->lim.rsv_excl);
+        }
+
+        unlock_user(target_inherit, inherit_addr, 0);
+    }
+
+#ifdef BTRFS_DEVICE_SPEC_BY_ID
+    if (host_args_v2->flags & BTRFS_DEVICE_SPEC_BY_ID) {
+        __get_user(host_args_v2->devid, &target_args_v2->devid);
+        device_spec_by_id = 1;
+    }
+#endif
+#ifdef BTRFS_SUBVOL_SPEC_BY_ID
+    if (host_args_v2->flags & BTRFS_SUBVOL_SPEC_BY_ID) {
+        __get_user(host_args_v2->subvolid, &target_args_v2->subvolid);
+        subvol_spec_by_id = 1;
+    }
+#endif
+
+    if (!device_spec_by_id & !subvol_spec_by_id) {
+        memcpy(host_args_v2->name, target_args_v2->name,
+               BTRFS_SUBVOL_NAME_MAX + 1);
+    }
+}
+
+static const StructEntry struct_btrfs_ioctl_vol_args_v2_def = {
+    .convert = { NULL, target_to_host_btrfs_ioctl_vol_args_v2},
+    .print = print_btrfs_ioctl_vol_args_v2,
+    .align = { __alignof__(struct target_btrfs_ioctl_vol_args_v2),
+               __alignof__(struct btrfs_ioctl_vol_args_v2) },
+    .size = { sizeof(struct target_btrfs_ioctl_vol_args_v2),
+              sizeof(struct btrfs_ioctl_vol_args_v2) },
+};
+#endif
+
 static bitmask_transtbl mmap_flags_tbl[] = {
     { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
     { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 969377d622..d2d4d1e1cb 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -967,6 +967,26 @@ struct target_rtc_pll_info {
 #define TARGET_FS_IOC32_GETVERSION TARGET_IOR('v', 1, int)
 #define TARGET_FS_IOC32_SETVERSION TARGET_IOW('v', 2, int)
 
+#define TARGET_BTRFS_SUBVOL_NAME_MAX    4039
+
+struct target_btrfs_ioctl_vol_args_v2 {
+    uint64_t fd;
+    uint64_t transid;
+    uint64_t flags;
+    union {
+        struct {
+            uint64_t size;
+            abi_long qgroup_inherit;
+        };
+        uint64_t unused[4];
+    };
+    union {
+        char name[TARGET_BTRFS_SUBVOL_NAME_MAX + 1];
+        uint64_t devid;
+        uint64_t subvolid;
+    };
+};
+
 /* btrfs ioctls */
 #define TARGET_BTRFS_IOC_SNAP_CREATE            TARGET_IOWU(BTRFS_IOCTL_MAGIC, 1)
 #define TARGET_BTRFS_IOC_SCAN_DEV               TARGET_IOWU(BTRFS_IOCTL_MAGIC, 4)
@@ -978,6 +998,10 @@ struct target_rtc_pll_info {
 #define TARGET_BTRFS_IOC_INO_LOOKUP             TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 18)
 #define TARGET_BTRFS_IOC_DEFAULT_SUBVOL         TARGET_IOW(BTRFS_IOCTL_MAGIC, 19,\
                                                            abi_ullong)
+#define TARGET_BTRFS_IOC_SNAP_CREATE_V2         TARGET_IOW(BTRFS_IOCTL_MAGIC, 23,\
+                                            struct target_btrfs_ioctl_vol_args_v2)
+#define TARGET_BTRFS_IOC_SUBVOL_CREATE_V2       TARGET_IOW(BTRFS_IOCTL_MAGIC, 24,\
+                                            struct target_btrfs_ioctl_vol_args_v2)
 #define TARGET_BTRFS_IOC_SUBVOL_GETFLAGS        TARGET_IOR(BTRFS_IOCTL_MAGIC, 25,\
                                                            abi_ullong)
 #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGS        TARGET_IOW(BTRFS_IOCTL_MAGIC, 26,\
@@ -999,10 +1023,14 @@ struct target_rtc_pll_info {
 #define TARGET_BTRFS_IOC_GET_FEATURES           TARGET_IORU(BTRFS_IOCTL_MAGIC, 57)
 #define TARGET_BTRFS_IOC_SET_FEATURES           TARGET_IOWU(BTRFS_IOCTL_MAGIC, 57)
 #define TARGET_BTRFS_IOC_GET_SUPPORTED_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57)
+#define TARGET_BTRFS_IOC_RM_DEV_V2              TARGET_IOW(BTRFS_IOCTL_MAGIC, 58,\
+                                            struct target_btrfs_ioctl_vol_args_v2)
 #define TARGET_BTRFS_IOC_LOGICAL_INO_V2         TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 59)
 #define TARGET_BTRFS_IOC_GET_SUBVOL_INFO        TARGET_IORU(BTRFS_IOCTL_MAGIC, 60)
 #define TARGET_BTRFS_IOC_GET_SUBVOL_ROOTREF     TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 61)
 #define TARGET_BTRFS_IOC_INO_LOOKUP_USER        TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 62)
+#define TARGET_BTRFS_IOC_SNAP_DESTROY_V2        TARGET_IOW(BTRFS_IOCTL_MAGIC, 63,\
+                                            struct target_btrfs_ioctl_vol_args_v2)
 
 /* usb ioctls */
 #define TARGET_USBDEVFS_CONTROL TARGET_IOWRU('U', 0)
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 8d4b5b3e92..83aee1fcf9 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -358,6 +358,11 @@ STRUCT(btrfs_ioctl_vol_args,
        TYPE_LONGLONG, /* fd */
        MK_ARRAY(TYPE_CHAR, BTRFS_PATH_NAME_MAX + 1)) /* name */
 
+#if defined(BTRFS_IOC_SUBVOL_CREATE_V2) || defined(BTRFS_IOC_SNAP_CREATE_V2) \
+ || defined(BTRFS_IOC_SNAP_DESTROY_V2)  || defined(BTRFS_IOC_RM_DEV_V2)
+STRUCT_SPECIAL(btrfs_ioctl_vol_args_v2)
+#endif
+
 STRUCT(btrfs_ioctl_timespec,
        TYPE_ULONGLONG, /* sec */
        TYPE_INT) /* nsec */
diff --git a/thunk.c b/thunk.c
index 0718325d86..0dfecb644b 100644
--- a/thunk.c
+++ b/thunk.c
@@ -246,7 +246,7 @@ const argtype *thunk_convert(void *dst, const void *src,
 
             assert(*type_ptr < max_struct_entries);
             se = struct_entries + *type_ptr++;
-            if (se->convert[0] != NULL) {
+            if (se->convert[to_host] != NULL) {
                 /* specific conversion is needed */
                 (*se->convert[to_host])(dst, src);
             } else {
