/*
* Copyright (c) 2009, 2010 Jeff Mahoney <jeffm@suse.com>
+ * Copyright (c) 2011-2016 Dmitry V. Levin <ldv@altlinux.org>
+ * Copyright (c) 2011-2018 The strace developers.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*/
#include "defs.h"
-#ifdef LINUX
-#include <stdint.h>
-#include <linux/blkpg.h>
+
+#include DEF_MPERS_TYPE(struct_blk_user_trace_setup)
+#include DEF_MPERS_TYPE(struct_blkpg_ioctl_arg)
+#include DEF_MPERS_TYPE(struct_blkpg_partition)
+
+#include <linux/ioctl.h>
#include <linux/fs.h>
-#include <linux/hdreg.h>
-/* ioctls <= 114 are present in Linux 2.4. The following ones have been
- * added since then and headers containing them may not be available on
- * every system. */
+typedef struct {
+ int op;
+ int flags;
+ int datalen;
+ void *data;
+} struct_blkpg_ioctl_arg;
+
+#define BLKPG_DEVNAMELTH 64
+#define BLKPG_VOLNAMELTH 64
+typedef struct {
+ int64_t start; /* starting offset in bytes */
+ int64_t length; /* length in bytes */
+ int pno; /* partition number */
+ char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2,
+ to be used in kernel messages */
+ char volname[BLKPG_VOLNAMELTH]; /* volume label */
+} struct_blkpg_partition;
#define BLKTRACE_BDEV_SIZE 32
-struct blk_user_trace_setup {
+typedef struct blk_user_trace_setup {
char name[BLKTRACE_BDEV_SIZE]; /* output */
uint16_t act_mask; /* input */
uint32_t buf_size; /* input */
uint64_t start_lba;
uint64_t end_lba;
uint32_t pid;
-};
+} struct_blk_user_trace_setup;
+
+#include MPERS_DEFS
+
+#include "print_fields.h"
+
+#ifndef BLKPG
+# define BLKPG _IO(0x12, 105)
+#endif
+
+/*
+ * ioctl numbers <= 114 are present in Linux 2.4. The following ones have been
+ * added since then and headers containing them may not be available on every
+ * system.
+ */
#ifndef BLKTRACESETUP
-#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup)
+# define BLKTRACESETUP _IOWR(0x12, 115, struct_blk_user_trace_setup)
#endif
#ifndef BLKTRACESTART
-#define BLKTRACESTART _IO(0x12,116)
+# define BLKTRACESTART _IO(0x12, 116)
#endif
-#ifndef BLKTRACESTART
-#define BLKTRACESTOP _IO(0x12,117)
+#ifndef BLKTRACESTOP
+# define BLKTRACESTOP _IO(0x12, 117)
#endif
#ifndef BLKTRACETEARDOWN
-#define BLKTRACETEARDOWN _IO(0x12,118)
+# define BLKTRACETEARDOWN _IO(0x12, 118)
#endif
#ifndef BLKDISCARD
-#define BLKDISCARD _IO(0x12,119)
+# define BLKDISCARD _IO(0x12, 119)
#endif
#ifndef BLKIOMIN
-#define BLKIOMIN _IO(0x12,120)
+# define BLKIOMIN _IO(0x12, 120)
#endif
#ifndef BLKIOOPT
-#define BLKIOOPT _IO(0x12,121)
+# define BLKIOOPT _IO(0x12, 121)
#endif
#ifndef BLKALIGNOFF
-#define BLKALIGNOFF _IO(0x12,122)
+# define BLKALIGNOFF _IO(0x12, 122)
#endif
#ifndef BLKPBSZGET
-#define BLKPBSZGET _IO(0x12,123)
+# define BLKPBSZGET _IO(0x12, 123)
#endif
#ifndef BLKDISCARDZEROES
-#define BLKDISCARDZEROES _IO(0x12,124)
+# define BLKDISCARDZEROES _IO(0x12, 124)
#endif
#ifndef BLKSECDISCARD
-#define BLKSECDISCARD _IO(0x12,125)
+# define BLKSECDISCARD _IO(0x12, 125)
+#endif
+#ifndef BLKROTATIONAL
+# define BLKROTATIONAL _IO(0x12, 126)
+#endif
+#ifndef BLKZEROOUT
+# define BLKZEROOUT _IO(0x12, 127)
#endif
-static const struct xlat blkpg_ops[] = {
- { BLKPG_ADD_PARTITION, "BLKPG_ADD_PARTITION", },
- { BLKPG_DEL_PARTITION, "BLKPG_DEL_PARTITION", },
- { 0, NULL },
-};
+#include "xlat/blkpg_ops.h"
static void
-print_blkpg_req(struct tcb *tcp, struct blkpg_ioctl_arg *blkpg)
+print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg)
{
- struct blkpg_partition p;
- const char *ioctl_name;
-
- ioctl_name = xlookup(blkpg_ops, blkpg->op);
- if (!ioctl_name) {
- tprintf("{%#x, /* BLKPG_??? */", blkpg->op);
- return;
- }
+ struct_blkpg_partition p;
- tprintf("{%s, flags=%d, datalen=%d, ",
- ioctl_name, blkpg->flags, blkpg->datalen);
+ PRINT_FIELD_XVAL("{", *blkpg, op, blkpg_ops, "BLKPG_???");
+ PRINT_FIELD_D(", ", *blkpg, flags);
+ PRINT_FIELD_D(", ", *blkpg, datalen);
- if (umove(tcp, (unsigned long)blkpg->data, &p) < 0) {
- tprintf("%#lx", (unsigned long)blkpg->data);
- return;
+ tprints(", data=");
+ if (!umove_or_printaddr(tcp, ptr_to_kulong(blkpg->data), &p)) {
+ PRINT_FIELD_D("{", p, start);
+ PRINT_FIELD_D(", ", p, length);
+ PRINT_FIELD_D(", ", p, pno);
+ PRINT_FIELD_CSTRING(", ", p, devname);
+ PRINT_FIELD_CSTRING(", ", p, volname);
+ tprints("}");
}
-
- tprintf("{start=%lld, length=%lld, pno=%d, ",
- p.start, p.length, p.pno);
-
- tprintf("devname=\"%s\", volname=\"%s\"}",
- p.devname, p.volname);
+ tprints("}");
}
-int
-block_ioctl(struct tcb *tcp, long code, long arg)
+MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp,
+ const unsigned int code, const kernel_ulong_t arg)
{
switch (code) {
-
- /* These pass arg as a value, not a pointer */
+ /* take arg as a value, not as a pointer */
case BLKRASET:
case BLKFRASET:
- if (entering(tcp))
- tprintf(", %ld", arg);
+ tprintf(", %" PRI_klu, arg);
break;
- /* Just pass in a signed int */
- case BLKROSET:
- case BLKBSZSET:
- if (entering(tcp)) {
- int int_val;
- if (umove(tcp, arg, &int_val) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", %d", int_val);
- }
- break;
-
- /* Just return an unsigned short */
+ /* return an unsigned short */
case BLKSECTGET:
- if (exiting(tcp)) {
- unsigned short ushort_val;
- if (umove(tcp, arg, &ushort_val) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", %hu", ushort_val);
- }
+ case BLKROTATIONAL:
+ if (entering(tcp))
+ return 0;
+ tprints(", ");
+ printnum_short(tcp, arg, "%hu");
break;
- /* Just return a signed int */
+ /* return a signed int */
case BLKROGET:
case BLKBSZGET:
case BLKSSZGET:
case BLKALIGNOFF:
- if (exiting(tcp)) {
- int int_val;
- if (umove(tcp, arg, &int_val) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", %d", int_val);
- }
+ if (entering(tcp))
+ return 0;
+ ATTRIBUTE_FALLTHROUGH;
+ /* take a signed int */
+ case BLKROSET:
+ case BLKBSZSET:
+ tprints(", ");
+ printnum_int(tcp, arg, "%d");
break;
- /* Just return an unsigned int */
+ /* return an unsigned int */
case BLKPBSZGET:
case BLKIOMIN:
case BLKIOOPT:
case BLKDISCARDZEROES:
- if (exiting(tcp)) {
- unsigned int uint_val;
- if (umove(tcp, arg, &uint_val) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", %u", uint_val);
- }
+ if (entering(tcp))
+ return 0;
+ tprints(", ");
+ printnum_int(tcp, arg, "%u");
break;
- /* Just return a signed long */
+ /* return a signed long */
case BLKRAGET:
case BLKFRAGET:
- if (exiting(tcp)) {
- long size;
- if (umove(tcp, arg, &size) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", %ld", size);
- }
+ if (entering(tcp))
+ return 0;
+ tprints(", ");
+ printnum_slong(tcp, arg);
break;
- /* Just return an unsigned long */
+ /* returns an unsigned long */
case BLKGETSIZE:
- if (exiting(tcp)) {
- unsigned long ulong_val;
- if (umove(tcp, arg, &ulong_val) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", %lu", ulong_val);
- }
+ if (entering(tcp))
+ return 0;
+ tprints(", ");
+ printnum_ulong(tcp, arg);
break;
- /* Just return a quad */
+#ifdef HAVE_BLKGETSIZE64
+ /* returns an uint64_t */
case BLKGETSIZE64:
- if (exiting(tcp)) {
- uint64_t uint64_val;
- if (umove(tcp, arg, &uint64_val) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", %llu",
- (unsigned long long)uint64_val);
- }
+ if (entering(tcp))
+ return 0;
+ tprints(", ");
+ printnum_int64(tcp, arg, "%" PRIu64);
break;
+#endif
- /* More complex types */
+ /* takes a pair of uint64_t */
case BLKDISCARD:
case BLKSECDISCARD:
- if (entering(tcp)) {
- uint64_t range[2];
- if (umove(tcp, arg, range) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", {%llx, %llx}",
- (unsigned long long)range[0],
- (unsigned long long)range[1]);
- }
+ case BLKZEROOUT:
+ tprints(", ");
+ printpair_int64(tcp, arg, "%" PRIu64);
break;
- case HDIO_GETGEO:
- if (exiting(tcp)) {
- struct hd_geometry geo;
- if (umove(tcp, arg, &geo) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", {heads=%hhu, sectors=%hhu, "
- "cylinders=%hu, start=%lu}",
- geo.heads, geo.sectors,
- geo.cylinders, geo.start);
- }
- break;
- case BLKPG:
- if (entering(tcp)) {
- struct blkpg_ioctl_arg blkpg;
- if (umove(tcp, arg, &blkpg) < 0)
- tprintf(", %#lx", arg);
- else {
- tprintf(", ");
- print_blkpg_req(tcp, &blkpg);
- }
- }
- if (exiting(tcp)) {
- tprintf("}");
- }
+ /* More complex types */
+ case BLKPG: {
+ struct_blkpg_ioctl_arg blkpg;
+
+ tprints(", ");
+ if (!umove_or_printaddr(tcp, arg, &blkpg))
+ print_blkpg_req(tcp, &blkpg);
break;
+ }
+
case BLKTRACESETUP:
if (entering(tcp)) {
- struct blk_user_trace_setup buts;
- if (umove(tcp, arg, &buts) < 0)
- tprintf(", %#lx", arg);
- else {
- tprintf(", {act_mask=%hu, buf_size=%u, ",
- buts.act_mask, buts.buf_size);
- tprintf("buf_nr=%u, start_lba=%llu, ",
- buts.buf_nr,
- (unsigned long long)buts.start_lba);
- tprintf("end_lba=%llu, pid=%u}",
- (unsigned long long)buts.end_lba,
- buts.pid);
- }
- }
- if (exiting(tcp)) {
- struct blk_user_trace_setup buts;
- if (umove(tcp, arg, &buts) < 0)
- tprintf(", %#lx", arg);
- else
- tprintf(", {name=\"%s\"}", buts.name);
+ struct_blk_user_trace_setup buts;
+
+ tprints(", ");
+ if (umove_or_printaddr(tcp, arg, &buts))
+ break;
+ PRINT_FIELD_U("{", buts, act_mask);
+ PRINT_FIELD_U(", ", buts, buf_size);
+ PRINT_FIELD_U(", ", buts, buf_nr);
+ PRINT_FIELD_U(", ", buts, start_lba);
+ PRINT_FIELD_U(", ", buts, end_lba);
+ PRINT_FIELD_U(", ", buts, pid);
+ return 0;
+ } else {
+ struct_blk_user_trace_setup buts;
+
+ if (!syserror(tcp) && !umove(tcp, arg, &buts))
+ PRINT_FIELD_CSTRING(", ", buts, name);
+ tprints("}");
+ break;
}
- break;
- /* No arguments or unhandled */
+
+ /* No arguments */
+ case BLKRRPART:
+ case BLKFLSBUF:
case BLKTRACESTART:
case BLKTRACESTOP:
case BLKTRACETEARDOWN:
- case BLKFLSBUF: /* Requires driver knowlege */
- case BLKRRPART: /* No args */
- default:
- if (entering(tcp))
- tprintf(", %#lx", arg);
break;
+ default:
+ return RVAL_DECODED;
+ }
- };
- return 1;
+ return RVAL_IOCTL_DECODED;
}
-#endif /* LINUX */