From: Jeff Mahoney Subject: strace: Add support for block ioctls References: bnc#539521 This patch adds support for blkdev_ioctl()-handled ioctls. Signed-off-by: Jeff Mahoney --- Makefile.am | 2 block.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ defs.h | 1 ioctl.c | 3 linux/ioctlent.sh | 3 5 files changed, 229 insertions(+), 1 deletion(-) Index: strace-4.5.20/Makefile.am =================================================================== --- strace-4.5.20.orig/Makefile.am +++ strace-4.5.20/Makefile.am @@ -15,7 +15,7 @@ INCLUDES = -I$(srcdir)/$(OS)/$(ARCH) -I$ strace_SOURCES = strace.c syscall.c count.c util.c desc.c file.c ipc.c \ io.c ioctl.c mem.c net.c process.c bjm.c quota.c \ resource.c signal.c sock.c system.c term.c time.c \ - proc.c scsi.c stream.c + proc.c scsi.c stream.c block.c noinst_HEADERS = defs.h EXTRA_DIST = $(man_MANS) errnoent.sh signalent.sh syscallent.sh ioctlsort.c \ Index: strace-4.5.20/block.c =================================================================== --- /dev/null +++ strace-4.5.20/block.c @@ -0,0 +1,221 @@ +#include "defs.h" +#ifdef LINUX +#include +#include +#include +#include +#include + +#ifndef BLKALIGNOFF +#define BLKALIGNOFF _IO(0x12,122) +#endif +#ifndef BLKPBSZGET +#define BLKPBSZGET _IO(0x12,123) +#endif +#ifndef BLKIOMIN +#define BLKIOMIN _IO(0x12,120) +#endif +#ifndef BLKIOOPT +#define BLKIOOPT _IO(0x12,121) +#endif + + +static void +print_blkpg_req(struct tcb *tcp, struct blkpg_ioctl_arg *blkpg) +{ + struct blkpg_partition p; + if (!(blkpg->op == BLKPG_ADD_PARTITION || + blkpg->op == BLKPG_DEL_PARTITION)) { + tprintf("{%d, ", blkpg->op); + return; + } + + tprintf("{%s, ", blkpg->op == BLKPG_ADD_PARTITION ? + "BLKPG_ADD_PARTITION" : "BLKPG_DEL_PARTITION"); + tprintf("flags=%d, datalen=%d, ", blkpg->flags, blkpg->datalen); + + if (umove(tcp, (unsigned long)blkpg->data, &p) < 0) { + tprintf("%#lx", (unsigned long)blkpg->data); + return; + } + + tprintf("{start=%lld, length=%lld, pno=%d, ", + p.start, p.length, p.pno); + + tprintf("devname=\"%s\", volname=\"%s\"}", + p.devname, p.volname); +} + +int +block_ioctl(struct tcb *tcp, long code, long arg) +{ + switch (code) { + + /* These pass arg as a value, not a pointer */ + case BLKRASET: + case BLKFRASET: + if (entering(tcp)) + tprintf(", %ld", 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 */ + case BLKSECTGET: + if (exiting(tcp)) { + unsigned short ushort_val; + if (umove(tcp, arg, &ushort_val) < 0) + tprintf(", %#lx", arg); + else + tprintf(", %hu", ushort_val); + } + break; + + /* Just 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); + } + break; + + /* Just return an unsigned int */ + case BLKPBSZGET: + case BLKIOMIN: + case BLKIOOPT: + if (exiting(tcp)) { + unsigned int uint_val; + if (umove(tcp, arg, &uint_val) < 0) + tprintf(", %#lx", arg); + else + tprintf(", %u", uint_val); + } + break; + + /* Just 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); + } + break; + + /* Just return 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); + } + break; + + /* Just return a quad */ + 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); + } + break; + + /* More complex types */ + case BLKDISCARD: + 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]); + } + 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("}"); + } + 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, buts.start_lba); + tprintf("end_lba=%llu, pid=%u}", + 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); + } + } + break; + /* No arguments or unhandled */ + case BLKFLSBUF: /* Requires driver knowlege */ + case BLKRRPART: /* No args */ + case BLKTRACESTART: + case BLKTRACESTOP: + case BLKTRACETEARDOWN: + default: + if (entering(tcp)) + tprintf(", %#lx", arg); + break; + + }; + return 1; +} +#endif /* LINUX */ Index: strace-4.5.20/defs.h =================================================================== --- strace-4.5.20.orig/defs.h +++ strace-4.5.20/defs.h @@ -550,6 +550,7 @@ extern int stream_ioctl(struct tcb *, in #ifdef LINUX extern int rtc_ioctl(struct tcb *, long, long); extern int scsi_ioctl(struct tcb *, long, long); +extern int block_ioctl(struct tcb *, long, long); #endif extern int tv_nz(struct timeval *); Index: strace-4.5.20/ioctl.c =================================================================== --- strace-4.5.20.orig/ioctl.c +++ strace-4.5.20/ioctl.c @@ -152,6 +152,9 @@ long code, arg; #ifdef LINUX case 'p': return rtc_ioctl(tcp, code, arg); + case 0x03: + case 0x12: + return block_ioctl(tcp, code, arg); case 0x22: return scsi_ioctl(tcp, code, arg); #endif Index: strace-4.5.20/linux/ioctlent.sh =================================================================== --- strace-4.5.20.orig/linux/ioctlent.sh +++ strace-4.5.20/linux/ioctlent.sh @@ -69,6 +69,9 @@ lookup_ioctls 56 linux/vt.h lookup_ioctls '7[12]' linux/videotext.h lookup_ioctls 89 $asm/sockios.h asm-generic/sockios.h linux/sockios.h lookup_ioctls 8B linux/wireless.h +lookup_ioctls 03 linux/hdreg.h +lookup_ioctls fd dm-ioctl.h +lookup_ioctls 52 linux/rfkill.h if [ -e $dir/Kbuild ]; then # kernel has exported user space headers, so query only them