diff options
author | Eugene Syromyatnikov <evgsyr@gmail.com> | 2022-05-02 03:50:34 +0200 |
---|---|---|
committer | Dmitry V. Levin <ldv@strace.io> | 2022-05-02 01:50:34 +0000 |
commit | db211a06d1e028173a3fc0a0f715c91ccbd97d8a (patch) | |
tree | 0ce8da6023b0658cd0758a74a6ecafb7e859ad01 | |
parent | 894b9ac409a0ef29b2a3fb6af51598a9fad9ecf6 (diff) | |
download | strace-db211a06d1e028173a3fc0a0f715c91ccbd97d8a.tar.gz |
io_uring: decode IORING_{,UN}REGISTER_RING_FDS io_uring_register operations
* src/xlat/uring_register_opcodes.in (IORING_REGISTER_RING_FDS,
IORING_UNREGISTER_RING_FDS): New constants, introduced by Linux commit
v5.18-rc1~22^2~44.
* src/io_uring.c (print_ringfd_register_array_member,
print_io_uring_ringfds_register, print_ringfd_unregister_array_member,
print_io_uring_ringfds_unregister): New functions.
(SYS_FUNC(io_uring_register)) <case IORING_REGISTER_RING_FDS>: New case,
call print_io_uring_ringfds_register.
(SYS_FUNC(io_uring_register)) <case IORING_UNREGISTER_RING_FDS>: New case,
call print_io_uring_ringfds_unregister.
* tests/io_uring_register.c: Update expected output, add checks
for IORING_REGISTER_RING_FDS and IORING_UNREGISTER_RING_FDS ops decoding.
* NEWS: Mention this.
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | src/io_uring.c | 82 | ||||
-rw-r--r-- | src/xlat/uring_register_opcodes.in | 2 | ||||
-rw-r--r-- | tests/io_uring_register.c | 102 |
4 files changed, 184 insertions, 3 deletions
@@ -5,6 +5,7 @@ Noteworthy changes in release ?.?? (????-??-??) * Added an interface of raising des Strausses awareness. * Added --tips option to print strace tips, tricks, and tweaks at the end of the tracing session. + * Enhanced decoding of io_uring_register syscall. * Updated lists of BR_*, BTRFS_*, IFA_*, IFLA_*, KEY_*, and MADV_* constants. * Bug fixes diff --git a/src/io_uring.c b/src/io_uring.c index 796e374bc..be86ca41e 100644 --- a/src/io_uring.c +++ b/src/io_uring.c @@ -485,6 +485,82 @@ print_io_uring_iowq_acct(struct tcb *tcp, const kernel_ulong_t addr, return ret ? 0 : RVAL_DECODED; } +static bool +print_ringfd_register_array_member(struct tcb *tcp, void *buf, + size_t elem_size, void *data) +{ + /* offset - offset to insert at or -1 for the first free place */ + /* resv - reserved */ + /* data - FD to register */ + struct io_uring_rsrc_update *elem = buf; + + tprint_struct_begin(); + if (elem->offset == -1U) + PRINT_FIELD_D(*elem, offset); + else + PRINT_FIELD_U(*elem, offset); + + if (elem->resv) { + tprint_struct_next(); + PRINT_FIELD_X(*elem, resv); + } + + tprint_struct_next(); + PRINT_FIELD_FD(*elem, data, tcp); + + tprint_struct_end(); + + return true; +} +static void +print_io_uring_ringfds_register(struct tcb *tcp, const kernel_ulong_t arg, + const unsigned int nargs) +{ + struct io_uring_rsrc_update buf; + CHECK_TYPE_SIZE(buf, 16); + CHECK_TYPE_SIZE(buf.resv, sizeof(uint32_t)); + + print_array(tcp, arg, nargs, &buf, sizeof(buf), + tfetch_mem, print_ringfd_register_array_member, NULL); +} + + +static bool +print_ringfd_unregister_array_member(struct tcb *tcp, void *buf, + size_t elem_size, void *data) +{ + /* offset - offset to unregister FD */ + /* resv - reserved */ + /* data - unused */ + struct io_uring_rsrc_update *elem = buf; + + tprint_struct_begin(); + PRINT_FIELD_U(*elem, offset); + + if (elem->resv) { + tprint_struct_next(); + PRINT_FIELD_X(*elem, resv); + } + + if (elem->data) { + tprint_struct_next(); + PRINT_FIELD_X(*elem, data); + } + + tprint_struct_end(); + + return true; +} +static void +print_io_uring_ringfds_unregister(struct tcb *tcp, const kernel_ulong_t arg, + const unsigned int nargs) +{ + struct io_uring_rsrc_update buf; + + print_array(tcp, arg, nargs, &buf, sizeof(buf), + tfetch_mem, print_ringfd_unregister_array_member, NULL); +} + SYS_FUNC(io_uring_register) { const int fd = tcp->u_arg[0]; @@ -541,6 +617,12 @@ SYS_FUNC(io_uring_register) if (entering(tcp) && !rc) tprint_value_changed(); break; + case IORING_REGISTER_RING_FDS: + print_io_uring_ringfds_register(tcp, arg, nargs); + break; + case IORING_UNREGISTER_RING_FDS: + print_io_uring_ringfds_unregister(tcp, arg, nargs); + break; case IORING_UNREGISTER_BUFFERS: case IORING_UNREGISTER_FILES: case IORING_UNREGISTER_EVENTFD: diff --git a/src/xlat/uring_register_opcodes.in b/src/xlat/uring_register_opcodes.in index 966d8cb37..2292bdaff 100644 --- a/src/xlat/uring_register_opcodes.in +++ b/src/xlat/uring_register_opcodes.in @@ -20,3 +20,5 @@ IORING_REGISTER_BUFFERS_UPDATE IORING_REGISTER_IOWQ_AFF IORING_UNREGISTER_IOWQ_AFF IORING_REGISTER_IOWQ_MAX_WORKERS +IORING_REGISTER_RING_FDS +IORING_UNREGISTER_RING_FDS diff --git a/tests/io_uring_register.c b/tests/io_uring_register.c index bbd703196..47311276a 100644 --- a/tests/io_uring_register.c +++ b/tests/io_uring_register.c @@ -152,6 +152,7 @@ main(void) skip_if_unavailable("/proc/self/fd/"); + close(0); /* Trying to get fd 0 for /dev/null */ int fd_null = open(path_null, O_RDONLY); if (fd_null < 0) perror_msg_and_fail("open: %s", path_null); @@ -161,11 +162,12 @@ main(void) perror_msg_and_fail("open: %s", path_full); int fds[] = { fd_full, fd_null, -1, -2, -3 }; + const char *paths[ARRAY_SIZE(fds)] = { path_full, path_null }; const int *arg_fds = tail_memdup(fds, sizeof(fds)); /* Invalid op */ - static const unsigned int invalid_ops[] = { 0xbadc0dedU, 20 }; + static const unsigned int invalid_ops[] = { 0xbadc0dedU, 22 }; for (size_t i = 0; i < ARRAY_SIZE(invalid_ops); i++) { sys_io_uring_register(fd_null, invalid_ops[i], path_null, @@ -452,10 +454,10 @@ main(void) { ARG_STR(IORING_RESTRICTION_REGISTER_OP), true, "register_op=", ARG_STR(IORING_REGISTER_BUFFERS), true }, { ARG_STR(IORING_RESTRICTION_REGISTER_OP), true, - "register_op=", ARG_STR(IORING_UNREGISTER_IOWQ_AFF), + "register_op=", ARG_STR(IORING_UNREGISTER_RING_FDS), true }, { ARG_STR(IORING_RESTRICTION_REGISTER_OP), true, - "register_op=", 20, " /* IORING_REGISTER_??? */", false }, + "register_op=", 22, " /* IORING_REGISTER_??? */", false }, { ARG_STR(IORING_RESTRICTION_REGISTER_OP), true, "register_op=", 255, " /* IORING_REGISTER_??? */", false }, { ARG_STR(IORING_RESTRICTION_SQE_OP), true, @@ -962,6 +964,100 @@ main(void) #endif errstr); + + /* IORING_REGISTER_RING_FDS, IORING_UNREGISTER_RING_FDS */ + static const struct { + unsigned int op; + const char *str; + } ringfd_ops[] = { + { 20, "IORING_REGISTER_RING_FDS" }, + { 21, "IORING_UNREGISTER_RING_FDS" }, + }; + + static const size_t ringfd_count = DEFAULT_STRLEN + 1; + static const uint32_t ringfd_off[] = + { -1U, 0, 1, 2, 161803398, 3141592653, -2U }; + TAIL_ALLOC_OBJECT_VAR_ARR(struct io_uring_rsrc_update, ringfds, + ringfd_count); + + fill_memory(ringfds, sizeof(*ringfds) * ringfd_count); + for (size_t i = 0; i < ringfd_count; i++) { + ringfds[i].offset = ringfd_off[i % ARRAY_SIZE(ringfd_off)]; + ringfds[i].resv = i % 2 ? i * 0x1010101 : 0; + ringfds[i].data = (i % 4 ? 0xbadc0ded00000000ULL : 0) + | fds[i % ARRAY_SIZE(fds)]; + } + + for (size_t i = 0; i < ARRAY_SIZE(ringfd_ops); i++) { + sys_io_uring_register(fd_null, ringfd_ops[i].op, 0, + 0xdeadbeef); + printf("io_uring_register(%u<%s>, " XLAT_FMT ", NULL, %u)" + " = %s\n", + fd_null, path_null, + XLAT_SEL(ringfd_ops[i].op, ringfd_ops[i].str), + 0xdeadbeef, errstr); + + sys_io_uring_register(fd_null, ringfd_ops[i].op, + ringfds + ringfd_count, 0); + printf("io_uring_register(%u<%s>, " XLAT_FMT ", [], 0) = %s\n", + fd_null, path_null, + XLAT_SEL(ringfd_ops[i].op, ringfd_ops[i].str), + errstr); + + sys_io_uring_register(fd_null, ringfd_ops[i].op, + ringfds + ringfd_count, 1); + printf("io_uring_register(%u<%s>, " XLAT_FMT ", %p, 1)" + " = %s\n", + fd_null, path_null, + XLAT_SEL(ringfd_ops[i].op, ringfd_ops[i].str), + ringfds + ringfd_count, errstr); + + /* offs:sz: 33-31:32, 33-32:32, 33-32:33, 33-33:33 */ + for (size_t j = 0; j < 4; j++) { + const size_t offs = (4 - j) / 2; + const size_t sz = 32 + j / 2; + + sys_io_uring_register(fd_null, ringfd_ops[i].op, + ringfds + offs, sz); + printf("io_uring_register(%u<%s>, " XLAT_FMT ", [", + fd_null, path_null, + XLAT_SEL(ringfd_ops[i].op, ringfd_ops[i].str)); + for (uint32_t k = offs; k < MIN(ringfd_count, + DEFAULT_STRLEN + offs); + k++) { + printf("%s{offset=", k != offs ? ", " : ""); + printf(ringfd_ops[i].op == 21 || + k % ARRAY_SIZE(ringfd_off) ? "%u" : "%d", + ringfd_off[k % ARRAY_SIZE(ringfd_off)]); + if (k % 2) + printf(", resv=%#x", k * 0x1010101); + + const size_t fdid = k % ARRAY_SIZE(fds); + if (ringfd_ops[i].op == 20) { + printf(", data=%d%s%s%s", + fds[fdid], + paths[fdid] ? "<": "", + paths[fdid] ? paths[fdid] : "", + paths[fdid] ? ">": ""); + } else { + if (!((k % ARRAY_SIZE(fds) == 1) + && !(k % 4))) { + printf(", data=%#llx", + (k % 4 + ? 0xbadc0ded00000000ULL + : 0) | fds[fdid]); + } + } + printf("}"); + } + if (j != 1) + printf(", ..."); + if (!(j % 2)) + printf(" /* %p */", ringfds + ringfd_count); + printf("], %zu) = %s\n", sz, errstr); + } + } + puts("+++ exited with 0 +++"); return 0; } |