* [PATCH] device mapper support for strace
@ 2015-07-31 14:49 Mikulas Patocka
[not found] ` <alpine.LRH.2.02.1507311043370.4689-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org>
0 siblings, 1 reply; 6+ messages in thread
From: Mikulas Patocka @ 2015-07-31 14:49 UTC (permalink / raw)
To: Alasdair G. Kergon, Dmitry V. Levin; +Cc: dm-devel, strace-devel
Hi
Here I'm sending a patch that makes it possible to decode device mapper
ioctls in strace.
How to apply the patch:
Download strace 4.10 from
http://downloads.sourceforge.net/project/strace/strace/4.10/strace-4.10.tar.xz
On the 4th line of configure.ac, change "m4_esyscmd([./git-version-gen
.tarball-version])," to "4.10," (the tarball references some file
git-version-gen that isn't present in the tarball, I think the maintainer
should fix it)
Apply this patch
Regenerate configure and Makefile.in:
aclocal -I m4
autoheader
autoconf
automake
Compile it:
./configure
make
Mikulas
Index: strace-4.10/configure.ac
===================================================================
--- strace-4.10.orig/configure.ac
+++ strace-4.10/configure.ac
@@ -247,6 +247,7 @@ AC_CHECK_HEADERS(m4_normalize([
inttypes.h
ioctls.h
linux/bsg.h
+ linux/dm-ioctl.h
linux/falloc.h
linux/filter.h
linux/hiddev.h
Index: strace-4.10/defs.h
===================================================================
--- strace-4.10.orig/defs.h
+++ strace-4.10/defs.h
@@ -518,6 +518,7 @@ extern void ioctl_print_code(const unsig
extern int ioctl_decode(struct tcb *, const unsigned int, long);
extern int ioctl_decode_command_number(const unsigned int);
extern int block_ioctl(struct tcb *, const unsigned int, long);
+extern int dm_ioctl(struct tcb *, const unsigned int, long);
extern int evdev_ioctl(struct tcb *, const unsigned int, long);
extern int loop_ioctl(struct tcb *, const unsigned int, long);
extern int mtd_ioctl(struct tcb *, const unsigned int, long);
Index: strace-4.10/dm.c
===================================================================
--- /dev/null
+++ strace-4.10/dm.c
@@ -0,0 +1,335 @@
+#include "defs.h"
+
+#ifdef HAVE_LINUX_DM_IOCTL_H
+
+#include <sys/ioctl.h>
+#include <linux/dm-ioctl.h>
+
+static void
+dm_decode_device(const unsigned int code, const struct dm_ioctl *ioc)
+{
+ if (code != DM_REMOVE_ALL &&
+ code != DM_LIST_DEVICES &&
+ code != DM_LIST_VERSIONS) {
+ if (ioc->dev)
+ tprintf(", dev=makedev(%u, %u)", major(ioc->dev), minor(ioc->dev));
+ if (ioc->name[0]) {
+ tprints(", name=");
+ print_quoted_string(ioc->name, DM_NAME_LEN, QUOTE_0_TERMINATED);
+ }
+ if (ioc->uuid[0]) {
+ tprints(", uuid=");
+ print_quoted_string(ioc->uuid, DM_UUID_LEN, QUOTE_0_TERMINATED);
+ }
+ }
+}
+
+static void
+dm_decode_values(struct tcb *tcp, const unsigned int code, const struct dm_ioctl *ioc)
+{
+ if (entering(tcp)) {
+ if (code == DM_TABLE_LOAD)
+ tprintf(", target_count=%u", (unsigned)ioc->target_count);
+ if (code == DM_DEV_RENAME ||
+ code == DM_DEV_REMOVE ||
+ (code == DM_DEV_SUSPEND && !(ioc->flags & DM_SUSPEND_FLAG)) ||
+ code == DM_DEV_WAIT)
+ tprintf(", event_nr=%u", (unsigned)ioc->event_nr);
+ } else if (!tcp->u_error) {
+ if (code == DM_DEV_CREATE ||
+ code == DM_DEV_RENAME ||
+ code == DM_DEV_SUSPEND ||
+ code == DM_DEV_STATUS ||
+ code == DM_DEV_WAIT ||
+ code == DM_TABLE_LOAD ||
+ code == DM_TABLE_CLEAR ||
+ code == DM_TABLE_DEPS ||
+ code == DM_TABLE_STATUS ||
+ code == DM_TARGET_MSG) {
+ tprintf(", target_count=%u", (unsigned)ioc->target_count);
+ tprintf(", open_count=%u", (unsigned)ioc->open_count);
+ tprintf(", event_nr=%u", (unsigned)ioc->event_nr);
+ }
+ }
+}
+
+static void
+dm_decode_flags(const struct dm_ioctl *ioc)
+{
+ if (ioc->flags) {
+ static const struct {
+ uint32_t flag;
+ const char *string;
+ } dm_flags[] = {
+ { DM_READONLY_FLAG, "DM_READONLY_FLAG" },
+ { DM_SUSPEND_FLAG, "DM_SUSPEND_FLAG" },
+ { DM_PERSISTENT_DEV_FLAG, "DM_PERSISTENT_DEV_FLAG" },
+ { DM_STATUS_TABLE_FLAG, "DM_STATUS_TABLE_FLAG" },
+ { DM_ACTIVE_PRESENT_FLAG, "DM_ACTIVE_PRESENT_FLAG" },
+ { DM_INACTIVE_PRESENT_FLAG, "DM_INACTIVE_PRESENT_FLAG" },
+ { DM_BUFFER_FULL_FLAG, "DM_BUFFER_FULL_FLAG" },
+ { DM_SKIP_BDGET_FLAG, "DM_SKIP_BDGET_FLAG" },
+#ifdef DM_SKIP_LOCKFS_FLAG
+ { DM_SKIP_LOCKFS_FLAG, "DM_SKIP_LOCKFS_FLAG" },
+#endif
+#ifdef DM_NOFLUSH_FLAG
+ { DM_NOFLUSH_FLAG, "DM_NOFLUSH_FLAG" },
+#endif
+#ifdef DM_QUERY_INACTIVE_TABLE_FLAG
+ { DM_QUERY_INACTIVE_TABLE_FLAG, "DM_QUERY_INACTIVE_TABLE_FLAG" },
+#endif
+#ifdef DM_UEVENT_GENERATED_FLAG
+ { DM_UEVENT_GENERATED_FLAG, "DM_UEVENT_GENERATED_FLAG" },
+#endif
+#ifdef DM_UUID_FLAG
+ { DM_UUID_FLAG, "DM_UUID_FLAG" },
+#endif
+#ifdef DM_SECURE_DATA_FLAG
+ { DM_SECURE_DATA_FLAG, "DM_SECURE_DATA_FLAG" },
+#endif
+#ifdef DM_DATA_OUT_FLAG
+ { DM_DATA_OUT_FLAG, "DM_DATA_OUT_FLAG" },
+#endif
+#ifdef DM_DEFERRED_REMOVE
+ { DM_DEFERRED_REMOVE, "DM_DEFERRED_REMOVE" },
+#endif
+#ifdef DM_INTERNAL_SUSPEND_FLAG
+ { DM_INTERNAL_SUSPEND_FLAG, "DM_INTERNAL_SUSPEND_FLAG" },
+#endif
+ };
+ uint32_t flags = ioc->flags;
+ bool first = true;
+ unsigned i;
+ tprints(", flags=");
+ for (i = 0; i < sizeof(dm_flags) / sizeof(*dm_flags); i++) {
+ if (flags & dm_flags[i].flag) {
+ if (!first)
+ tprints("|");
+ else
+ first = false;
+ tprints(dm_flags[i].string);
+ flags &= ~dm_flags[i].flag;
+ }
+ }
+ if (flags) {
+ if (!first)
+ tprints("|");
+ else
+ first = false;
+ tprintf("0x%x", (unsigned)flags);
+ }
+
+ }
+}
+
+static void
+dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc, const char *extra, size_t extra_size)
+{
+ uint32_t i;
+ size_t offset = ioc->data_start;
+ for (i = 0; i < ioc->target_count; i++) {
+ if (offset + sizeof(struct dm_target_spec) >= offset &&
+ offset + sizeof(struct dm_target_spec) < extra_size) {
+ const struct dm_target_spec *s = (const struct dm_target_spec *)(extra + offset);
+ tprintf(", {sector_start=%llu, length=%llu", (unsigned long long)s->sector_start, (unsigned long long)s->length);
+ if (!entering(tcp))
+ tprintf(", status=%d", (int)s->status);
+ tprints(", target_type=");
+ print_quoted_string(s->target_type, DM_MAX_TYPE_NAME, QUOTE_0_TERMINATED);
+ tprints(", string=");
+ print_quoted_string((const char *)(s + 1), extra_size - (offset + sizeof(struct dm_target_spec)), QUOTE_0_TERMINATED);
+ tprintf("}");
+ if (entering(tcp))
+ offset = offset + s->next;
+ else
+ offset = ioc->data_start + s->next;
+ } else {
+ tprints(", misplaced struct dm_target_spec");
+ break;
+ }
+ }
+}
+
+static void
+dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra, size_t extra_size)
+{
+ size_t offset = ioc->data_start;
+ if (offset + offsetof(struct dm_target_deps, dev) >= offset &&
+ offset + offsetof(struct dm_target_deps, dev) <= extra_size) {
+ uint32_t i;
+ size_t space = (extra_size - (offset + offsetof(struct dm_target_deps, dev))) / sizeof(__u64);
+ const struct dm_target_deps *s = (const struct dm_target_deps *)(extra + offset);
+ if (s->count > space)
+ goto misplaced;
+ tprints(", deps={");
+ for (i = 0; i < s->count; i++) {
+ tprintf("%smakedev(%u, %u)", i ? ", " : "", major(s->dev[i]), minor(s->dev[i]));
+ }
+ tprints("}");
+ } else {
+misplaced:
+ tprints(", misplaced struct dm_target_deps");
+ }
+}
+
+static void
+dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra, size_t extra_size)
+{
+ size_t offset = ioc->data_start;
+ while (1) {
+ if (offset + offsetof(struct dm_name_list, name) >= offset &&
+ offset + offsetof(struct dm_name_list, name) < extra_size) {
+ const struct dm_name_list *s = (const struct dm_name_list *)(extra + offset);
+ if (!s->dev)
+ break;
+ tprintf(", {dev=makedev(%u, %u), name=", major(s->dev), minor(s->dev));
+ print_quoted_string(s->name, extra_size - (offset + offsetof(struct dm_name_list, name)), QUOTE_0_TERMINATED);
+ tprints("}");
+ if (!s->next)
+ break;
+ if (offset + s->next < offset)
+ goto misplaced;
+ offset = offset + s->next;
+ } else {
+misplaced:
+ tprints(", misplaced struct dm_name_list");
+ break;
+ }
+ }
+}
+
+static void
+dm_decode_dm_target_versions(const struct dm_ioctl *ioc, const char *extra, size_t extra_size)
+{
+ size_t offset = ioc->data_start;
+ while (1) {
+ if (offset + offsetof(struct dm_target_versions, name) >= offset &&
+ offset + offsetof(struct dm_target_versions, name) < extra_size) {
+ const struct dm_target_versions *s = (const struct dm_target_versions *)(extra + offset);
+ tprints(", {name=");
+ print_quoted_string(s->name, extra_size - (offset + offsetof(struct dm_target_versions, name)), QUOTE_0_TERMINATED);
+ tprintf(", version=%u.%u.%u}", (unsigned)s->version[0], (unsigned)s->version[1], (unsigned)s->version[2]);
+ if (!s->next)
+ break;
+ if (offset + s->next < offset)
+ goto misplaced;
+ offset = offset + s->next;
+ } else {
+misplaced:
+ tprints(", misplaced struct dm_target_versions");
+ break;
+ }
+ }
+}
+
+static void
+dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra, size_t extra_size)
+{
+ size_t offset = ioc->data_start;
+ if (offset + offsetof(struct dm_target_msg, message) >= offset &&
+ offset + offsetof(struct dm_target_msg, message) < extra_size) {
+ const struct dm_target_msg *s = (const struct dm_target_msg *)(extra + offset);
+ tprintf(", {sector=%llu, message=", (unsigned long long)s->sector);
+ print_quoted_string(s->message, extra_size - offsetof(struct dm_target_msg, message), QUOTE_0_TERMINATED);
+ tprints("}");
+ } else {
+ tprints(", misplaced struct dm_target_msg");
+ }
+}
+
+static void
+dm_decode_string(const struct dm_ioctl *ioc, const char *extra, size_t extra_size)
+{
+ size_t offset = ioc->data_start;
+ if (offset < extra_size) {
+ tprints(", string=");
+ print_quoted_string(extra + offset, extra_size - offset, QUOTE_0_TERMINATED);
+ } else {
+ tprints(", misplaced string");
+ }
+}
+
+static int
+dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+{
+ struct dm_ioctl ioc;
+ char *extra = NULL;
+ size_t extra_size = 0;
+
+ if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), (char *)&ioc) < 0)
+ return 0;
+ tprintf(", {version=%d.%d.%d", ioc.version[0], ioc.version[1], ioc.version[2]);
+
+ /* if we use a different version of ABI, do not attempt to decode ioctl fields */
+ if (ioc.version[0] != DM_VERSION_MAJOR)
+ goto skip;
+
+ if (ioc.data_size > sizeof(ioc)) {
+ extra = malloc(ioc.data_size);
+ if (extra) {
+ extra_size = ioc.data_size;
+ if (umoven(tcp, arg, extra_size, extra) < 0) {
+ free(extra);
+ extra = NULL;
+ extra_size = 0;
+ }
+ }
+ }
+ dm_decode_device(code, &ioc);
+ dm_decode_values(tcp, code, &ioc);
+ dm_decode_flags(&ioc);
+ if (!abbrev(tcp)) {
+ if ((code == DM_DEV_WAIT && !entering(tcp) && !tcp->u_error) ||
+ (code == DM_TABLE_STATUS && !entering(tcp) && !tcp->u_error) ||
+ (code == DM_TABLE_LOAD && entering(tcp)))
+ dm_decode_dm_target_spec(tcp, &ioc, extra, extra_size);
+ if (code == DM_TABLE_DEPS && !entering(tcp) && !tcp->u_error)
+ dm_decode_dm_target_deps(&ioc, extra, extra_size);
+ if (code == DM_LIST_DEVICES && !entering(tcp) && !tcp->u_error)
+ dm_decode_dm_name_list(&ioc, extra, extra_size);
+ if (code == DM_LIST_VERSIONS && !entering(tcp) && !tcp->u_error)
+ dm_decode_dm_target_versions(&ioc, extra, extra_size);
+ if (code == DM_TARGET_MSG && entering(tcp))
+ dm_decode_dm_target_msg(&ioc, extra, extra_size);
+ if (code == DM_TARGET_MSG && !entering(tcp) && !tcp->u_error && ioc.flags & DM_DATA_OUT_FLAG)
+ dm_decode_string(&ioc, extra, extra_size);
+ if (code == DM_DEV_RENAME && entering(tcp))
+ dm_decode_string(&ioc, extra, extra_size);
+ if (code == DM_DEV_SET_GEOMETRY && entering(tcp))
+ dm_decode_string(&ioc, extra, extra_size);
+ }
+
+skip:
+ tprints("}");
+ if (extra)
+ free(extra);
+ return 1;
+}
+
+int
+dm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+{
+ switch (code) {
+ case DM_VERSION:
+ case DM_REMOVE_ALL:
+ case DM_LIST_DEVICES:
+ case DM_DEV_CREATE:
+ case DM_DEV_REMOVE:
+ case DM_DEV_RENAME:
+ case DM_DEV_SUSPEND:
+ case DM_DEV_STATUS:
+ case DM_DEV_WAIT:
+ case DM_TABLE_LOAD:
+ case DM_TABLE_CLEAR:
+ case DM_TABLE_DEPS:
+ case DM_TABLE_STATUS:
+ case DM_LIST_VERSIONS:
+ case DM_TARGET_MSG:
+ case DM_DEV_SET_GEOMETRY:
+ return dm_known_ioctl(tcp, code, arg);
+ default:
+ return 0;
+ }
+}
+
+#endif
Index: strace-4.10/ioctl.c
===================================================================
--- strace-4.10.orig/ioctl.c
+++ strace-4.10/ioctl.c
@@ -258,6 +258,10 @@ ioctl_decode(struct tcb *tcp, unsigned i
case 'E':
return evdev_ioctl(tcp, code, arg);
#endif
+#ifdef HAVE_LINUX_DM_IOCTL_H
+ case 0xfd:
+ return dm_ioctl(tcp, code, arg);
+#endif
default:
break;
}
Index: strace-4.10/Makefile.am
===================================================================
--- strace-4.10.orig/Makefile.am
+++ strace-4.10/Makefile.am
@@ -41,6 +41,7 @@ strace_SOURCES = \
count.c \
desc.c \
dirent.c \
+ dm.c \
evdev.c \
execve.c \
exit.c \
^ permalink raw reply [flat|nested] 6+ messages in thread[parent not found: <alpine.LRH.2.02.1507311043370.4689-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org>]
* Re: [PATCH] device mapper support for strace [not found] ` <alpine.LRH.2.02.1507311043370.4689-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org> @ 2015-07-31 15:35 ` Dmitry V. Levin [not found] ` <20150731153520.GA20404-u2l5PoMzF/Vg9hUCZPvPmw@public.gmane.org> 0 siblings, 1 reply; 6+ messages in thread From: Dmitry V. Levin @ 2015-07-31 15:35 UTC (permalink / raw) To: Mikulas Patocka Cc: dm-devel-H+wXaHxf7aLQT0dZR+AlfA, strace-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f [-- Attachment #1.1: Type: text/plain, Size: 462 bytes --] Hi, On Fri, Jul 31, 2015 at 10:49:44AM -0400, Mikulas Patocka wrote: > Hi > > Here I'm sending a patch that makes it possible to decode device mapper > ioctls in strace. > > > How to apply the patch: > > Download strace 4.10 from > http://downloads.sourceforge.net/project/strace/strace/4.10/strace-4.10.tar.xz Please rebase onto strace.git HEAD (v4.10-277-gd9fb450 at this moment). Use ./bootstrap to regenerate dev files. -- ldv [-- Attachment #1.2: Type: application/pgp-signature, Size: 181 bytes --] [-- Attachment #2: Type: text/plain, Size: 79 bytes --] ------------------------------------------------------------------------------ [-- Attachment #3: Type: text/plain, Size: 195 bytes --] _______________________________________________ Strace-devel mailing list Strace-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/strace-devel ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <20150731153520.GA20404-u2l5PoMzF/Vg9hUCZPvPmw@public.gmane.org>]
* Re: [PATCH] device mapper support for strace [not found] ` <20150731153520.GA20404-u2l5PoMzF/Vg9hUCZPvPmw@public.gmane.org> @ 2015-07-31 16:04 ` Mikulas Patocka [not found] ` <alpine.LRH.2.02.1507311202320.29679-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org> 0 siblings, 1 reply; 6+ messages in thread From: Mikulas Patocka @ 2015-07-31 16:04 UTC (permalink / raw) To: Dmitry V. Levin Cc: dm-devel-H+wXaHxf7aLQT0dZR+AlfA, strace-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f On Fri, 31 Jul 2015, Dmitry V. Levin wrote: > Hi, > > On Fri, Jul 31, 2015 at 10:49:44AM -0400, Mikulas Patocka wrote: > > Hi > > > > Here I'm sending a patch that makes it possible to decode device mapper > > ioctls in strace. > > > > > > How to apply the patch: > > > > Download strace 4.10 from > > http://downloads.sourceforge.net/project/strace/strace/4.10/strace-4.10.tar.xz > > Please rebase onto strace.git HEAD (v4.10-277-gd9fb450 at this moment). > Use ./bootstrap to regenerate dev files. This is the updated patch for strace.git. Mikulas Index: strace/configure.ac =================================================================== --- strace.orig/configure.ac +++ strace/configure.ac @@ -222,6 +222,7 @@ AC_CHECK_HEADERS(m4_normalize([ elf.h inttypes.h ioctls.h + linux/dm-ioctl.h linux/falloc.h linux/hiddev.h linux/input.h Index: strace/dm.c =================================================================== --- /dev/null +++ strace/dm.c @@ -0,0 +1,335 @@ +#include "defs.h" + +#ifdef HAVE_LINUX_DM_IOCTL_H + +#include <sys/ioctl.h> +#include <linux/dm-ioctl.h> + +static void +dm_decode_device(const unsigned int code, const struct dm_ioctl *ioc) +{ + if (code != DM_REMOVE_ALL && + code != DM_LIST_DEVICES && + code != DM_LIST_VERSIONS) { + if (ioc->dev) + tprintf(", dev=makedev(%u, %u)", major(ioc->dev), minor(ioc->dev)); + if (ioc->name[0]) { + tprints(", name="); + print_quoted_string(ioc->name, DM_NAME_LEN, QUOTE_0_TERMINATED); + } + if (ioc->uuid[0]) { + tprints(", uuid="); + print_quoted_string(ioc->uuid, DM_UUID_LEN, QUOTE_0_TERMINATED); + } + } +} + +static void +dm_decode_values(struct tcb *tcp, const unsigned int code, const struct dm_ioctl *ioc) +{ + if (entering(tcp)) { + if (code == DM_TABLE_LOAD) + tprintf(", target_count=%u", (unsigned)ioc->target_count); + if (code == DM_DEV_RENAME || + code == DM_DEV_REMOVE || + (code == DM_DEV_SUSPEND && !(ioc->flags & DM_SUSPEND_FLAG)) || + code == DM_DEV_WAIT) + tprintf(", event_nr=%u", (unsigned)ioc->event_nr); + } else if (!tcp->u_error) { + if (code == DM_DEV_CREATE || + code == DM_DEV_RENAME || + code == DM_DEV_SUSPEND || + code == DM_DEV_STATUS || + code == DM_DEV_WAIT || + code == DM_TABLE_LOAD || + code == DM_TABLE_CLEAR || + code == DM_TABLE_DEPS || + code == DM_TABLE_STATUS || + code == DM_TARGET_MSG) { + tprintf(", target_count=%u", (unsigned)ioc->target_count); + tprintf(", open_count=%u", (unsigned)ioc->open_count); + tprintf(", event_nr=%u", (unsigned)ioc->event_nr); + } + } +} + +static void +dm_decode_flags(const struct dm_ioctl *ioc) +{ + if (ioc->flags) { + static const struct { + uint32_t flag; + const char *string; + } dm_flags[] = { + { DM_READONLY_FLAG, "DM_READONLY_FLAG" }, + { DM_SUSPEND_FLAG, "DM_SUSPEND_FLAG" }, + { DM_PERSISTENT_DEV_FLAG, "DM_PERSISTENT_DEV_FLAG" }, + { DM_STATUS_TABLE_FLAG, "DM_STATUS_TABLE_FLAG" }, + { DM_ACTIVE_PRESENT_FLAG, "DM_ACTIVE_PRESENT_FLAG" }, + { DM_INACTIVE_PRESENT_FLAG, "DM_INACTIVE_PRESENT_FLAG" }, + { DM_BUFFER_FULL_FLAG, "DM_BUFFER_FULL_FLAG" }, + { DM_SKIP_BDGET_FLAG, "DM_SKIP_BDGET_FLAG" }, +#ifdef DM_SKIP_LOCKFS_FLAG + { DM_SKIP_LOCKFS_FLAG, "DM_SKIP_LOCKFS_FLAG" }, +#endif +#ifdef DM_NOFLUSH_FLAG + { DM_NOFLUSH_FLAG, "DM_NOFLUSH_FLAG" }, +#endif +#ifdef DM_QUERY_INACTIVE_TABLE_FLAG + { DM_QUERY_INACTIVE_TABLE_FLAG, "DM_QUERY_INACTIVE_TABLE_FLAG" }, +#endif +#ifdef DM_UEVENT_GENERATED_FLAG + { DM_UEVENT_GENERATED_FLAG, "DM_UEVENT_GENERATED_FLAG" }, +#endif +#ifdef DM_UUID_FLAG + { DM_UUID_FLAG, "DM_UUID_FLAG" }, +#endif +#ifdef DM_SECURE_DATA_FLAG + { DM_SECURE_DATA_FLAG, "DM_SECURE_DATA_FLAG" }, +#endif +#ifdef DM_DATA_OUT_FLAG + { DM_DATA_OUT_FLAG, "DM_DATA_OUT_FLAG" }, +#endif +#ifdef DM_DEFERRED_REMOVE + { DM_DEFERRED_REMOVE, "DM_DEFERRED_REMOVE" }, +#endif +#ifdef DM_INTERNAL_SUSPEND_FLAG + { DM_INTERNAL_SUSPEND_FLAG, "DM_INTERNAL_SUSPEND_FLAG" }, +#endif + }; + uint32_t flags = ioc->flags; + bool first = true; + unsigned i; + tprints(", flags="); + for (i = 0; i < sizeof(dm_flags) / sizeof(*dm_flags); i++) { + if (flags & dm_flags[i].flag) { + if (!first) + tprints("|"); + else + first = false; + tprints(dm_flags[i].string); + flags &= ~dm_flags[i].flag; + } + } + if (flags) { + if (!first) + tprints("|"); + else + first = false; + tprintf("0x%x", (unsigned)flags); + } + + } +} + +static void +dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc, const char *extra, size_t extra_size) +{ + uint32_t i; + size_t offset = ioc->data_start; + for (i = 0; i < ioc->target_count; i++) { + if (offset + sizeof(struct dm_target_spec) >= offset && + offset + sizeof(struct dm_target_spec) < extra_size) { + const struct dm_target_spec *s = (const struct dm_target_spec *)(extra + offset); + tprintf(", {sector_start=%llu, length=%llu", (unsigned long long)s->sector_start, (unsigned long long)s->length); + if (!entering(tcp)) + tprintf(", status=%d", (int)s->status); + tprints(", target_type="); + print_quoted_string(s->target_type, DM_MAX_TYPE_NAME, QUOTE_0_TERMINATED); + tprints(", string="); + print_quoted_string((const char *)(s + 1), extra_size - (offset + sizeof(struct dm_target_spec)), QUOTE_0_TERMINATED); + tprintf("}"); + if (entering(tcp)) + offset = offset + s->next; + else + offset = ioc->data_start + s->next; + } else { + tprints(", misplaced struct dm_target_spec"); + break; + } + } +} + +static void +dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra, size_t extra_size) +{ + size_t offset = ioc->data_start; + if (offset + offsetof(struct dm_target_deps, dev) >= offset && + offset + offsetof(struct dm_target_deps, dev) <= extra_size) { + uint32_t i; + size_t space = (extra_size - (offset + offsetof(struct dm_target_deps, dev))) / sizeof(__u64); + const struct dm_target_deps *s = (const struct dm_target_deps *)(extra + offset); + if (s->count > space) + goto misplaced; + tprints(", deps={"); + for (i = 0; i < s->count; i++) { + tprintf("%smakedev(%u, %u)", i ? ", " : "", major(s->dev[i]), minor(s->dev[i])); + } + tprints("}"); + } else { +misplaced: + tprints(", misplaced struct dm_target_deps"); + } +} + +static void +dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra, size_t extra_size) +{ + size_t offset = ioc->data_start; + while (1) { + if (offset + offsetof(struct dm_name_list, name) >= offset && + offset + offsetof(struct dm_name_list, name) < extra_size) { + const struct dm_name_list *s = (const struct dm_name_list *)(extra + offset); + if (!s->dev) + break; + tprintf(", {dev=makedev(%u, %u), name=", major(s->dev), minor(s->dev)); + print_quoted_string(s->name, extra_size - (offset + offsetof(struct dm_name_list, name)), QUOTE_0_TERMINATED); + tprints("}"); + if (!s->next) + break; + if (offset + s->next < offset) + goto misplaced; + offset = offset + s->next; + } else { +misplaced: + tprints(", misplaced struct dm_name_list"); + break; + } + } +} + +static void +dm_decode_dm_target_versions(const struct dm_ioctl *ioc, const char *extra, size_t extra_size) +{ + size_t offset = ioc->data_start; + while (1) { + if (offset + offsetof(struct dm_target_versions, name) >= offset && + offset + offsetof(struct dm_target_versions, name) < extra_size) { + const struct dm_target_versions *s = (const struct dm_target_versions *)(extra + offset); + tprints(", {name="); + print_quoted_string(s->name, extra_size - (offset + offsetof(struct dm_target_versions, name)), QUOTE_0_TERMINATED); + tprintf(", version=%u.%u.%u}", (unsigned)s->version[0], (unsigned)s->version[1], (unsigned)s->version[2]); + if (!s->next) + break; + if (offset + s->next < offset) + goto misplaced; + offset = offset + s->next; + } else { +misplaced: + tprints(", misplaced struct dm_target_versions"); + break; + } + } +} + +static void +dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra, size_t extra_size) +{ + size_t offset = ioc->data_start; + if (offset + offsetof(struct dm_target_msg, message) >= offset && + offset + offsetof(struct dm_target_msg, message) < extra_size) { + const struct dm_target_msg *s = (const struct dm_target_msg *)(extra + offset); + tprintf(", {sector=%llu, message=", (unsigned long long)s->sector); + print_quoted_string(s->message, extra_size - offsetof(struct dm_target_msg, message), QUOTE_0_TERMINATED); + tprints("}"); + } else { + tprints(", misplaced struct dm_target_msg"); + } +} + +static void +dm_decode_string(const struct dm_ioctl *ioc, const char *extra, size_t extra_size) +{ + size_t offset = ioc->data_start; + if (offset < extra_size) { + tprints(", string="); + print_quoted_string(extra + offset, extra_size - offset, QUOTE_0_TERMINATED); + } else { + tprints(", misplaced string"); + } +} + +static int +dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg) +{ + struct dm_ioctl ioc; + char *extra = NULL; + size_t extra_size = 0; + + if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), (char *)&ioc) < 0) + return 0; + tprintf(", {version=%d.%d.%d", ioc.version[0], ioc.version[1], ioc.version[2]); + + /* if we use a different version of ABI, do not attempt to decode ioctl fields */ + if (ioc.version[0] != DM_VERSION_MAJOR) + goto skip; + + if (ioc.data_size > sizeof(ioc)) { + extra = malloc(ioc.data_size); + if (extra) { + extra_size = ioc.data_size; + if (umoven(tcp, arg, extra_size, extra) < 0) { + free(extra); + extra = NULL; + extra_size = 0; + } + } + } + dm_decode_device(code, &ioc); + dm_decode_values(tcp, code, &ioc); + dm_decode_flags(&ioc); + if (!abbrev(tcp)) { + if ((code == DM_DEV_WAIT && !entering(tcp) && !tcp->u_error) || + (code == DM_TABLE_STATUS && !entering(tcp) && !tcp->u_error) || + (code == DM_TABLE_LOAD && entering(tcp))) + dm_decode_dm_target_spec(tcp, &ioc, extra, extra_size); + if (code == DM_TABLE_DEPS && !entering(tcp) && !tcp->u_error) + dm_decode_dm_target_deps(&ioc, extra, extra_size); + if (code == DM_LIST_DEVICES && !entering(tcp) && !tcp->u_error) + dm_decode_dm_name_list(&ioc, extra, extra_size); + if (code == DM_LIST_VERSIONS && !entering(tcp) && !tcp->u_error) + dm_decode_dm_target_versions(&ioc, extra, extra_size); + if (code == DM_TARGET_MSG && entering(tcp)) + dm_decode_dm_target_msg(&ioc, extra, extra_size); + if (code == DM_TARGET_MSG && !entering(tcp) && !tcp->u_error && ioc.flags & DM_DATA_OUT_FLAG) + dm_decode_string(&ioc, extra, extra_size); + if (code == DM_DEV_RENAME && entering(tcp)) + dm_decode_string(&ioc, extra, extra_size); + if (code == DM_DEV_SET_GEOMETRY && entering(tcp)) + dm_decode_string(&ioc, extra, extra_size); + } + +skip: + tprints("}"); + if (extra) + free(extra); + return 1; +} + +int +dm_ioctl(struct tcb *tcp, const unsigned int code, long arg) +{ + switch (code) { + case DM_VERSION: + case DM_REMOVE_ALL: + case DM_LIST_DEVICES: + case DM_DEV_CREATE: + case DM_DEV_REMOVE: + case DM_DEV_RENAME: + case DM_DEV_SUSPEND: + case DM_DEV_STATUS: + case DM_DEV_WAIT: + case DM_TABLE_LOAD: + case DM_TABLE_CLEAR: + case DM_TABLE_DEPS: + case DM_TABLE_STATUS: + case DM_LIST_VERSIONS: + case DM_TARGET_MSG: + case DM_DEV_SET_GEOMETRY: + return dm_known_ioctl(tcp, code, arg); + default: + return 0; + } +} + +#endif Index: strace/ioctl.c =================================================================== --- strace.orig/ioctl.c +++ strace/ioctl.c @@ -254,6 +254,10 @@ ioctl_decode(struct tcb *tcp, unsigned i return v4l2_ioctl(tcp, code, arg); case '=': return ptp_ioctl(tcp, code, arg); +#ifdef HAVE_LINUX_DM_IOCTL_H + case 0xfd: + return dm_ioctl(tcp, code, arg); +#endif default: break; } Index: strace/Makefile.am =================================================================== --- strace.orig/Makefile.am +++ strace/Makefile.am @@ -39,6 +39,7 @@ strace_SOURCES = \ count.c \ desc.c \ dirent.c \ + dm.c \ execve.c \ exit.c \ fadvise.c \ Index: strace/defs.h =================================================================== --- strace.orig/defs.h +++ strace/defs.h @@ -741,6 +741,7 @@ extern void ioctl_print_code(const unsig extern int ioctl_decode(struct tcb *, const unsigned int, long); extern int ioctl_decode_command_number(const unsigned int); extern int block_ioctl(struct tcb *, const unsigned int, long); +extern int dm_ioctl(struct tcb *, const unsigned int, long); extern int loop_ioctl(struct tcb *, const unsigned int, long); extern int mtd_ioctl(struct tcb *, const unsigned int, long); extern int ptp_ioctl(struct tcb *, const unsigned int, long); ------------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <alpine.LRH.2.02.1507311202320.29679-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org>]
* Re: [PATCH] device mapper support for strace [not found] ` <alpine.LRH.2.02.1507311202320.29679-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org> @ 2015-08-01 17:54 ` Dmitry V. Levin [not found] ` <20150801175400.GA3943-u2l5PoMzF/Vg9hUCZPvPmw@public.gmane.org> 0 siblings, 1 reply; 6+ messages in thread From: Dmitry V. Levin @ 2015-08-01 17:54 UTC (permalink / raw) To: Mikulas Patocka Cc: dm-devel-H+wXaHxf7aLQT0dZR+AlfA, strace-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f [-- Attachment #1.1: Type: text/plain, Size: 6357 bytes --] On Fri, Jul 31, 2015 at 12:04:48PM -0400, Mikulas Patocka wrote: > On Fri, 31 Jul 2015, Dmitry V. Levin wrote: > > On Fri, Jul 31, 2015 at 10:49:44AM -0400, Mikulas Patocka wrote: > > > Hi > > > > > > Here I'm sending a patch that makes it possible to decode device mapper > > > ioctls in strace. > > > > > > How to apply the patch: > > > > > > Download strace 4.10 from > > > http://downloads.sourceforge.net/project/strace/strace/4.10/strace-4.10.tar.xz > > > > Please rebase onto strace.git HEAD (v4.10-277-gd9fb450 at this moment). > > Use ./bootstrap to regenerate dev files. > > This is the updated patch for strace.git. Thanks. Unfortunately, this one doesn't apply at all, you must be using a quite outdated strace.git repository. The up to date strace.git is located at git://git.code.sf.net/p/strace/code.git, and when it is not available because of sf.net issues (which are quite often nowadays), one can use mirrors at https://github.com/ldv-alt/strace.git and git://git.altlinux.org/people/ldv/public/strace.git Just a few comments after very cursory look at your patch: > --- /dev/null > +++ strace/dm.c > @@ -0,0 +1,335 @@ > +#include "defs.h" > + > +#ifdef HAVE_LINUX_DM_IOCTL_H > + > +#include <sys/ioctl.h> Please include <linux/ioctl.h> instead. > +#include <linux/dm-ioctl.h> > + > +static void > +dm_decode_device(const unsigned int code, const struct dm_ioctl *ioc) > +{ > + if (code != DM_REMOVE_ALL && > + code != DM_LIST_DEVICES && > + code != DM_LIST_VERSIONS) { Please use switch statement instead. > + if (ioc->dev) > + tprintf(", dev=makedev(%u, %u)", major(ioc->dev), minor(ioc->dev)); > + if (ioc->name[0]) { > + tprints(", name="); > + print_quoted_string(ioc->name, DM_NAME_LEN, QUOTE_0_TERMINATED); > + } > + if (ioc->uuid[0]) { > + tprints(", uuid="); > + print_quoted_string(ioc->uuid, DM_UUID_LEN, QUOTE_0_TERMINATED); > + } > + } > +} > + > +static void > +dm_decode_values(struct tcb *tcp, const unsigned int code, const struct dm_ioctl *ioc) > +{ > + if (entering(tcp)) { > + if (code == DM_TABLE_LOAD) > + tprintf(", target_count=%u", (unsigned)ioc->target_count); > + if (code == DM_DEV_RENAME || > + code == DM_DEV_REMOVE || > + (code == DM_DEV_SUSPEND && !(ioc->flags & DM_SUSPEND_FLAG)) || > + code == DM_DEV_WAIT) Please use switch statement instead. > + tprintf(", event_nr=%u", (unsigned)ioc->event_nr); > + } else if (!tcp->u_error) { Please use !syserror(tcp) instead. > + if (code == DM_DEV_CREATE || > + code == DM_DEV_RENAME || > + code == DM_DEV_SUSPEND || > + code == DM_DEV_STATUS || > + code == DM_DEV_WAIT || > + code == DM_TABLE_LOAD || > + code == DM_TABLE_CLEAR || > + code == DM_TABLE_DEPS || > + code == DM_TABLE_STATUS || > + code == DM_TARGET_MSG) { Please use switch statement instead. > + tprintf(", target_count=%u", (unsigned)ioc->target_count); > + tprintf(", open_count=%u", (unsigned)ioc->open_count); > + tprintf(", event_nr=%u", (unsigned)ioc->event_nr); > + } > + } > +} > + > +static void > +dm_decode_flags(const struct dm_ioctl *ioc) > +{ > + if (ioc->flags) { > + static const struct { > + uint32_t flag; > + const char *string; > + } dm_flags[] = { > + { DM_READONLY_FLAG, "DM_READONLY_FLAG" }, > + { DM_SUSPEND_FLAG, "DM_SUSPEND_FLAG" }, > + { DM_PERSISTENT_DEV_FLAG, "DM_PERSISTENT_DEV_FLAG" }, > + { DM_STATUS_TABLE_FLAG, "DM_STATUS_TABLE_FLAG" }, > + { DM_ACTIVE_PRESENT_FLAG, "DM_ACTIVE_PRESENT_FLAG" }, > + { DM_INACTIVE_PRESENT_FLAG, "DM_INACTIVE_PRESENT_FLAG" }, > + { DM_BUFFER_FULL_FLAG, "DM_BUFFER_FULL_FLAG" }, > + { DM_SKIP_BDGET_FLAG, "DM_SKIP_BDGET_FLAG" }, > +#ifdef DM_SKIP_LOCKFS_FLAG > + { DM_SKIP_LOCKFS_FLAG, "DM_SKIP_LOCKFS_FLAG" }, > +#endif > +#ifdef DM_NOFLUSH_FLAG > + { DM_NOFLUSH_FLAG, "DM_NOFLUSH_FLAG" }, > +#endif > +#ifdef DM_QUERY_INACTIVE_TABLE_FLAG > + { DM_QUERY_INACTIVE_TABLE_FLAG, "DM_QUERY_INACTIVE_TABLE_FLAG" }, > +#endif > +#ifdef DM_UEVENT_GENERATED_FLAG > + { DM_UEVENT_GENERATED_FLAG, "DM_UEVENT_GENERATED_FLAG" }, > +#endif > +#ifdef DM_UUID_FLAG > + { DM_UUID_FLAG, "DM_UUID_FLAG" }, > +#endif > +#ifdef DM_SECURE_DATA_FLAG > + { DM_SECURE_DATA_FLAG, "DM_SECURE_DATA_FLAG" }, > +#endif > +#ifdef DM_DATA_OUT_FLAG > + { DM_DATA_OUT_FLAG, "DM_DATA_OUT_FLAG" }, > +#endif > +#ifdef DM_DEFERRED_REMOVE > + { DM_DEFERRED_REMOVE, "DM_DEFERRED_REMOVE" }, > +#endif > +#ifdef DM_INTERNAL_SUSPEND_FLAG > + { DM_INTERNAL_SUSPEND_FLAG, "DM_INTERNAL_SUSPEND_FLAG" }, > +#endif > + }; Please create an xlat file instead. See e.g. xlat/evdev_*.in files. > + uint32_t flags = ioc->flags; > + bool first = true; > + unsigned i; > + tprints(", flags="); > + for (i = 0; i < sizeof(dm_flags) / sizeof(*dm_flags); i++) { > + if (flags & dm_flags[i].flag) { > + if (!first) > + tprints("|"); > + else > + first = false; > + tprints(dm_flags[i].string); > + flags &= ~dm_flags[i].flag; > + } > + } > + if (flags) { > + if (!first) > + tprints("|"); > + else > + first = false; > + tprintf("0x%x", (unsigned)flags); > + } Please use printflags instead. > + > + } > +} > + > +static void > +dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc, const char *extra, size_t extra_size) > +{ > + uint32_t i; > + size_t offset = ioc->data_start; > + for (i = 0; i < ioc->target_count; i++) { > + if (offset + sizeof(struct dm_target_spec) >= offset && > + offset + sizeof(struct dm_target_spec) < extra_size) { > + const struct dm_target_spec *s = (const struct dm_target_spec *)(extra + offset); > + tprintf(", {sector_start=%llu, length=%llu", (unsigned long long)s->sector_start, (unsigned long long)s->length); > + if (!entering(tcp)) > + tprintf(", status=%d", (int)s->status); > + tprints(", target_type="); > + print_quoted_string(s->target_type, DM_MAX_TYPE_NAME, QUOTE_0_TERMINATED); > + tprints(", string="); > + print_quoted_string((const char *)(s + 1), extra_size - (offset + sizeof(struct dm_target_spec)), QUOTE_0_TERMINATED); Please wrap long lines so they won't exceed 80 symbols. -- ldv [-- Attachment #1.2: Type: application/pgp-signature, Size: 181 bytes --] [-- Attachment #2: Type: text/plain, Size: 79 bytes --] ------------------------------------------------------------------------------ [-- Attachment #3: Type: text/plain, Size: 195 bytes --] _______________________________________________ Strace-devel mailing list Strace-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/strace-devel ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <20150801175400.GA3943-u2l5PoMzF/Vg9hUCZPvPmw@public.gmane.org>]
* Re: [PATCH] device mapper support for strace [not found] ` <20150801175400.GA3943-u2l5PoMzF/Vg9hUCZPvPmw@public.gmane.org> @ 2015-08-11 17:11 ` Mikulas Patocka [not found] ` <alpine.LRH.2.02.1508111310290.20408-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org> 0 siblings, 1 reply; 6+ messages in thread From: Mikulas Patocka @ 2015-08-11 17:11 UTC (permalink / raw) To: Dmitry V. Levin Cc: dm-devel-H+wXaHxf7aLQT0dZR+AlfA, strace-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f On Sat, 1 Aug 2015, Dmitry V. Levin wrote: > On Fri, Jul 31, 2015 at 12:04:48PM -0400, Mikulas Patocka wrote: > > On Fri, 31 Jul 2015, Dmitry V. Levin wrote: > > > On Fri, Jul 31, 2015 at 10:49:44AM -0400, Mikulas Patocka wrote: > > > > Hi > > > > > > > > Here I'm sending a patch that makes it possible to decode device mapper > > > > ioctls in strace. > > > > > > > > How to apply the patch: > > > > > > > > Download strace 4.10 from > > > > http://downloads.sourceforge.net/project/strace/strace/4.10/strace-4.10.tar.xz > > > > > > Please rebase onto strace.git HEAD (v4.10-277-gd9fb450 at this moment). > > > Use ./bootstrap to regenerate dev files. > > > > This is the updated patch for strace.git. > > Thanks. > > Unfortunately, this one doesn't apply at all, you must be using a quite > outdated strace.git repository. > > The up to date strace.git is located at git://git.code.sf.net/p/strace/code.git, > and when it is not available because of sf.net issues (which are quite > often nowadays), one can use mirrors at https://github.com/ldv-alt/strace.git > and git://git.altlinux.org/people/ldv/public/strace.git > > Just a few comments after very cursory look at your patch: Hi Here I'm sending updated patch with your suggestions: Index: strace/configure.ac =================================================================== --- strace.orig/configure.ac +++ strace/configure.ac @@ -259,6 +259,7 @@ AC_CHECK_HEADERS(m4_normalize([ ioctls.h linux/bsg.h linux/falloc.h + linux/dm-ioctl.h linux/filter.h linux/hiddev.h linux/mmtimer.h Index: strace/dm.c =================================================================== --- /dev/null +++ strace/dm.c @@ -0,0 +1,354 @@ +#include "defs.h" + +#ifdef HAVE_LINUX_DM_IOCTL_H + +#include <sys/ioctl.h> +#include <linux/dm-ioctl.h> + +static void +dm_decode_device(const unsigned int code, const struct dm_ioctl *ioc) +{ + switch (code) { + case DM_REMOVE_ALL: + case DM_LIST_DEVICES: + case DM_LIST_VERSIONS: + break; + default: + if (ioc->dev) + tprintf(", dev=makedev(%u, %u)", + major(ioc->dev), minor(ioc->dev)); + if (ioc->name[0]) { + tprints(", name="); + print_quoted_string(ioc->name, DM_NAME_LEN, + QUOTE_0_TERMINATED); + } + if (ioc->uuid[0]) { + tprints(", uuid="); + print_quoted_string(ioc->uuid, DM_UUID_LEN, + QUOTE_0_TERMINATED); + } + break; + } +} + +static void +dm_decode_values(struct tcb *tcp, const unsigned int code, + const struct dm_ioctl *ioc) +{ + if (entering(tcp)) { + switch (code) { + case DM_TABLE_LOAD: + tprintf(", target_count=%u", + (unsigned)ioc->target_count); + break; + case DM_DEV_SUSPEND: + if (ioc->flags & DM_SUSPEND_FLAG) + break; + case DM_DEV_RENAME: + case DM_DEV_REMOVE: + case DM_DEV_WAIT: + tprintf(", event_nr=%u", + (unsigned)ioc->event_nr); + break; + } + } else if (!syserror(tcp)) { + switch (code) { + case DM_DEV_CREATE: + case DM_DEV_RENAME: + case DM_DEV_SUSPEND: + case DM_DEV_STATUS: + case DM_DEV_WAIT: + case DM_TABLE_LOAD: + case DM_TABLE_CLEAR: + case DM_TABLE_DEPS: + case DM_TABLE_STATUS: + case DM_TARGET_MSG: + tprintf(", target_count=%u", + (unsigned)ioc->target_count); + tprintf(", open_count=%u", + (unsigned)ioc->open_count); + tprintf(", event_nr=%u", + (unsigned)ioc->event_nr); + break; + } + } +} + +#include "xlat/dm_flags.h" + +static void +dm_decode_flags(const struct dm_ioctl *ioc) +{ + tprints(", flags="); + printflags(dm_flags, ioc->flags, "DM_???"); +} + +static void +dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc, + const char *extra, size_t extra_size) +{ + uint32_t i; + size_t offset = ioc->data_start; + for (i = 0; i < ioc->target_count; i++) { + if (offset + sizeof(struct dm_target_spec) >= offset && + offset + sizeof(struct dm_target_spec) < extra_size) { + const struct dm_target_spec *s = + (const struct dm_target_spec *)(extra + offset); + tprintf(", {sector_start=%llu, length=%llu", + (unsigned long long)s->sector_start, + (unsigned long long)s->length); + if (!entering(tcp)) + tprintf(", status=%d", (int)s->status); + tprints(", target_type="); + print_quoted_string(s->target_type, DM_MAX_TYPE_NAME, + QUOTE_0_TERMINATED); + tprints(", string="); + print_quoted_string((const char *)(s + 1), extra_size - + (offset + + sizeof(struct dm_target_spec)), + QUOTE_0_TERMINATED); + tprintf("}"); + if (entering(tcp)) + offset = offset + s->next; + else + offset = ioc->data_start + s->next; + } else { + tprints(", misplaced struct dm_target_spec"); + break; + } + } +} + +static void +dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra, + size_t extra_size) +{ + size_t offset = ioc->data_start; + if (offset + offsetof(struct dm_target_deps, dev) >= offset && + offset + offsetof(struct dm_target_deps, dev) <= extra_size) { + uint32_t i; + size_t space = (extra_size - (offset + + offsetof(struct dm_target_deps, dev))) / sizeof(__u64); + const struct dm_target_deps *s = + (const struct dm_target_deps *)(extra + offset); + if (s->count > space) + goto misplaced; + tprints(", deps={"); + for (i = 0; i < s->count; i++) { + tprintf("%smakedev(%u, %u)", i ? ", " : "", + major(s->dev[i]), minor(s->dev[i])); + } + tprints("}"); + } else { +misplaced: + tprints(", misplaced struct dm_target_deps"); + } +} + +static void +dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra, + size_t extra_size) +{ + size_t offset = ioc->data_start; + while (1) { + if (offset + offsetof(struct dm_name_list, name) >= offset && + offset + offsetof(struct dm_name_list, name) < extra_size) { + const struct dm_name_list *s = + (const struct dm_name_list *)(extra + offset); + if (!s->dev) + break; + tprintf(", {dev=makedev(%u, %u), name=", major(s->dev), minor(s->dev)); + print_quoted_string(s->name, extra_size - (offset + + offsetof(struct dm_name_list, + name)), QUOTE_0_TERMINATED); + tprints("}"); + if (!s->next) + break; + if (offset + s->next < offset) + goto misplaced; + offset = offset + s->next; + } else { +misplaced: + tprints(", misplaced struct dm_name_list"); + break; + } + } +} + +static void +dm_decode_dm_target_versions(const struct dm_ioctl *ioc, const char *extra, + size_t extra_size) +{ + size_t offset = ioc->data_start; + while (1) { + if (offset + offsetof(struct dm_target_versions, name) >= + offset && + offset + offsetof(struct dm_target_versions, name) < + extra_size) { + const struct dm_target_versions *s = + (const struct dm_target_versions *)(extra + offset); + tprints(", {name="); + print_quoted_string(s->name, extra_size - (offset + + offsetof(struct dm_target_versions, + name)), QUOTE_0_TERMINATED); + tprintf(", version=%u.%u.%u}", (unsigned)s->version[0], + (unsigned)s->version[1], + (unsigned)s->version[2]); + if (!s->next) + break; + if (offset + s->next < offset) + goto misplaced; + offset = offset + s->next; + } else { +misplaced: + tprints(", misplaced struct dm_target_versions"); + break; + } + } +} + +static void +dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra, + size_t extra_size) +{ + size_t offset = ioc->data_start; + if (offset + offsetof(struct dm_target_msg, message) >= offset && + offset + offsetof(struct dm_target_msg, message) < extra_size) { + const struct dm_target_msg *s = + (const struct dm_target_msg *)(extra + offset); + tprintf(", {sector=%llu, message=", + (unsigned long long)s->sector); + print_quoted_string(s->message, extra_size - + offsetof(struct dm_target_msg, message), + QUOTE_0_TERMINATED); + tprints("}"); + } else { + tprints(", misplaced struct dm_target_msg"); + } +} + +static void +dm_decode_string(const struct dm_ioctl *ioc, const char *extra, + size_t extra_size) +{ + size_t offset = ioc->data_start; + if (offset < extra_size) { + tprints(", string="); + print_quoted_string(extra + offset, extra_size - offset, + QUOTE_0_TERMINATED); + } else { + tprints(", misplaced string"); + } +} + +static int +dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg) +{ + struct dm_ioctl ioc; + char *extra = NULL; + size_t extra_size = 0; + + if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), (char *)&ioc) < 0) + return 0; + tprintf(", {version=%d.%d.%d", ioc.version[0], ioc.version[1], + ioc.version[2]); + + /* + * if we use a different version of ABI, do not attempt to decode + * ioctl fields + */ + if (ioc.version[0] != DM_VERSION_MAJOR) + goto skip; + + if (ioc.data_size > sizeof(ioc)) { + extra = malloc(ioc.data_size); + if (extra) { + extra_size = ioc.data_size; + if (umoven(tcp, arg, extra_size, extra) < 0) { + free(extra); + extra = NULL; + extra_size = 0; + } + } + } + dm_decode_device(code, &ioc); + dm_decode_values(tcp, code, &ioc); + dm_decode_flags(&ioc); + if (!abbrev(tcp)) switch (code) { + case DM_DEV_WAIT: + case DM_TABLE_STATUS: + if (entering(tcp) || syserror(tcp)) + break; + dm_decode_dm_target_spec(tcp, &ioc, extra, extra_size); + break; + case DM_TABLE_LOAD: + if (!entering(tcp)) + break; + dm_decode_dm_target_spec(tcp, &ioc, extra, extra_size); + break; + case DM_TABLE_DEPS: + if (entering(tcp) || syserror(tcp)) + break; + dm_decode_dm_target_deps(&ioc, extra, extra_size); + break; + case DM_LIST_DEVICES: + if (entering(tcp) || syserror(tcp)) + break; + dm_decode_dm_name_list(&ioc, extra, extra_size); + break; + case DM_LIST_VERSIONS: + if (entering(tcp) || syserror(tcp)) + break; + dm_decode_dm_target_versions(&ioc, extra, extra_size); + break; + case DM_TARGET_MSG: + if (entering(tcp)) { + dm_decode_dm_target_msg(&ioc, extra, + extra_size); + } else if (!syserror(tcp) && + ioc.flags & DM_DATA_OUT_FLAG) { + dm_decode_string(&ioc, extra, extra_size); + } + break; + case DM_DEV_RENAME: + case DM_DEV_SET_GEOMETRY: + if (!entering(tcp)) + break; + dm_decode_string(&ioc, extra, extra_size); + break; + } + +skip: + tprints("}"); + if (extra) + free(extra); + return 1; +} + +int +dm_ioctl(struct tcb *tcp, const unsigned int code, long arg) +{ + switch (code) { + case DM_VERSION: + case DM_REMOVE_ALL: + case DM_LIST_DEVICES: + case DM_DEV_CREATE: + case DM_DEV_REMOVE: + case DM_DEV_RENAME: + case DM_DEV_SUSPEND: + case DM_DEV_STATUS: + case DM_DEV_WAIT: + case DM_TABLE_LOAD: + case DM_TABLE_CLEAR: + case DM_TABLE_DEPS: + case DM_TABLE_STATUS: + case DM_LIST_VERSIONS: + case DM_TARGET_MSG: + case DM_DEV_SET_GEOMETRY: + return dm_known_ioctl(tcp, code, arg); + default: + return 0; + } +} + +#endif Index: strace/ioctl.c =================================================================== --- strace.orig/ioctl.c +++ strace/ioctl.c @@ -263,6 +263,10 @@ ioctl_decode(struct tcb *tcp) case 'E': return evdev_ioctl(tcp, code, arg); #endif +#ifdef HAVE_LINUX_DM_IOCTL_H + case 0xfd: + return dm_ioctl(tcp, code, arg); +#endif default: break; } Index: strace/Makefile.am =================================================================== --- strace.orig/Makefile.am +++ strace/Makefile.am @@ -42,6 +42,7 @@ strace_SOURCES = \ count.c \ desc.c \ dirent.c \ + dm.c \ epoll.c \ evdev.c \ eventfd.c \ Index: strace/defs.h =================================================================== --- strace.orig/defs.h +++ strace/defs.h @@ -587,6 +587,7 @@ extern void print_seccomp_filter(struct extern int block_ioctl(struct tcb *, const unsigned int, long); extern int evdev_ioctl(struct tcb *, const unsigned int, long); +extern int dm_ioctl(struct tcb *, const unsigned int, long); extern int loop_ioctl(struct tcb *, const unsigned int, long); extern int mtd_ioctl(struct tcb *, const unsigned int, long); extern int ptp_ioctl(struct tcb *, const unsigned int, long); Index: strace/xlat/dm_flags.in =================================================================== --- /dev/null +++ strace/xlat/dm_flags.in @@ -0,0 +1,17 @@ +DM_READONLY_FLAG +DM_SUSPEND_FLAG +DM_PERSISTENT_DEV_FLAG +DM_STATUS_TABLE_FLAG +DM_ACTIVE_PRESENT_FLAG +DM_INACTIVE_PRESENT_FLAG +DM_BUFFER_FULL_FLAG +DM_SKIP_BDGET_FLAG +DM_SKIP_LOCKFS_FLAG +DM_NOFLUSH_FLAG +DM_QUERY_INACTIVE_TABLE_FLAG +DM_UEVENT_GENERATED_FLAG +DM_UUID_FLAG +DM_SECURE_DATA_FLAG +DM_DATA_OUT_FLAG +DM_DEFERRED_REMOVE +DM_INTERNAL_SUSPEND_FLAG ------------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <alpine.LRH.2.02.1508111310290.20408-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org>]
* Re: [PATCH] device mapper support for strace [not found] ` <alpine.LRH.2.02.1508111310290.20408-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org> @ 2015-08-13 7:05 ` Mike Frysinger 0 siblings, 0 replies; 6+ messages in thread From: Mike Frysinger @ 2015-08-13 7:05 UTC (permalink / raw) To: strace development list; +Cc: dm-devel-H+wXaHxf7aLQT0dZR+AlfA [-- Attachment #1.1: Type: text/plain, Size: 1947 bytes --] On 11 Aug 2015 13:11, Mikulas Patocka wrote: > --- /dev/null > +++ strace/dm.c > @@ -0,0 +1,354 @@ > +#include "defs.h" all files should have a comment block at the top. see mtd.c as an example. > +{ > + switch (code) { > + case DM_REMOVE_ALL: case statements should be at the same indent level as the switch. see mtd.c. > + size_t offset = ioc->data_start; data_start is a __u32, so this should be uint32_t instead of size_t > + tprintf(", {sector_start=%llu, length=%llu", > + (unsigned long long)s->sector_start, > + (unsigned long long)s->length); sector_start/length are uint64_t, not unsigned long long. please use PRIu64 defines from inttypes.h instead of random casts. you can find plenty of examples in the tree already. > + if (!entering(tcp)) > + tprintf(", status=%d", (int)s->status); status is int32_t, not int, so please use PRId32 instead of int casts. > +static void > +dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra, > + size_t extra_size) > +{ > + size_t offset = ioc->data_start; uint32_t, not size_t > + if (offset + offsetof(struct dm_target_deps, dev) >= offset && > + offset + offsetof(struct dm_target_deps, dev) <= extra_size) { > + uint32_t i; > + size_t space = (extra_size - (offset + > + offsetof(struct dm_target_deps, dev))) / sizeof(__u64); > + const struct dm_target_deps *s = > + (const struct dm_target_deps *)(extra + offset); > + if (s->count > space) > + goto misplaced; count is __u32, so space should probably be uint32_t instead of size_t > +misplaced: it's not standard in strace, but personal preference is to put a single space before labels to help out with diff context > + size_t offset = ioc->data_start; uint32_t > +misplaced: add a space looks like many of these comments apply to the rest of this file, so i'll refrain from repeating myself -mike [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] [-- Attachment #2: Type: text/plain, Size: 79 bytes --] ------------------------------------------------------------------------------ [-- Attachment #3: Type: text/plain, Size: 195 bytes --] _______________________________________________ Strace-devel mailing list Strace-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/strace-devel ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-08-13 7:05 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-31 14:49 [PATCH] device mapper support for strace Mikulas Patocka
[not found] ` <alpine.LRH.2.02.1507311043370.4689-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org>
2015-07-31 15:35 ` Dmitry V. Levin
[not found] ` <20150731153520.GA20404-u2l5PoMzF/Vg9hUCZPvPmw@public.gmane.org>
2015-07-31 16:04 ` Mikulas Patocka
[not found] ` <alpine.LRH.2.02.1507311202320.29679-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org>
2015-08-01 17:54 ` Dmitry V. Levin
[not found] ` <20150801175400.GA3943-u2l5PoMzF/Vg9hUCZPvPmw@public.gmane.org>
2015-08-11 17:11 ` Mikulas Patocka
[not found] ` <alpine.LRH.2.02.1508111310290.20408-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/txMwJMAicBL8TP8PQ@public.gmane.org>
2015-08-13 7:05 ` Mike Frysinger
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.