]> granicus.if.org Git - strace/blobdiff - btrfs.c
Include "kernel_types.h" in defs.h and tests/tests.h
[strace] / btrfs.c
diff --git a/btrfs.c b/btrfs.c
index 0f1f2688d2987636ebd206456d44e9e675f14466..1306ceffcc327bb783fe53a3c0acd85de65a9cdb 100644 (file)
--- a/btrfs.c
+++ b/btrfs.c
  */
 
 #include "defs.h"
-#include <linux/fs.h>
+
+#ifdef HAVE_LINUX_BTRFS_H
+
+#include DEF_MPERS_TYPE(struct_btrfs_ioctl_dev_replace_args)
+#include DEF_MPERS_TYPE(struct_btrfs_ioctl_send_args)
+#include DEF_MPERS_TYPE(struct_btrfs_ioctl_received_subvol_args)
+#include DEF_MPERS_TYPE(struct_btrfs_ioctl_vol_args_v2)
+
+# include <linux/btrfs.h>
+
+typedef struct btrfs_ioctl_dev_replace_args
+       struct_btrfs_ioctl_dev_replace_args;
+typedef struct btrfs_ioctl_send_args
+       struct_btrfs_ioctl_send_args;
+typedef struct btrfs_ioctl_received_subvol_args
+       struct_btrfs_ioctl_received_subvol_args;
+typedef struct btrfs_ioctl_vol_args_v2
+       struct_btrfs_ioctl_vol_args_v2;
+
+#endif /* HAVE_LINUX_BTRFS_H */
+
+#include MPERS_DEFS
+
 #ifdef HAVE_LINUX_BTRFS_H
+
+#include <linux/fs.h>
+
 /*
  * Prior to Linux 3.12, the BTRFS_IOC_DEFAULT_SUBVOL used u64 in
  * its definition, which isn't exported by the kernel.
  */
 typedef __u64 u64;
 
-#include <linux/btrfs.h>
-
 #ifndef HAVE_STRUCT_BTRFS_IOCTL_FEATURE_FLAGS_COMPAT_FLAGS
 struct btrfs_ioctl_feature_flags {
        uint64_t compat_flags;
@@ -55,10 +78,6 @@ struct btrfs_ioctl_defrag_range_args {
 };
 #endif
 
-#ifndef BTRFS_SUBVOL_NAME_MAX
-# define BTRFS_SUBVOL_NAME_MAX 4039
-#endif
-
 #ifndef BTRFS_LABEL_SIZE
 # define BTRFS_LABEL_SIZE 256
 #endif
@@ -67,6 +86,20 @@ struct btrfs_ioctl_defrag_range_args {
 # define BTRFS_FIRST_FREE_OBJECTID 256ULL
 #endif
 
+#ifndef BTRFS_IOC_QUOTA_RESCAN
+struct btrfs_ioctl_quota_rescan_args {
+       uint64_t flags, progress, reserved[6];
+};
+# define BTRFS_IOC_QUOTA_RESCAN _IOW(BTRFS_IOCTL_MAGIC, 44, \
+                                       struct btrfs_ioctl_quota_rescan_args)
+# define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \
+                                       struct btrfs_ioctl_quota_rescan_args)
+#endif
+
+#ifndef BTRFS_IOC_QUOTA_RESCAN_WAIT
+# define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46)
+#endif
+
 #ifndef BTRFS_IOC_GET_FEATURES
 # define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \
                                        struct btrfs_ioctl_feature_flags)
@@ -153,7 +186,7 @@ print_u64(const char *name, uint64_t value)
 #define print_member_u64(obj, name) print_u64(#name, obj->name)
 
 static void
