Skip to content

Commit f31ecf6

Browse files
committed
io_uring: add IORING_OP_WAITID support
This adds support for an async version of waitid(2), in a fully async version. If an event isn't immediately available, wait for a callback to trigger a retry. The format of the sqe is as follows: sqe->len The 'which', the idtype being queried/waited for. sqe->fd The 'pid' (or id) being waited for. sqe->file_index The 'options' being set. sqe->addr2 A pointer to siginfo_t, if any, being filled in. buf_index, add3, and waitid_flags are reserved/unused for now. waitid_flags will be used for options for this request type. One interesting use case may be to add multi-shot support, so that the request stays armed and posts a notification every time a monitored process state change occurs. Note that this does not support rusage, on Arnd's recommendation. See the waitid(2) man page for details on the arguments. Signed-off-by: Jens Axboe <[email protected]>
1 parent 2e521a2 commit f31ecf6

File tree

8 files changed

+410
-1
lines changed

8 files changed

+410
-1
lines changed

include/linux/io_uring_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ struct io_ring_ctx {
313313
struct list_head cq_overflow_list;
314314
struct io_hash_table cancel_table;
315315

316+
struct hlist_head waitid_list;
317+
316318
const struct cred *sq_creds; /* cred used for __io_sq_thread() */
317319
struct io_sq_data *sq_data; /* if using sq thread polling */
318320

include/uapi/linux/io_uring.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct io_uring_sqe {
6565
__u32 xattr_flags;
6666
__u32 msg_ring_flags;
6767
__u32 uring_cmd_flags;
68+
__u32 waitid_flags;
6869
};
6970
__u64 user_data; /* data to be passed back at completion time */
7071
/* pack this to avoid bogus arm OABI complaints */
@@ -241,6 +242,7 @@ enum io_uring_op {
241242
IORING_OP_SEND_ZC,
242243
IORING_OP_SENDMSG_ZC,
243244
IORING_OP_READ_MULTISHOT,
245+
IORING_OP_WAITID,
244246

245247
/* this goes last, obviously */
246248
IORING_OP_LAST,

io_uring/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ obj-$(CONFIG_IO_URING) += io_uring.o xattr.o nop.o fs.o splice.o \
77
openclose.o uring_cmd.o epoll.o \
88
statx.o net.o msg_ring.o timeout.o \
99
sqpoll.o fdinfo.o tctx.o poll.o \
10-
cancel.o kbuf.o rsrc.o rw.o opdef.o notif.o
10+
cancel.o kbuf.o rsrc.o rw.o opdef.o \
11+
notif.o waitid.o
1112
obj-$(CONFIG_IO_WQ) += io-wq.o

io_uring/cancel.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "tctx.h"
1616
#include "poll.h"
1717
#include "timeout.h"
18+
#include "waitid.h"
1819
#include "cancel.h"
1920

2021
struct io_cancel {
@@ -119,6 +120,10 @@ int io_try_cancel(struct io_uring_task *tctx, struct io_cancel_data *cd,
119120
if (ret != -ENOENT)
120121
return ret;
121122

123+
ret = io_waitid_cancel(ctx, cd, issue_flags);
124+
if (ret != -ENOENT)
125+
return ret;
126+
122127
spin_lock(&ctx->completion_lock);
123128
if (!(cd->flags & IORING_ASYNC_CANCEL_FD))
124129
ret = io_timeout_cancel(ctx, cd);

io_uring/io_uring.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
#include "cancel.h"
9393
#include "net.h"
9494
#include "notif.h"
95+
#include "waitid.h"
9596

9697
#include "timeout.h"
9798
#include "poll.h"
@@ -348,6 +349,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
348349
INIT_LIST_HEAD(&ctx->tctx_list);
349350
ctx->submit_state.free_list.next = NULL;
350351
INIT_WQ_LIST(&ctx->locked_free_list);
352+
INIT_HLIST_HEAD(&ctx->waitid_list);
351353
INIT_DELAYED_WORK(&ctx->fallback_work, io_fallback_req_func);
352354
INIT_WQ_LIST(&ctx->submit_state.compl_reqs);
353355
return ctx;
@@ -3303,6 +3305,7 @@ static __cold bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
33033305
ret |= io_cancel_defer_files(ctx, task, cancel_all);
33043306
mutex_lock(&ctx->uring_lock);
33053307
ret |= io_poll_remove_all(ctx, task, cancel_all);
3308+
ret |= io_waitid_remove_all(ctx, task, cancel_all);
33063309
mutex_unlock(&ctx->uring_lock);
33073310
ret |= io_kill_timeouts(ctx, task, cancel_all);
33083311
if (task)

io_uring/opdef.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "poll.h"
3434
#include "cancel.h"
3535
#include "rw.h"
36+
#include "waitid.h"
3637

3738
static int io_no_issue(struct io_kiocb *req, unsigned int issue_flags)
3839
{
@@ -439,6 +440,10 @@ const struct io_issue_def io_issue_defs[] = {
439440
.prep = io_read_mshot_prep,
440441
.issue = io_read_mshot,
441442
},
443+
[IORING_OP_WAITID] = {
444+
.prep = io_waitid_prep,
445+
.issue = io_waitid,
446+
},
442447
};
443448

444449
const struct io_cold_def io_cold_defs[] = {
@@ -661,6 +666,10 @@ const struct io_cold_def io_cold_defs[] = {
661666
[IORING_OP_READ_MULTISHOT] = {
662667
.name = "READ_MULTISHOT",
663668
},
669+
[IORING_OP_WAITID] = {
670+
.name = "WAITID",
671+
.async_size = sizeof(struct io_waitid_async),
672+
},
664673
};
665674

666675
const char *io_uring_get_opcode(u8 opcode)

0 commit comments

Comments
 (0)