From: Andi K. <ak...@li...> - 2011-04-08 05:07:22
|
The io_submit handler didn't show a lot of the important information in iocb passed to io_submit, like how much This patch improves this. Also I prefixed the fields with names to make it easier to read. Otherwise -- since there are so many of them -- it's hard to figure out which numbers are which. And it now only shows some fields if they have a != 0 value. This still doesn't dump the actual data in IO like read/write, just the pointer to it and the size. But that could be added on top of this patch easily. Also I was wondering if configure should error out when libaio-devel is not installed. Right now when it's not there the code is just silently stubbed out. At least the SUSE rpm has exactly this problem. -Andi diff --git a/desc.c b/desc.c index 2b9f30a..57dc755 100644 --- a/desc.c +++ b/desc.c @@ -806,6 +806,51 @@ sys_io_destroy(struct tcb *tcp) return 0; } +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*(x))) + +enum iocb_sub { + SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR +}; + +static const char * +iocb_cmd_lookup(unsigned cmd, enum iocb_sub *sub) +{ + static char buf[20]; + static struct { + const char *name; + enum iocb_sub sub; + } cmds[] = { + { "pread", SUB_COMMON }, + { "pwrite", SUB_COMMON }, + { "fsync", SUB_NONE }, + { "fdsync", SUB_NONE }, + { "op4", SUB_NONE }, + { "poll", SUB_POLL }, + { "noop", SUB_NONE }, + { "preadv", SUB_VECTOR }, + { "pwritev", SUB_VECTOR }, + }; + + if (cmd < ARRAY_SIZE(cmds)) { + *sub = cmds[cmd].sub; + return cmds[cmd].name; + } + *sub = SUB_NONE; + snprintf(buf, sizeof buf, "?%u?", cmd); + return buf; +} + +/* Not defined in libaio.h */ +#define IOCB_RESFD (1 << 0) + +static void +print_common_flags(struct iocb *iocb) +{ + if (iocb->u.c.flags & IOCB_RESFD) + tprintf("resfd=%d, ", iocb->u.c.resfd); + if (iocb->u.c.flags & ~IOCB_RESFD) + tprintf("flags=%x, ", iocb->u.c.flags); +} int sys_io_submit(struct tcb *tcp) { @@ -822,7 +867,9 @@ sys_io_submit(struct tcb *tcp) struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2]; for (i = 0; i < nr; i++, iocbs++) { + enum iocb_sub sub; struct iocb iocb; + int k; if (i == 0) tprintf("{"); else @@ -833,10 +880,45 @@ sys_io_submit(struct tcb *tcp) tprintf("{...}"); continue; } - tprintf("{%p, %u, %hu, %hu, %d}", - iocb.data, iocb.key, - iocb.aio_lio_opcode, - iocb.aio_reqprio, iocb.aio_fildes); + tprintf("{"); + if (iocb.data) + tprintf("data:%p, ", iocb.data); + if (iocb.key) + tprintf("key:%u, ", iocb.key); + tprintf("%s, ", iocb_cmd_lookup(iocb.aio_lio_opcode, &sub)); + if (iocb.aio_reqprio) + tprintf("reqprio:%d, ", iocb.aio_reqprio); + tprintf("filedes:%d", iocb.aio_fildes); + switch (sub) { + case SUB_COMMON: + tprintf(", buf:%p, nbytes:%lu, offset:%llx", + iocb.u.c.buf, + iocb.u.c.nbytes, + iocb.u.c.offset); + print_common_flags(&iocb); + break; + case SUB_VECTOR: + tprintf(", %llx, ", iocb.u.v.offset); + print_common_flags(&iocb); + for (k = 0; k < iocb.u.v.nr; k++) { + struct iovec iov; + tprintf("%s", k == 0 ? "" : ", "); + if (umove(tcp, (unsigned long)iocb.u.v.vec + + sizeof(struct iovec)*k, &iov)) + tprintf("{...}"); + else + tprintf("{ %p, %lu }", + iov.iov_base, + iov.iov_len); + } + break; + case SUB_POLL: + tprintf(", %x", iocb.u.poll.events); + break; + case SUB_NONE: + break; + } + tprintf("}"); } if (i) tprintf("}"); -- ak...@li... -- Speaking for myself only |
From: Dmitry V. L. <ld...@al...> - 2011-04-09 21:33:03
|
On Thu, Apr 07, 2011 at 10:07:15PM -0700, Andi Kleen wrote: > The io_submit handler didn't show a lot of the important information > in iocb passed to io_submit, like how much This patch improves this. Thanks. Would you like to write a commit message for the patch? [...] > Also I was wondering if configure should error out when libaio-devel > is not installed. Right now when it's not there the code is just > silently stubbed out. At least the SUSE rpm has exactly this problem. The easy fix is to add a #warning. A bit more complicated approach is to implement --enable/--disable configure switch for libaio-devel, and error out if --enable is requested but libaio-devel is not available. [...] > + case SUB_VECTOR: > + tprintf(", %llx, ", iocb.u.v.offset); > + print_common_flags(&iocb); > + for (k = 0; k < iocb.u.v.nr; k++) { > + struct iovec iov; > + tprintf("%s", k == 0 ? "" : ", "); > + if (umove(tcp, (unsigned long)iocb.u.v.vec + > + sizeof(struct iovec)*k, &iov)) > + tprintf("{...}"); > + else > + tprintf("{ %p, %lu }", > + iov.iov_base, > + iov.iov_len); > + } > + break; Please use tprint_iov() to decode iovec arrays if appropriate. -- ldv |
From: Andi K. <ak...@li...> - 2011-04-11 18:43:30
|
On Sun, Apr 10, 2011 at 01:32:55AM +0400, Dmitry V. Levin wrote: > On Thu, Apr 07, 2011 at 10:07:15PM -0700, Andi Kleen wrote: > > The io_submit handler didn't show a lot of the important information > > in iocb passed to io_submit, like how much This patch improves this. > > Thanks. Would you like to write a commit message for the patch? Here's an updated patch with ChangeLog. --- Fix io_submit decoding in strace v2 strace didn't decode important fields in the iocb passed to io_submit. This patch changes the code to dump them all. Also I prefixed the fields with names to make it easier to read. v2: Address review feedback. Use tprint_iov()/printstr() for write. Add #warning for fallback. * desc.c: (ARRAY_SIZE, iocb_cmd_lookup, print_common_flags): Add. (sys_io_submit): New iocb decoder. diff --git a/desc.c b/desc.c index 2b9f30a..6cd45a6 100644 --- a/desc.c +++ b/desc.c @@ -806,6 +806,51 @@ sys_io_destroy(struct tcb *tcp) return 0; } +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*(x))) + +enum iocb_sub { + SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR +}; + +static const char * +iocb_cmd_lookup(unsigned cmd, enum iocb_sub *sub) +{ + static char buf[20]; + static struct { + const char *name; + enum iocb_sub sub; + } cmds[] = { + { "pread", SUB_COMMON }, + { "pwrite", SUB_COMMON }, + { "fsync", SUB_NONE }, + { "fdsync", SUB_NONE }, + { "op4", SUB_NONE }, + { "poll", SUB_POLL }, + { "noop", SUB_NONE }, + { "preadv", SUB_VECTOR }, + { "pwritev", SUB_VECTOR }, + }; + + if (cmd < ARRAY_SIZE(cmds)) { + *sub = cmds[cmd].sub; + return cmds[cmd].name; + } + *sub = SUB_NONE; + snprintf(buf, sizeof buf, "?%u?", cmd); + return buf; +} + +/* Not defined in libaio.h */ +#define IOCB_RESFD (1 << 0) + +static void +print_common_flags(struct iocb *iocb) +{ + if (iocb->u.c.flags & IOCB_RESFD) + tprintf("resfd=%d, ", iocb->u.c.resfd); + if (iocb->u.c.flags & ~IOCB_RESFD) + tprintf("flags=%x, ", iocb->u.c.flags); +} int sys_io_submit(struct tcb *tcp) { @@ -822,7 +867,9 @@ sys_io_submit(struct tcb *tcp) struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2]; for (i = 0; i < nr; i++, iocbs++) { + enum iocb_sub sub; struct iocb iocb; + int k; if (i == 0) tprintf("{"); else @@ -833,14 +880,60 @@ sys_io_submit(struct tcb *tcp) tprintf("{...}"); continue; } - tprintf("{%p, %u, %hu, %hu, %d}", - iocb.data, iocb.key, - iocb.aio_lio_opcode, - iocb.aio_reqprio, iocb.aio_fildes); + tprintf("{"); + if (iocb.data) + tprintf("data:%p, ", iocb.data); + if (iocb.key) + tprintf("key:%u, ", iocb.key); + tprintf("%s, ", iocb_cmd_lookup(iocb.aio_lio_opcode, &sub)); + if (iocb.aio_reqprio) + tprintf("reqprio:%d, ", iocb.aio_reqprio); + tprintf("filedes:%d", iocb.aio_fildes); + switch (sub) { + case SUB_COMMON: + if (iocb.aio_lio_opcode == IO_CMD_PWRITE) { + tprintf(", str:"); + printstr(tcp, (unsigned long)iocb.u.c.buf, + iocb.u.c.nbytes); + } else { + tprintf(", buf:%p", iocb.u.c.buf); + } + tprintf(", nbytes:%lu, offset:%llx", + iocb.u.c.nbytes, + iocb.u.c.offset); + print_common_flags(&iocb); + break; + case SUB_VECTOR: + tprintf(", %llx, ", iocb.u.v.offset); + print_common_flags(&iocb); + if (iocb.aio_lio_opcode == IO_CMD_PWRITEV) { + tprint_iov(tcp, iocb.u.v.nr, (unsigned long)iocb.u.v.vec); + break; + } + for (k = 0; k < iocb.u.v.nr; k++) { + struct iovec iov; + tprintf("%s", k == 0 ? "" : ", "); + if (umove(tcp, (unsigned long)iocb.u.v.vec + + sizeof(struct iovec)*k, &iov)) + tprintf("[ ? ]"); + else + tprintf("[ %p, %lu ]", + iov.iov_base, + iov.iov_len); + } + break; + case SUB_POLL: + tprintf(", %x", iocb.u.poll.events); + break; + case SUB_NONE: + break; + } + tprintf("}"); } if (i) tprintf("}"); #else +#warning "no io_submit decoding. install libaio-devel" tprintf("{...}"); #endif } |
From: Dmitry V. L. <ld...@al...> - 2011-04-24 20:42:32
|
On Mon, Apr 11, 2011 at 11:43:13AM -0700, Andi Kleen wrote: [...] > Here's an updated patch with ChangeLog. Sorry for the long delay. > + case SUB_VECTOR: > + tprintf(", %llx, ", iocb.u.v.offset); > + print_common_flags(&iocb); > + if (iocb.aio_lio_opcode == IO_CMD_PWRITEV) { > + tprint_iov(tcp, iocb.u.v.nr, (unsigned long)iocb.u.v.vec); > + break; > + } > + for (k = 0; k < iocb.u.v.nr; k++) { > + struct iovec iov; > + tprintf("%s", k == 0 ? "" : ", "); > + if (umove(tcp, (unsigned long)iocb.u.v.vec + > + sizeof(struct iovec)*k, &iov)) > + tprintf("[ ? ]"); > + else > + tprintf("[ %p, %lu ]", > + iov.iov_base, > + iov.iov_len); > + } It's still unobvious for me why pwritew can be decoded using tprint_iov but preadv still has to be decoded manually. Could you explain it, please? -- ldv |
From: Andi K. <ak...@li...> - 2011-04-25 16:00:32
|
> It's still unobvious for me why pwritew can be decoded using tprint_iov > but preadv still has to be decoded manually. Could you explain it, please? Because the data is not available yet for reading -- after all it's an asynchronous read. So tprint_iov would print random old buffer contents, which doesn't seem useful to me. -Andi |