From: Dmitry V. Levin Date: Wed, 26 Aug 2015 17:48:40 +0000 (+0000) Subject: aio: rewrite from libaio.h to linux/aio_abi.h X-Git-Tag: v4.11~250 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f56046e45911f5a1e1a617e35d5c709570ec43d5;p=strace aio: rewrite from libaio.h to linux/aio_abi.h * configure.ac (AC_CHECK_HEADERS): Remove libaio.h. * aio.c: Assume that is available, include it instead of . [!IOCB_RESFD]: Remove. (enum iocb_sub): Remove SUB_POLL. (tprint_lio_opcode): Update. (print_common_flags): Use IOCB_FLAG_RESFD instead of IOCB_RESFD, rename fields of struct iocb. (iocb_is_valid, print_iocb_header, print_iocb): New functions. (sys_io_submit): Use print_iocb. (print_io_event): Fix struct io_event decoding. (sys_io_cancel): Use print_iocb_header. * strace.spec (BuildRequires): Remove libaio-devel. * tests/aio.c (main): Test IOCB_CMD_PREADV, io_cancel, and struct io_event decoding. * tests/aio.test (syscalls): Add io_cancel. --- diff --git a/aio.c b/aio.c index 5822a4fd..f8c73358 100644 --- a/aio.c +++ b/aio.c @@ -29,14 +29,7 @@ */ #include "defs.h" -#ifdef HAVE_LIBAIO_H -# include -#endif - -/* Not defined in libaio.h */ -#ifndef IOCB_RESFD -# define IOCB_RESFD (1 << 0) -#endif +#include SYS_FUNC(io_setup) { @@ -54,10 +47,8 @@ SYS_FUNC(io_destroy) return RVAL_DECODED; } -#ifdef HAVE_LIBAIO_H - enum iocb_sub { - SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR + SUB_NONE, SUB_COMMON, SUB_VECTOR }; static enum iocb_sub @@ -71,8 +62,8 @@ tprint_lio_opcode(unsigned cmd) { "pwrite", SUB_COMMON }, { "fsync", SUB_NONE }, { "fdsync", SUB_NONE }, - { "op4", SUB_NONE }, - { "poll", SUB_POLL }, + { "preadx", SUB_NONE }, + { "poll", SUB_NONE }, { "noop", SUB_NONE }, { "preadv", SUB_VECTOR }, { "pwritev", SUB_VECTOR }, @@ -87,34 +78,94 @@ tprint_lio_opcode(unsigned cmd) } static void -print_common_flags(struct iocb *iocb) +print_common_flags(const struct iocb *cb) { -#ifdef HAVE_STRUCT_IOCB_U_C_FLAGS - 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); -#else -# warning "libaio.h is too old => limited io_submit decoding" +/* IOCB_FLAG_RESFD is available since v2.6.22-rc1~47 */ +#ifdef IOCB_FLAG_RESFD + if (cb->aio_flags & IOCB_FLAG_RESFD) + tprintf(", resfd=%d", cb->aio_resfd); + if (cb->aio_flags & ~IOCB_FLAG_RESFD) + tprintf(", flags=%x", cb->aio_flags); #endif } -#endif /* HAVE_LIBAIO_H */ +static bool +iocb_is_valid(const struct iocb *cb) +{ + return cb->aio_buf == (unsigned long) cb->aio_buf && + cb->aio_nbytes == (size_t) cb->aio_nbytes && + (ssize_t) cb->aio_nbytes >= 0; +} + +static enum iocb_sub +print_iocb_header(const struct iocb *cb) +{ + enum iocb_sub sub; + + if (cb->aio_data) + tprintf("data=%#" PRIx64 ", ", + (uint64_t) cb->aio_data); + + if (cb->aio_key) + tprintf("key=%u, ", cb->aio_key); + + sub = tprint_lio_opcode(cb->aio_lio_opcode); + if (cb->aio_reqprio) + tprintf(", reqprio=%hd", cb->aio_reqprio); + + tprintf(", fildes=%d", cb->aio_fildes); + + return sub; +} + +static void +print_iocb(struct tcb *tcp, const struct iocb *cb) +{ + enum iocb_sub sub = print_iocb_header(cb); + + switch (sub) { + case SUB_COMMON: + if (cb->aio_lio_opcode == 1 && iocb_is_valid(cb)) { + tprints(", str="); + printstr(tcp, (unsigned long) cb->aio_buf, + (unsigned long) cb->aio_nbytes); + } else { + tprintf(", buf=%#" PRIx64, (uint64_t) cb->aio_buf); + } + tprintf(", nbytes=%" PRIu64 ", offset=%" PRId64, + (uint64_t) cb->aio_nbytes, (int64_t) cb->aio_offset); + print_common_flags(cb); + break; + case SUB_VECTOR: + if (iocb_is_valid(cb)) { + tprints(", iovec="); + tprint_iov(tcp, cb->aio_nbytes, cb->aio_buf, + cb->aio_lio_opcode == 8); + } else { + tprintf(", buf=%#" PRIx64 ", nbytes=%" PRIu64, + (uint64_t) cb->aio_buf, + (uint64_t) cb->aio_nbytes); + } + tprintf(", offset=%" PRId64, (int64_t) cb->aio_offset); + print_common_flags(cb); + break; + case SUB_NONE: + break; + } +} SYS_FUNC(io_submit) { -#ifdef HAVE_LIBAIO_H long nr = tcp->u_arg[1]; /* if nr <= 0, we end up printing just "[]" */ - tprintf("%lu, %ld, [", tcp->u_arg[0], tcp->u_arg[1]); + tprintf("%lu, %ld, [", tcp->u_arg[0], nr); { long i; long iocbs = tcp->u_arg[2]; for (i = 0; i < nr; ++i, iocbs += current_wordsize) { - enum iocb_sub sub; long iocbp; - struct iocb iocb; + struct iocb cb; if (i) tprints(", "); @@ -128,86 +179,26 @@ SYS_FUNC(io_submit) } tprints("{"); - if (umove_or_printaddr(tcp, iocbp, &iocb)) { - tprints("}"); - continue; - } - - if (iocb.data) { - tprints("data="); - printaddr((long) iocb.data); - tprints(", "); - } - if (iocb.key) - tprintf("key=%u, ", iocb.key); - sub = tprint_lio_opcode(iocb.aio_lio_opcode); - if (iocb.aio_reqprio) - tprintf(", reqprio=%d", iocb.aio_reqprio); - tprintf(", filedes=%d", iocb.aio_fildes); - switch (sub) { - case SUB_COMMON: -#if HAVE_DECL_IO_CMD_PWRITE - if (iocb.aio_lio_opcode == IO_CMD_PWRITE) { - tprints(", str="); - printstr(tcp, (unsigned long)iocb.u.c.buf, - iocb.u.c.nbytes); - } else -#endif - { - tprints(", buf="); - printaddr((long) iocb.u.c.buf); - } - tprintf(", nbytes=%lu, offset=%lld", - iocb.u.c.nbytes, - iocb.u.c.offset); - print_common_flags(&iocb); - break; - case SUB_VECTOR: - tprintf(", %lld", iocb.u.v.offset); - print_common_flags(&iocb); - tprints(", "); - tprint_iov(tcp, iocb.u.v.nr, - (unsigned long)iocb.u.v.vec, -#if HAVE_DECL_IO_CMD_PWRITEV - iocb.aio_lio_opcode == IO_CMD_PWRITEV -#else - 0 -#endif - ); - break; - case SUB_POLL: - tprintf(", %x", iocb.u.poll.events); - break; - case SUB_NONE: - break; - } + if (!umove_or_printaddr(tcp, iocbp, &cb)) + print_iocb(tcp, &cb); tprints("}"); } } tprints("]"); -#else -# warning "libaio.h is not available => no io_submit decoding" - tprintf("%lu, %ld, %#lx", tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]); -#endif return RVAL_DECODED; } static int print_io_event(struct tcb *tcp, const long addr) { -#ifdef HAVE_LIBAIO_H struct io_event event; if (umove_or_printaddr(tcp, addr, &event)) return -1; - tprints("{data="); - printaddr((long) event.data); - tprints(", obj="); - printaddr((long) event.obj); - tprintf(", res=%ld, res2=%ld}", event.res, event.res2); -#else - printaddr(tcp->u_arg[2]); -#endif + tprintf("{data=%#" PRIx64 ", obj=%#" PRIx64 + ", res=%" PRId64 ", res2=%" PRId64 "}", + (uint64_t) event.data, (uint64_t) event.obj, + (int64_t) event.res, (int64_t) event.res2); return 0; } @@ -215,18 +206,14 @@ SYS_FUNC(io_cancel) { if (entering(tcp)) { tprintf("%lu, ", tcp->u_arg[0]); -#ifdef HAVE_LIBAIO_H - struct iocb iocb; + struct iocb cb; - if (!umove_or_printaddr(tcp, tcp->u_arg[1], &iocb)) { - tprintf("{%p, %u, %u, %u, %d}, ", - iocb.data, iocb.key, - (unsigned)iocb.aio_lio_opcode, - (unsigned)iocb.aio_reqprio, iocb.aio_fildes); + if (!umove_or_printaddr(tcp, tcp->u_arg[1], &cb)) { + tprints("{"); + print_iocb_header(&cb); + tprints("}"); } -#else - printaddr(tcp->u_arg[1]); -#endif + tprints(", "); } else { print_io_event(tcp, tcp->u_arg[2]); } @@ -242,7 +229,6 @@ SYS_FUNC(io_getevents) if (tcp->u_rval == 0) { tprints("[]"); } else { -#ifdef HAVE_LIBAIO_H struct io_event *events = (void *)tcp->u_arg[3]; long i, nr = tcp->u_rval; @@ -256,9 +242,6 @@ SYS_FUNC(io_getevents) break; } tprints("], "); -#else - printaddr(tcp->u_arg[3]); -#endif } print_timespec(tcp, tcp->u_arg[4]); diff --git a/configure.ac b/configure.ac index 92160392..2f43b188 100644 --- a/configure.ac +++ b/configure.ac @@ -330,11 +330,6 @@ AC_CHECK_MEMBERS([struct sigevent._sigev_un._pad, AC_CHECK_TYPES([struct flock64],,, [#include ]) -AC_CHECK_HEADERS([libaio.h], [ - AC_CHECK_MEMBERS([struct iocb.u.c.flags],,, [#include ]) - AC_CHECK_DECLS([IO_CMD_PWRITE, IO_CMD_PWRITEV],,, [#include ]) -]) - AC_CHECK_HEADERS([linux/input.h], [ AC_CHECK_MEMBERS([struct input_absinfo.resolution],,, [#include ]) ]) diff --git a/strace.spec b/strace.spec index 7ab1bdae..8165d0d7 100644 --- a/strace.spec +++ b/strace.spec @@ -7,7 +7,7 @@ Group: Development/Debuggers URL: http://sourceforge.net/projects/strace/ Source: http://downloads.sourceforge.net/strace/%{name}-%{version}.tar.xz -BuildRequires: libacl-devel, libaio-devel, time +BuildRequires: libacl-devel, time %define strace64_arches ppc64 sparc64 diff --git a/tests/aio.c b/tests/aio.c index a59ae8ed..08974e1b 100644 --- a/tests/aio.c +++ b/tests/aio.c @@ -29,6 +29,8 @@ # include "config.h" #endif +#include +#include #include #include #include @@ -38,43 +40,93 @@ #if defined __NR_io_setup \ && defined __NR_io_submit \ && defined __NR_io_getevents \ + && defined __NR_io_cancel \ && defined __NR_io_destroy # include +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + int main(void) { static char data0[4096]; static char data1[8192]; - struct iocb cb[2] = { + const struct iocb cb[] = { { - .aio_data = 0x11111111, + .aio_data = 0xfeedface11111111, .aio_reqprio = 11, .aio_buf = (unsigned long) data0, - .aio_offset = 0xdefacedfacefeed, + .aio_offset = 0xdeface1facefeed, .aio_nbytes = sizeof(data0) }, { - .aio_data = 0x22222222, + .aio_data = 0xfeedface22222222, .aio_reqprio = 22, .aio_buf = (unsigned long) data1, - .aio_offset = 0xdefacedcafef00d, + .aio_offset = 0xdeface2cafef00d, .aio_nbytes = sizeof(data1) } }; + const struct iovec iov0[] = { + { + .iov_base = data0, + .iov_len = sizeof(data0) / 4 + }, + { + .iov_base = data0 + sizeof(data0) / 4, + .iov_len = sizeof(data0) / 4 * 3 + }, + }; + const struct iovec iov1[] = { + { + .iov_base = data1, + .iov_len = sizeof(data1) / 4 + }, + { + .iov_base = data1 + sizeof(data1) / 4, + .iov_len = sizeof(data1) / 4 * 3 + }, + }; + const struct iocb cbv[] = { + { + .aio_data = 0xfeed11111111face, + .aio_lio_opcode = 7, + .aio_reqprio = 111, + .aio_buf = (unsigned long) &iov0, + .aio_offset = 0xdeface1facefeed, + .aio_nbytes = ARRAY_SIZE(iov0) + }, + { + .aio_data = 0xfeed22222222face, + .aio_lio_opcode = 7, + .aio_reqprio = 222, + .aio_buf = (unsigned long) &iov1, + .aio_offset = 0xdeface2cafef00d, + .aio_nbytes = ARRAY_SIZE(iov1) + } + }; + struct iocb cbc = { + .aio_data = 0xdeadbeefbadc0ded, + .aio_reqprio = 99, + .aio_fildes = -42 + }; - long cbs[4] = { + const long cbs[ARRAY_SIZE(cb) + 2] = { (long) &cb[0], (long) &cb[1], 0xdeadbeef, 0xbadc0ded }; + const long cbvs[ARRAY_SIZE(cb) + 2] = { + (long) &cbv[0], (long) &cbv[1], + 0xdeadbeef, 0xbadc0ded + }; unsigned long ctx = 0; - const unsigned int nr = sizeof(cb) / sizeof(*cb); + const unsigned int nr = ARRAY_SIZE(cb); const unsigned long lnr = (unsigned long) (0xdeadbeef00000000ULL | nr); struct io_event ev[nr]; - struct timespec ts = { .tv_nsec = 123456789 }; + const struct timespec ts = { .tv_nsec = 123456789 }; (void) close(0); if (open("/dev/zero", O_RDONLY)) @@ -87,9 +139,9 @@ main(void) if (syscall(__NR_io_submit, ctx, nr, cbs) != (long) nr) return 77; printf("io_submit(%lu, %u, [" - "{data=%#llx, pread, reqprio=11, filedes=0, " + "{data=%#llx, pread, reqprio=11, fildes=0, " "buf=%p, nbytes=%u, offset=%lld}, " - "{data=%#llx, pread, reqprio=22, filedes=0, " + "{data=%#llx, pread, reqprio=22, fildes=0, " "buf=%p, nbytes=%u, offset=%lld}" "]) = %u\n", ctx, nr, @@ -99,21 +151,43 @@ main(void) (unsigned int) sizeof(data1), (long long) cb[1].aio_offset, nr); - if (syscall(__NR_io_getevents, ctx, nr, nr, ev, &ts) != (long) nr) - return 77; + assert(syscall(__NR_io_getevents, ctx, nr, nr + 1, ev, &ts) == (long) nr); printf("io_getevents(%lu, %u, %u, [" "{data=%#llx, obj=%p, res=%u, res2=0}, " "{data=%#llx, obj=%p, res=%u, res2=0}" "], {0, 123456789}) = %u\n", - ctx, nr, nr, + ctx, nr, nr + 1, (unsigned long long) cb[0].aio_data, &cb[0], (unsigned int) sizeof(data0), (unsigned long long) cb[1].aio_data, &cb[1], (unsigned int) sizeof(data1), nr); - if (syscall(__NR_io_destroy, ctx)) + assert(syscall(__NR_io_cancel, ctx, &cbc, ev) == -1 && EINVAL == errno); + printf("io_cancel(%lu, {data=%#llx, pread, reqprio=99, fildes=-42}, %p) " + "= -1 EINVAL (Invalid argument)\n", + ctx, (unsigned long long) cbc.aio_data, ev); + + if (syscall(__NR_io_submit, ctx, nr, cbvs) != (long) nr) return 77; + printf("io_submit(%lu, %u, [" + "{data=%#llx, preadv, reqprio=%hd, fildes=0, " + "iovec=[{%p, %u}, {%p, %u}], offset=%lld}, " + "{data=%#llx, preadv, reqprio=%hd, fildes=0, " + "iovec=[{%p, %u}, {%p, %u}], offset=%lld}" + "]) = %u\n", + ctx, nr, + (unsigned long long) cbv[0].aio_data, cbv[0].aio_reqprio, + iov0[0].iov_base, (unsigned int) iov0[0].iov_len, + iov0[1].iov_base, (unsigned int) iov0[1].iov_len, + (long long) cbv[0].aio_offset, + (unsigned long long) cbv[1].aio_data, cbv[1].aio_reqprio, + iov1[0].iov_base, (unsigned int) iov1[0].iov_len, + iov1[1].iov_base, (unsigned int) iov1[1].iov_len, + (long long) cbv[1].aio_offset, + nr); + + assert(syscall(__NR_io_destroy, ctx) == 0); printf("io_destroy(%lu) = 0\n", ctx); puts("+++ exited with 0 +++"); diff --git a/tests/aio.test b/tests/aio.test index f5907e46..93428f3f 100755 --- a/tests/aio.test +++ b/tests/aio.test @@ -6,7 +6,7 @@ run_prog > /dev/null OUT="$LOG.out" -syscalls=io_setup,io_submit,io_getevents,io_destroy +syscalls=io_setup,io_submit,io_getevents,io_cancel,io_destroy run_strace -a14 -e trace=$syscalls $args > "$OUT" match_diff "$LOG" "$OUT" rm -f "$OUT"