/*
* Copyright (c) 2016 Jeff Mahoney <jeffm@suse.com>
+ * Copyright (c) 2016-2018 The strace developers.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*/
#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 "print_fields.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;
# 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)
{
tprintf(", %s=%" PRIu64, name, value);
if (value == UINT64_MAX)
- tprints(" /* UINT64_MAX */");
+ tprints_comment("UINT64_MAX");
}
#define print_member_u64(obj, name) print_u64(#name, obj->name)
}
static void
-btrfs_print_balance(struct tcb *tcp, const long arg, bool out)
+btrfs_print_balance(struct tcb *const tcp, const kernel_ulong_t arg, bool out)
{
struct btrfs_ioctl_balance_args balance_args;
static void
btrfs_print_key_type(uint32_t type)
{
- const char *str = xlookup(btrfs_key_types, type);
tprintf("%u", type);
- if (str)
- tprintf(" /* %s */", str);
+ tprints_comment(xlookup(btrfs_key_types, type));
}
static void
btrfs_print_objectid(uint64_t objectid)
{
- const char *str = xlookup(btrfs_tree_objectids, objectid);
tprintf("%" PRIu64, objectid);
- if (str)
- tprintf(" /* %s */", str);
+ tprints_comment(xlookup(btrfs_tree_objectids, objectid));
}
static void
const uint64_t val_addr =
inodes_addr + offsetof(typeof(container), val);
uint64_t record[3];
- print_array(tcp, val_addr, container.elem_cnt,
+ print_array(tcp, val_addr, container.elem_cnt / 3,
record, sizeof(record),
umoven_or_printaddr,
print_btrfs_data_container_logical_ino, 0);
static bool
print_uint64(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
{
- tprintf("%" PRIu64, * (uint64_t *) elem_buf);
+ tprintf("%" PRIu64, *(uint64_t *) elem_buf);
return true;
}
static void
-btrfs_print_qgroup_inherit(struct tcb *tcp, const uint64_t qgi_addr)
+btrfs_print_qgroup_inherit(struct tcb *const tcp, const kernel_ulong_t 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
if (value) {
tprintf(", %s=%" PRIu64, name, value);
if (value == UINT64_MAX)
- tprints(" /* UINT64_MAX */");
+ tprints_comment("UINT64_MAX");
}
}
#define print_key_value(tcp, key, name) \
print_key_value_internal((tcp), #name, (key)->name)
-static bool
-print_btrfs_ioctl_search_header(struct tcb *tcp, void *elem_buf,
- size_t elem_size, void *data)
-{
- const struct btrfs_ioctl_search_header *sh = elem_buf;
-
- 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);
-
- return true;
-}
-
static void
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 ||
if (abbrev(tcp))
tprints("...");
else {
- struct btrfs_ioctl_search_header sh;
+ 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;
- print_array(tcp, buf_addr, key->nr_items,
- &sh, sizeof(sh),
- umoven_or_printaddr,
- print_btrfs_ioctl_search_header, 0);
+ }
+ tprints("]");
}
tprints("}");
}
print_objectid_callback(struct tcb *tcp, void *elem_buf,
size_t elem_size, void *data)
{
- btrfs_print_objectid(* (uint64_t *) elem_buf);
+ btrfs_print_objectid(*(uint64_t *) elem_buf);
return true;
}
return true;
}
-int
-btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
+MPERS_PRINTER_DECL(int, btrfs_ioctl,
+ struct tcb *const tcp, const unsigned int code,
+ const kernel_ulong_t arg)
{
switch (code) {
/* Take no arguments; command only. */
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 */");
+ tprints_comment("UINT64_MAX");
tprints(", flags=");
printflags64(btrfs_defrag_flags, args.flags,
if (valid)
tprintf("uuid=%s, ", uuid);
tprintf("bytes_used=%" PRI__u64
- ", total_bytes=%" PRI__u64 ", path=",
+ ", total_bytes=%" PRI__u64,
args.bytes_used, args.total_bytes);
- print_quoted_string((const char *)args.path, sizeof(args.path),
- QUOTE_0_TERMINATED);
+ PRINT_FIELD_CSTRING(", ", args, path);
tprints("}");
break;
}
case BTRFS_IOC_DEV_REPLACE: { /* RW */
- struct btrfs_ioctl_dev_replace_args args;
+ struct_btrfs_ioctl_dev_replace_args args;
if (entering(tcp))
tprints(", ");
"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,
- sizeof(args.start.srcdev_name),
- QUOTE_0_TERMINATED);
+ str = (const char *) args.start.srcdev_name;
+ print_quoted_cstring(str,
+ sizeof(args.start.srcdev_name));
tprints(", tgtdev_name=");
- str = (const char*) args.start.tgtdev_name;
- print_quoted_string(str,
- sizeof(args.start.tgtdev_name),
- QUOTE_0_TERMINATED);
+ str = (const char *) args.start.tgtdev_name;
+ print_quoted_cstring(str,
+ sizeof(args.start.tgtdev_name));
tprints("}");
}
printxval64(btrfs_dev_replace_results, args.result,
"BTRFS_IOCTL_DEV_REPLACE_RESULT_???");
if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS) {
- char buf[sizeof("HH:MM:SS") + 1];
- time_t time;
tprints(", ");
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);
- else
- tprints("???");
- tprints(" */ ,");
-
- time = args.status.time_started;
- strftime(buf, sizeof(buf), "%T",
- localtime(&time));
- tprintf("time_started=%" PRI__u64" /* %s */, ",
- 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("num_write_errors=%" PRI__u64
- ", num_uncorrectable_read_errors=%" PRI__u64,
- args.status.num_write_errors,
- args.status.num_uncorrectable_read_errors);
+ tprintf_comment("%u.%u%%",
+ (unsigned) args.status.progress_1000 / 10,
+ (unsigned) args.status.progress_1000 % 10);
+
+ tprintf(", time_started=%" PRIu64,
+ (uint64_t) args.status.time_started);
+ tprints_comment(sprinttime(args.status.time_started));
+
+ tprintf(", time_stopped=%" PRIu64,
+ (uint64_t) args.status.time_stopped);
+ tprints_comment(sprinttime(args.status.time_stopped));
+
+ 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;
if (umove_or_printaddr(tcp, arg, &flarg))
break;
- tprints("[ /* supported */ ");
+ tprints("[");
btrfs_print_features(&flarg[0]);
+ tprints_comment("supported");
- tprints(", /* safe to set */ ");
+ tprints(", ");
btrfs_print_features(&flarg[1]);
+ tprints_comment("safe to set");
- tprints(", /* safe to clear */ ");
+ tprints(", ");
btrfs_print_features(&flarg[2]);
+ tprints_comment("safe to clear");
tprints("]");
break;
char uuid[UUID_STRING_SIZE+1];
uint32_t nodesize, sectorsize, clone_alignment;
#ifndef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE
- __u32 *reserved32;
+ uint32_t *reserved32;
#endif
if (entering(tcp))
sectorsize = args.sectorsize,
clone_alignment = args.clone_alignment;
#else
- reserved32 = (__u32 *)args.reserved;
+ reserved32 = (void *) args.reserved;
nodesize = reserved32[0];
sectorsize = reserved32[1];
clone_alignment = reserved32[2];
tprints("...");
break;
}
- const char *name = xlookup(btrfs_dev_stats_values, i);
- if (name)
- tprintf("/* %s */ ", name);
tprintf("%" PRI__u64, args.values[i]);
+ tprints_comment(xlookup(btrfs_dev_stats_values, i));
}
tprints("]}");
break;
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);
}
tprints("{");
- if (tcp->auxstr) {
- tcp->auxstr = NULL;
+ if (get_tcb_priv_ulong(tcp)) {
tprints("treeid=");
btrfs_print_objectid(args.treeid);
tprints(", ");
}
- tprints("name=");
- print_quoted_string(args.name, sizeof(args.name),
- QUOTE_0_TERMINATED);
+ PRINT_FIELD_CSTRING("", args, name);
tprints("}");
break;
}
if (umove_or_printaddr(tcp, arg, &args))
break;
- tprintf("{flags=%" PRI__u64 "}", args.flags);
+ tprintf("{flags=%" PRIu64 "}", (uint64_t) args.flags);
break;
}
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))
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;
}
args.start);
tprintf("%" PRI__u64, args.end);
if (args.end == UINT64_MAX)
- tprints(" /* UINT64_MAX */");
+ tprints_comment("UINT64_MAX");
tprints(", flags=");
printflags64(btrfs_scrub_flags, args.flags,
"BTRFS_SCRUB_???");
}
case BTRFS_IOC_SEND: { /* W */
- struct btrfs_ioctl_send_args args;
+ 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))
tprints("...");
else {
uint64_t record;
- print_array(tcp, (unsigned long) args.clone_sources,
+ print_array(tcp, ptr_to_kulong(args.clone_sources),
args.clone_sources_count,
&record, sizeof(record),
umoven_or_printaddr,
if (umove_or_printaddr(tcp, arg, &args))
break;
- tprintf("{fd=%" PRI__d64 ", name=", args.fd);
- print_quoted_string(args.name, sizeof(args.name),
- QUOTE_0_TERMINATED);
+ tprints("{fd=");
+ printfd(tcp, args.fd);
+ PRINT_FIELD_CSTRING(", ", args, name);
tprints("}");
break;
}
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(", ");
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=%" PRIu64 ", qgroup_inherit=",
+ (uint64_t) args.size);
btrfs_print_qgroup_inherit(tcp,
- (unsigned long)args.qgroup_inherit);
+ ptr_to_kulong(args.qgroup_inherit));
}
- tprintf(", name=");
- print_quoted_string(args.name, sizeof(args.name),
- QUOTE_0_TERMINATED);
+ PRINT_FIELD_CSTRING(", ", args, name);
tprints("}");
return 0;
}
- tprintf("{transid=%" PRI__u64 "}", args.transid);
+ tprintf("{transid=%" PRIu64 "}", (uint64_t) args.transid);
break;
}
tprints(", ");
if (umove_or_printaddr(tcp, arg, &label))
break;
- print_quoted_string(label, sizeof(label), QUOTE_0_TERMINATED);
+ print_quoted_cstring(label, sizeof(label));
break;
}
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
default:
return RVAL_DECODED;
};
- return RVAL_DECODED | 1;
+ return RVAL_IOCTL_DECODED;
}
#endif /* HAVE_LINUX_BTRFS_H */