io_uring: add support for IORING_SETUP_CLAMP
authorJens Axboe <axboe@kernel.dk>
Sat, 28 Dec 2019 22:39:54 +0000 (15:39 -0700)
committerJens Axboe <axboe@kernel.dk>
Tue, 21 Jan 2020 00:04:02 +0000 (17:04 -0700)
Some applications like to start small in terms of ring size, and then
ramp up as needed. This is a bit tricky to do currently, since we don't
advertise the max ring size.

This adds IORING_SETUP_CLAMP. If set, and the values for SQ or CQ ring
size exceed what we support, then clamp them at the max values instead
of returning -EINVAL. Since we return the chosen ring sizes after setup,
no further changes are needed on the application side. io_uring already
changes the ring sizes if the application doesn't ask for power-of-two
sizes, for example.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c
include/uapi/linux/io_uring.h

index 1fbe3eb78d089e72f3b981da4c4928248612a89c..7c44b0ef10d7937561767242bb5c2af23b363546 100644 (file)
@@ -6234,8 +6234,13 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
        bool account_mem;
        int ret;
 
-       if (!entries || entries > IORING_MAX_ENTRIES)
+       if (!entries)
                return -EINVAL;
+       if (entries > IORING_MAX_ENTRIES) {
+               if (!(p->flags & IORING_SETUP_CLAMP))
+                       return -EINVAL;
+               entries = IORING_MAX_ENTRIES;
+       }
 
        /*
         * Use twice as many entries for the CQ ring. It's possible for the
@@ -6252,8 +6257,13 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
                 * to a power-of-two, if it isn't already. We do NOT impose
                 * any cq vs sq ring sizing.
                 */
-               if (p->cq_entries < p->sq_entries || p->cq_entries > IORING_MAX_CQ_ENTRIES)
+               if (p->cq_entries < p->sq_entries)
                        return -EINVAL;
+               if (p->cq_entries > IORING_MAX_CQ_ENTRIES) {
+                       if (!(p->flags & IORING_SETUP_CLAMP))
+                               return -EINVAL;
+                       p->cq_entries = IORING_MAX_CQ_ENTRIES;
+               }
                p->cq_entries = roundup_pow_of_two(p->cq_entries);
        } else {
                p->cq_entries = 2 * p->sq_entries;
@@ -6345,7 +6355,8 @@ static long io_uring_setup(u32 entries, struct io_uring_params __user *params)
        }
 
        if (p.flags & ~(IORING_SETUP_IOPOLL | IORING_SETUP_SQPOLL |
-                       IORING_SETUP_SQ_AFF | IORING_SETUP_CQSIZE))
+                       IORING_SETUP_SQ_AFF | IORING_SETUP_CQSIZE |
+                       IORING_SETUP_CLAMP))
                return -EINVAL;
 
        ret = io_uring_create(entries, &p);
index 8ad3cece54408f9a63633bcaaf323db614b2b370..29fae13395a8123c868eb8fb57011707e1a6e017 100644 (file)
@@ -61,6 +61,7 @@ struct io_uring_sqe {
 #define IORING_SETUP_SQPOLL    (1U << 1)       /* SQ poll thread */
 #define IORING_SETUP_SQ_AFF    (1U << 2)       /* sq_thread_cpu is valid */
 #define IORING_SETUP_CQSIZE    (1U << 3)       /* app defines CQ size */
+#define IORING_SETUP_CLAMP     (1U << 4)       /* clamp SQ/CQ ring sizes */
 
 enum {
        IORING_OP_NOP,