io_uring: add zc notification flush requests
authorPavel Begunkov <asml.silence@gmail.com>
Tue, 12 Jul 2022 20:52:49 +0000 (21:52 +0100)
committerJens Axboe <axboe@kernel.dk>
Mon, 25 Jul 2022 00:41:07 +0000 (18:41 -0600)
Overlay notification control onto IORING_OP_RSRC_UPDATE (former
IORING_OP_FILES_UPDATE). It allows to flush a range of zc notifications
from slots with indexes [sqe->off, sqe->off+sqe->len). If sqe->arg is
not zero, it also copies sqe->arg as a new tag for all flushed
notifications.

Note, it doesn't flush a notification of a slot if there was no requests
attached to it (since last flush or registration).

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/df13e2363400682a73dd9e71c3b990b8d1ff0333.1657643355.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/uapi/linux/io_uring.h
io_uring/rsrc.c

index 210a00a..1463cfe 100644 (file)
@@ -297,6 +297,7 @@ enum io_uring_op {
  */
 enum {
        IORING_RSRC_UPDATE_FILES,
+       IORING_RSRC_UPDATE_NOTIF,
 };
 
 /*
index fc2b337..9165fdf 100644 (file)
@@ -15,6 +15,7 @@
 #include "io_uring.h"
 #include "openclose.h"
 #include "rsrc.h"
+#include "notif.h"
 
 struct io_rsrc_update {
        struct file                     *file;
@@ -744,6 +745,41 @@ static int io_files_update(struct io_kiocb *req, unsigned int issue_flags)
        return IOU_OK;
 }
 
+static int io_notif_update(struct io_kiocb *req, unsigned int issue_flags)
+{
+       struct io_rsrc_update *up = io_kiocb_to_cmd(req);
+       struct io_ring_ctx *ctx = req->ctx;
+       unsigned len = up->nr_args;
+       unsigned idx_end, idx = up->offset;
+       int ret = 0;
+
+       io_ring_submit_lock(ctx, issue_flags);
+       if (unlikely(check_add_overflow(idx, len, &idx_end))) {
+               ret = -EOVERFLOW;
+               goto out;
+       }
+       if (unlikely(idx_end > ctx->nr_notif_slots)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       for (; idx < idx_end; idx++) {
+               struct io_notif_slot *slot = &ctx->notif_slots[idx];
+
+               if (!slot->notif)
+                       continue;
+               if (up->arg)
+                       slot->tag = up->arg;
+               io_notif_slot_flush_submit(slot, issue_flags);
+       }
+out:
+       io_ring_submit_unlock(ctx, issue_flags);
+       if (ret < 0)
+               req_set_fail(req);
+       io_req_set_res(req, ret, 0);
+       return IOU_OK;
+}
+
 int io_rsrc_update(struct io_kiocb *req, unsigned int issue_flags)
 {
        struct io_rsrc_update *up = io_kiocb_to_cmd(req);
@@ -751,6 +787,8 @@ int io_rsrc_update(struct io_kiocb *req, unsigned int issue_flags)
        switch (up->type) {
        case IORING_RSRC_UPDATE_FILES:
                return io_files_update(req, issue_flags);
+       case IORING_RSRC_UPDATE_NOTIF:
+               return io_notif_update(req, issue_flags);
        }
        return -EINVAL;
 }