-btrfs_print_balance_args(const char *name, struct btrfs_balance_args *bba)
+btrfs_print_balance_args(const char *name, const struct btrfs_balance_args *bba)
 {
        tprintf(", %s={profiles=", name);
        printflags64(btrfs_space_info_flags, bba->profiles,
@@ -197,7 +230,7 @@ btrfs_print_balance(struct tcb *tcp, const long arg, bool out)
 }
 
 static void
-btrfs_print_features(struct btrfs_ioctl_feature_flags *flags)
+btrfs_print_features(const struct btrfs_ioctl_feature_flags *flags)
 {
        tprints("{compat_flags=");
        printflags64(btrfs_features_compat, flags->compat_flags,
@@ -214,7 +247,7 @@ btrfs_print_features(struct btrfs_ioctl_feature_flags *flags)
 }
 
 static void
-btrfs_print_qgroup_limit(struct btrfs_qgroup_limit *lim)
+btrfs_print_qgroup_limit(const struct btrfs_qgroup_limit *lim)
 {
        tprints("{flags=");
        printflags64(btrfs_qgroup_limit_flags, lim->flags,
@@ -244,7 +277,7 @@ btrfs_print_objectid(uint64_t objectid)
 }
 
 static void
-btrfs_print_data_container_header(struct btrfs_data_container *container)
+btrfs_print_data_container_header(const struct btrfs_data_container *container)
 {
        tprintf("{bytes_left=%u, bytes_missing=%u"
                ", elem_cnt=%u, elem_missed=%u, val=",
@@ -258,97 +291,99 @@ btrfs_print_data_container_footer(void)
        tprints("}");
 }
 
-static uint64_t
-data_container_record_offset(unsigned int index)
+static bool
+print_btrfs_data_container_logical_ino(struct tcb *tcp, void *elem_buf,
+                                      size_t elem_size, void *data)
 {
-       return offsetof(struct btrfs_data_container, val[index]);
+       const uint64_t *const record = elem_buf;
+
+       tprintf("{inum=%" PRIu64 ", offset=%" PRIu64 ", root=%" PRIu64 "}",
+               record[0], record[1], record[2]);
+
+       return true;
 }
 
 static void
-btrfs_print_logical_ino_container(struct tcb *tcp, uint64_t inodes_addr)
+btrfs_print_logical_ino_container(struct tcb *tcp,
+                                 const uint64_t inodes_addr)
 {
        struct btrfs_data_container container;
-       uint32_t i;
-       uint32_t printed = 0;
 
        if (umove_or_printaddr(tcp, inodes_addr, &container))
                return;
 
        btrfs_print_data_container_header(&container);
+
        if (abbrev(tcp)) {
                tprints("...");
-               btrfs_print_data_container_footer();
-               return;
+       } else {
+               const uint64_t val_addr =
+                       inodes_addr + offsetof(typeof(container), val);
+               uint64_t record[3];
+               print_array(tcp, val_addr, container.elem_cnt / 3,
+                           record, sizeof(record),
+                           umoven_or_printaddr,
+                           print_btrfs_data_container_logical_ino, 0);
        }
 
-       tprints("[");
+       btrfs_print_data_container_footer();
+}
 
-       for (i = 0; i < container.elem_cnt; i += 3, printed++) {
-               uint64_t offset = data_container_record_offset(i);
-               uint64_t record[3];
+static bool
+print_btrfs_data_container_ino_path(struct tcb *tcp, void *elem_buf,
+                                      size_t elem_size, void *data)
+{
+       const uint64_t *const offset = elem_buf;
+       const uint64_t *const val_addr = data;
 
-               if (i)
-                       tprints(", ");
+       printpath(tcp, *val_addr + *offset);
 
-               if (printed > max_strlen ||
-                   umove(tcp, inodes_addr + offset, &record)) {
-                       tprints("...");
-                       break;
-               }
-               tprintf("{inum=%" PRIu64 ", offset=%" PRIu64
-                       ", root=%" PRIu64 "}", record[0], record[1], record[2]);
-       }
-       tprints("]");
-       btrfs_print_data_container_footer();
+       return true;
 }
 
 static void
-btrfs_print_ino_path_container(struct tcb *tcp, uint64_t fspath_addr)
+btrfs_print_ino_path_container(struct tcb *tcp,
+                              const uint64_t fspath_addr)
 {
        struct btrfs_data_container container;
-       uint32_t i;
 
        if (umove_or_printaddr(tcp, fspath_addr, &container))
                return;
 
        btrfs_print_data_container_header(&container);
+
        if (abbrev(tcp)) {
                tprints("...");
-               btrfs_print_data_container_footer();
-               return;
+       } else {
+               uint64_t val_addr =
+                       fspath_addr + offsetof(typeof(container), val);
+               uint64_t offset;
+               print_array(tcp, val_addr, container.elem_cnt,
+                           &offset, sizeof(offset),
+                           umoven_or_printaddr,
+                           print_btrfs_data_container_ino_path, &val_addr);
        }
 
-       tprints("[");
-
-       for (i = 0; i < container.elem_cnt; i++) {
-               uint64_t offset = data_container_record_offset(i);
-               uint64_t ptr;
-
-               if (i)
-                       tprints(", ");
+       btrfs_print_data_container_footer();
+}
 
-               if (i > max_strlen ||
-                   umove(tcp, fspath_addr + offset, &ptr)) {
-                       tprints("...");
-                       break;
-               }
+static bool
+print_uint64(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
+{
+       tprintf("%" PRIu64, * (uint64_t *) elem_buf);
 
-               printpath(tcp,
-                         fspath_addr + data_container_record_offset(0) + ptr);
-       }
-       tprints("]");
-       btrfs_print_data_container_footer();
+       return true;
 }
 
 static void
-btrfs_print_qgroup_inherit(struct tcb *tcp, uint64_t qgi_addr)
+btrfs_print_qgroup_inherit(struct tcb *tcp, const unsigned long qgi_addr)
 {
        struct btrfs_qgroup_inherit inherit;
 
        if (umove_or_printaddr(tcp, qgi_addr, &inherit))
                return;
 
-       tprintf("{flags=");
+       tprints("{flags=");
        printflags64(btrfs_qgroup_inherit_flags, inherit.flags,
                     "BTRFS_QGROUP_INHERIT_???");
        tprintf(", num_qgroups=%" PRI__u64 ", num_ref_copies=%" PRI__u64
@@ -363,23 +398,10 @@ btrfs_print_qgroup_inherit(struct tcb *tcp, uint64_t qgi_addr)
        if (abbrev(tcp)) {
                tprints("...");
        } else {
-               uint32_t i;
-
-               tprints("[");
-               for (i = 0; i < inherit.num_qgroups; i++) {
-                       uint64_t offset = offsetof(typeof(inherit), qgroups[i]);
-                       uint64_t record;
-                       if (i)
-                               tprints(", ");
-                       if (i > max_strlen ||
-                           umove(tcp, qgi_addr + offset, &record)) {
-                               tprints("...");
-                               break;
-                       }
-
-                       tprintf("%" PRIu64, record);
-               }
-               tprints("]");
+               uint64_t record;
+               print_array(tcp, qgi_addr + offsetof(typeof(inherit), qgroups),
+                           inherit.num_qgroups, &record, sizeof(record),
+                           umoven_or_printaddr, print_uint64, 0);
        }
        tprints("}");
 }
@@ -401,7 +423,7 @@ btrfs_print_tree_search(struct tcb *tcp, struct btrfs_ioctl_search_key *key,
                        uint64_t buf_addr, uint64_t buf_size, bool print_size)
 {
        if (entering(tcp)) {
-               tprintf("{key={tree_id=");
+               tprints("{key={tree_id=");
                btrfs_print_objectid(key->tree_id);
 
                if (key->min_objectid != BTRFS_FIRST_FREE_OBJECTID ||
@@ -429,44 +451,68 @@ btrfs_print_tree_search(struct tcb *tcp, struct btrfs_ioctl_search_key *key,
                if (print_size)
                        tprintf(", buf_size=%" PRIu64, buf_size);
                tprints("}");
-               return;
-       }
-       tprintf("{key={nr_items=%u}", key->nr_items);
-       if (print_size)
-               tprintf(", buf_size=%" PRIu64, buf_size);
-       tprints(", buf=");
-       if (abbrev(tcp))
-               tprints("...");
-       else {
-               uint64_t i;
-               uint64_t off = 0;
-               tprints("[");
-               for (i = 0; i < key->nr_items; i++) {
-                       struct btrfs_ioctl_search_header sh;
-                       uint64_t addr = buf_addr + off;
-                       if (i)
-                               tprints(", ");
-                       if (i > max_strlen ||
-                           umove(tcp, addr, &sh)) {
-                               tprints("...");
-                               break;
+       } else {
+               tprintf("{key={nr_items=%u}", key->nr_items);
+               if (print_size)
+                       tprintf(", buf_size=%" PRIu64, buf_size);
+               tprints(", buf=");
+               if (abbrev(tcp))
+                       tprints("...");
+               else {
+                       uint64_t i;
+                       uint64_t off = 0;
+                       tprints("[");
+                       for (i = 0; i < key->nr_items; i++) {
+                               struct btrfs_ioctl_search_header sh;
+                               uint64_t addr = buf_addr + off;
+                               if (i)
+                                       tprints(", ");
+                               if (i > max_strlen ||
+                                   umove(tcp, addr, &sh)) {
+                                       tprints("...");
+                                       break;
+                               }
+                               tprintf("{transid=%" PRI__u64 ", objectid=",
+                                       sh.transid);
+                               btrfs_print_objectid(sh.objectid);
+                               tprintf(", offset=%" PRI__u64 ", type=", sh.offset);
+                               btrfs_print_key_type(sh.type);
+                               tprintf(", len=%u}", sh.len);
+                               off += sizeof(sh) + sh.len;
+
                        }
-                       tprintf("{transid=%" PRI__u64 ", objectid=",
-                               sh.transid);
-                       btrfs_print_objectid(sh.objectid);
-                       tprintf(", offset=%" PRI__u64 ", type=", sh.offset);
-                       btrfs_print_key_type(sh.type);
-                       tprintf(", len=%u}", sh.len);
-                       off += sizeof(sh) + sh.len;
+                       tprints("]");
                }
-               tprints("]");
+               tprints("}");
        }
+}
 
-       tprints("}");
+static bool
+print_objectid_callback(struct tcb *tcp, void *elem_buf,
+                       size_t elem_size, void *data)
+{
+       btrfs_print_objectid(* (uint64_t *) elem_buf);
+
+       return true;
 }
 
-int
-btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
+static bool
+print_btrfs_ioctl_space_info(struct tcb *tcp, void *elem_buf,
+                            size_t elem_size, void *data)
+{
+       const struct btrfs_ioctl_space_info *info = elem_buf;
+
+       tprints("{flags=");
+       printflags64(btrfs_space_info_flags, info->flags,
+                    "BTRFS_SPACE_INFO_???");
+       tprintf(", total_bytes=%" PRI__u64 ", used_bytes=%" PRI__u64 "}",
+               info->total_bytes, info->used_bytes);
+
+       return true;
+}
+
+MPERS_PRINTER_DECL(int, btrfs_ioctl,
+                  struct tcb *tcp, const unsigned int code, const long arg)
 {
        switch (code) {
        /* Take no arguments; command only. */
@@ -561,7 +607,7 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
 
                tprintf("{start=%" PRIu64 ", len=", (uint64_t)args.start);
 
-               tprintf("%" PRIu64, args.len);
+               tprintf("%" PRIu64, (uint64_t) args.len);
                if (args.len == UINT64_MAX)
                        tprints(" /* UINT64_MAX */");
 
@@ -611,7 +657,7 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
        }
 
        case BTRFS_IOC_DEV_REPLACE: { /* RW */
-               struct btrfs_ioctl_dev_replace_args args;
+               struct_btrfs_ioctl_dev_replace_args args;
 
                if (entering(tcp))
                        tprints(", ");
@@ -629,11 +675,11 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                                    "BTRFS_IOCTL_DEV_REPLACE_CMD_???");
                        if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_START) {
                                const char *str;
-                               tprintf(", start={srcdevid=%" PRI__u64
-                                  ", cont_reading_from_srcdev_mode=%" PRI__u64
+                               tprintf(", start={srcdevid=%" PRIu64
+                                  ", cont_reading_from_srcdev_mode=%" PRIu64
                                   ", srcdev_name=",
-                                  args.start.srcdevid,
-                                  args.start.cont_reading_from_srcdev_mode);
+                                  (uint64_t) args.start.srcdevid,
+                                  (uint64_t) args.start.cont_reading_from_srcdev_mode);
 
                                str = (const char*) args.start.srcdev_name;
                                print_quoted_string(str,
@@ -661,12 +707,12 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                        printxval64(btrfs_dev_replace_state,
                                   args.status.replace_state,
                                   "BTRFS_IOCTL_DEV_REPLACE_STATE_???");
-                       tprintf(", progress_1000=%" PRI__u64 " /* ",
-                               args.status.progress_1000);
+                       tprintf(", progress_1000=%" PRIu64 " /* ",
+                               (uint64_t) args.status.progress_1000);
                        if (args.status.progress_1000 <= 1000)
-                               tprintf("%" PRI__u64 ".%.2" PRI__u64 "%%",
-                                       args.status.progress_1000 / 10,
-                                       args.status.progress_1000 % 10);
+                               tprintf("%" PRIu64 ".%.2" PRIu64 "%%",
+                                       (uint64_t) args.status.progress_1000 / 10,
+                                       (uint64_t) args.status.progress_1000 % 10);
                        else
                                tprints("???");
                        tprints(" */ ,");
@@ -674,19 +720,19 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                        time = args.status.time_started;
                        strftime(buf, sizeof(buf), "%T",
                                 localtime(&time));
-                       tprintf("time_started=%" PRI__u64" /* %s */, ",
-                               args.status.time_started, buf);
+                       tprintf("time_started=%" PRIu64" /* %s */, ",
+                               (uint64_t) args.status.time_started, buf);
 
                        time = args.status.time_stopped;
                        strftime(buf, sizeof(buf), "%T",
                                 localtime(&time));
-                       tprintf("time_stopped=%" PRI__u64" /* %s */, ",
-                               args.status.time_stopped, buf);
+                       tprintf("time_stopped=%" PRIu64" /* %s */, ",
+                               (uint64_t) args.status.time_stopped, buf);
 
-                       tprintf("num_write_errors=%" PRI__u64
-                               ", num_uncorrectable_read_errors=%" PRI__u64,
-                               args.status.num_write_errors,
-                               args.status.num_uncorrectable_read_errors);
+                       tprintf("num_write_errors=%" PRIu64
+                               ", num_uncorrectable_read_errors=%" PRIu64,
+                               (uint64_t) args.status.num_write_errors,
+                               (uint64_t) args.status.num_uncorrectable_read_errors);
                }
                tprints("}");
                break;
@@ -765,7 +811,7 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                sectorsize = args.sectorsize,
                clone_alignment = args.clone_alignment;
 #else
-               reserved32 = (__u32 *)args.reserved;
+               reserved32 = (__u32 *) (void *) args.reserved;
                nodesize = reserved32[0];
                sectorsize = reserved32[1];
                clone_alignment = reserved32[2];
@@ -784,7 +830,7 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
 
        case BTRFS_IOC_GET_DEV_STATS: { /* RW */
                struct btrfs_ioctl_get_dev_stats args;
-               uint64_t i, max_nr_items;
+               uint64_t i;
 
                if (entering(tcp))
                        tprints(", ");
@@ -814,17 +860,15 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                 * go off into the middle of nowhere with a bad nr_items
                 * value.
                 */
-               max_nr_items = sizeof(args) - offsetof(typeof(args), values);
-
                tprints(", [");
                for (i = 0; i < args.nr_items; i++) {
-                       const char *name = xlookup(btrfs_dev_stats_values, i);
                        if (i)
                                tprints(", ");
-                       if (i > max_nr_items) {
-                               tprints("/* overflow */");
+                       if (i >= ARRAY_SIZE(args.values)) {
+                               tprints("...");
                                break;
                        }
+                       const char *name = xlookup(btrfs_dev_stats_values, i);
                        if (name)
                                tprintf("/* %s */ ", name);
                        tprintf("%" PRI__u64, args.values[i]);
@@ -849,10 +893,7 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                if (entering(tcp)) {
                        /* Use subvolume id of the containing root */
                        if (args.treeid == 0)
-                               /* abuse of auxstr to retain state */
-                               tcp->auxstr = (void *)1;
-                       else
-                               tcp->auxstr = NULL;
+                               set_tcb_priv_ulong(tcp, 1);
 
                        tprints("{treeid=");
                        btrfs_print_objectid(args.treeid);
@@ -863,12 +904,11 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                }
 
                tprints("{");
-               if (tcp->auxstr) {
+               if (get_tcb_priv_ulong(tcp)) {
                        tprints("treeid=");
                        btrfs_print_objectid(args.treeid);
                        tprints(", ");
                }
-               tcp->auxstr = NULL;
 
                tprints("name=");
                print_quoted_string(args.name, sizeof(args.name),
@@ -997,7 +1037,7 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                if (umove_or_printaddr(tcp, arg, &args))
                        break;
 
-               tprintf("{flags=%" PRI__u64 "}", args.flags);
+               tprintf("{flags=%" PRIu64 "}", (uint64_t) args.flags);
                break;
        }
 
@@ -1011,18 +1051,14 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                if (umove_or_printaddr(tcp, arg, &args))
                        break;
 
-               tprintf("{flags=%" PRI__u64 ", progress=", args.flags);
+               tprintf("{flags=%" PRIu64 ", progress=", (uint64_t) args.flags);
                btrfs_print_objectid(args.progress);
                tprints("}");
                break;
        }
 
        case BTRFS_IOC_SET_RECEIVED_SUBVOL: { /* RW */
-#ifdef BTRFS_IOC_SET_RECEIVED_SUBVOL_32
-       case BTRFS_IOC_SET_RECEIVED_SUBVOL_32: { /* RW */
-               struct btrfs_ioctl_received_subvol_args_32 args32;
-#endif
-               struct btrfs_ioctl_received_subvol_args args;
+               struct_btrfs_ioctl_received_subvol_args args;
                char uuid[UUID_STRING_SIZE+1];
 
                if (entering(tcp))
@@ -1032,37 +1068,21 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                else
                        tprints(" => ");
 
-#ifdef BTRFS_IOC_SET_RECEIVED_SUBVOL_32
-               /*
-                * This is a compat ioctl for 32 bit tools on
-                * 64 bit systems.
-                */
-               if (code == BTRFS_IOC_SET_RECEIVED_SUBVOL_32) {
-                       if (umove_or_printaddr(tcp, arg, &args32))
-                               break;
-                       memcpy(args.uuid, args32.uuid, sizeof(uuid));
-                       args.stransid = args32.stransid;
-                       args.rtransid = args32.rtransid;
-                       args.stime.sec = args32.stime.sec;
-                       args.stime.nsec = args32.stime.nsec;
-                       args.rtime.sec = args32.rtime.sec;
-                       args.rtime.nsec = args32.rtime.nsec;
-                       args.flags = args32.flags;
-               } else
-#endif
                if (umove_or_printaddr(tcp, arg, &args))
                        break;
 
                if (entering(tcp)) {
                        btrfs_unparse_uuid((unsigned char *)args.uuid, uuid);
-                       tprintf("{uuid=%s, stransid=%" PRI__u64
-                               ", stime=%" PRI__u64 ".%u, flags=%" PRI__u64
-                               "}", uuid, args.stransid, args.stime.sec,
-                               args.stime.nsec, args.flags);
+                       tprintf("{uuid=%s, stransid=%" PRIu64
+                               ", stime=%" PRIu64 ".%u, flags=%" PRIu64
+                               "}", uuid, (uint64_t) args.stransid,
+                               (uint64_t) args.stime.sec, args.stime.nsec,
+                               (uint64_t) args.flags);
                        return 0;
                }
-               tprintf("{rtransid=%" PRI__u64 ", rtime=%" PRI__u64 ".%u}",
-                       args.rtransid, args.rtime.sec, args.rtime.nsec);
+               tprintf("{rtransid=%" PRIu64 ", rtime=%" PRIu64 ".%u}",
+                       (uint64_t) args.rtransid, (uint64_t) args.rtime.sec,
+                       args.rtime.nsec);
                break;
        }
 
@@ -1158,9 +1178,10 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                        tprints(", ");
                else if (syserror(tcp)) {
                        if (tcp->u_error == EOVERFLOW) {
+                               tprints(" => ");
                                tcp->u_error = 0;
                                if (!umove_or_printaddr(tcp, arg, &args))
-                                       tprintf(" => {buf_size=%" PRIu64 "}",
+                                       tprintf("{buf_size=%" PRIu64 "}",
                                                (uint64_t)args.buf_size);
                                tcp->u_error = EOVERFLOW;
                        }
@@ -1180,36 +1201,26 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
        }
 
        case BTRFS_IOC_SEND: { /* W */
-               struct btrfs_ioctl_send_args args;
-               uint64_t base_addr;
-               uint64_t i;
+               struct_btrfs_ioctl_send_args args;
 
                tprints(", ");
                if (umove_or_printaddr(tcp, arg, &args))
                        break;
 
-               tprintf("{send_fd=%" PRI__d64 ", clone_sources_count=%" PRI__u64
-                       ", clone_sources=", args.send_fd,
-                       args.clone_sources_count);
+               tprints("{send_fd=");
+               printfd(tcp, args.send_fd);
+               tprintf(", clone_sources_count=%" PRIu64 ", clone_sources=",
+                       (uint64_t) args.clone_sources_count);
 
-               if (abbrev(tcp)) {
+               if (abbrev(tcp))
                        tprints("...");
-               } else {
-                       tprints("[");
-                       base_addr = (unsigned long)args.clone_sources;
-                       for (i = 0; i < args.clone_sources_count; i++) {
-                               uint64_t offset = sizeof(uint64_t) * i;
-                               uint64_t record;
-                               if (i)
-                                       tprints(", ");
-                               if (i > max_strlen ||
-                                   umove(tcp, base_addr + offset, &record)) {
-                                       tprints("...");
-                                       break;
-                               }
-                               btrfs_print_objectid(record);
-                       }
-                       tprints("]");
+               else {
+                       uint64_t record;
+                       print_array(tcp, (unsigned long) args.clone_sources,
+                                   args.clone_sources_count,
+                                   &record, sizeof(record),
+                                   umoven_or_printaddr,
+                                   print_objectid_callback, 0);
                }
                tprints(", parent_root=");
                btrfs_print_objectid(args.parent_root);
@@ -1222,7 +1233,6 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
 
        case BTRFS_IOC_SPACE_INFO: { /* RW */
                struct btrfs_ioctl_space_args args;
-               uint64_t i;
 
                if (entering(tcp))
                        tprints(", ");
@@ -1249,33 +1259,16 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
 
                tprints(", spaces=");
 
-               if (abbrev(tcp)) {
-                       tprints("...}");
-                       break;
-               }
-
-               tprints("[");
-
-               for (i = 0; i < args.total_spaces; i++) {
+               if (abbrev(tcp))
+                       tprints("...");
+               else {
                        struct btrfs_ioctl_space_info info;
-                       uint64_t off = offsetof(typeof(args), spaces[i]);
-                       if (i)
-                               tprints(", ");
-
-                       if (i > max_strlen ||
-                           umove(tcp, arg + off, &info)) {
-                               tprints("...");
-                               break;
-                       }
-
-                       tprints("{flags=");
-                       printflags64(btrfs_space_info_flags, info.flags,
-                                    "BTRFS_SPACE_INFO_???");
-                       tprintf(", total_bytes=%" PRI__u64
-                               ", used_bytes=%" PRI__u64 "}",
-                               info.total_bytes, info.used_bytes);
+                       print_array(tcp, arg + offsetof(typeof(args), spaces),
+                                   args.total_spaces,
+                                   &info, sizeof(info), umoven_or_printaddr,
+                                   print_btrfs_ioctl_space_info, 0);
                }
-               tprints("]}");
+               tprints("}");
                break;
        }
 
@@ -1293,7 +1286,9 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                if (umove_or_printaddr(tcp, arg, &args))
                        break;
 
-               tprintf("{fd=%" PRI__d64 ", name=", args.fd);
+               tprints("{fd=");
+               printfd(tcp, args.fd);
+               tprints(", name=");
                print_quoted_string(args.name, sizeof(args.name),
                                    QUOTE_0_TERMINATED);
                tprints("}");
@@ -1302,7 +1297,7 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
 
        case BTRFS_IOC_SNAP_CREATE_V2:
        case BTRFS_IOC_SUBVOL_CREATE_V2: { /* code is W, but is actually RW */
-               struct btrfs_ioctl_vol_args_v2 args;
+               struct_btrfs_ioctl_vol_args_v2 args;
 
                if (entering(tcp))
                        tprints(", ");
@@ -1315,32 +1310,34 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
                        break;
 
                if (entering(tcp)) {
-                       tprintf("{fd=%" PRI__d64 ", flags=", args.fd);
+                       tprints("{fd=");
+                       printfd(tcp, args.fd);
+                       tprints(", flags=");
                        printflags64(btrfs_snap_flags_v2, args.flags,
                                     "BTRFS_SUBVOL_???");
                        if (args.flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
-                               tprintf(", size=%" PRI__u64 ", qgroup_inherit=",
-                                       args.size);
+                               tprintf(", size=%llu, qgroup_inherit=",
+                                       (unsigned long long) args.size);
 
                                btrfs_print_qgroup_inherit(tcp,
-                                       (unsigned long)args.qgroup_inherit);
-
+                                       (unsigned long) args.qgroup_inherit);
                        }
-                       tprintf(", name=");
-                       print_quoted_string(args.name,
-                                           BTRFS_SUBVOL_NAME_MAX + 1,
+                       tprints(", name=");
+                       print_quoted_string(args.name, sizeof(args.name),
                                            QUOTE_0_TERMINATED);
                        tprints("}");
                        return 0;
                }
-               tprintf("{transid=%" PRI__u64 "}", args.transid);
+               tprintf("{transid=%llu}", (unsigned long long) args.transid);
                break;
        }
+
        case BTRFS_IOC_GET_FSLABEL: /* R */
-       case BTRFS_IOC_SET_FSLABEL: {/* W */
-               char label[BTRFS_LABEL_SIZE];
-               if (code == BTRFS_IOC_GET_FSLABEL && entering(tcp))
+               if (entering(tcp))
                        return 0;
+               /* fall through */
+       case BTRFS_IOC_SET_FSLABEL: { /* W */
+               char label[BTRFS_LABEL_SIZE];
 
                tprints(", ");
                if (umove_or_printaddr(tcp, arg, &label))
@@ -1351,7 +1348,9 @@ btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
 
        case BTRFS_IOC_CLONE:                   /* FICLONE */
        case BTRFS_IOC_CLONE_RANGE:             /* FICLONERANGE */
+#ifdef BTRFS_IOC_FILE_EXTENT_SAME
        case BTRFS_IOC_FILE_EXTENT_SAME:        /* FIDEDUPERANGE */
+#endif
                /*
                 * FICLONE, FICLONERANGE, and FIDEDUPERANGE started out as
                 * btrfs ioctls and the code was kept for the generic