io_uring/memmap: reuse io_free_region for failure path
authorPavel Begunkov <asml.silence@gmail.com>
Fri, 29 Nov 2024 13:34:27 +0000 (13:34 +0000)
committerJens Axboe <axboe@kernel.dk>
Mon, 23 Dec 2024 15:17:15 +0000 (08:17 -0700)
Regions are going to become more complex with allocation options and
optimisations, I want to split initialisation into steps and for that it
needs a sane fail path. Reuse io_free_region(), it's smart enough to
undo only what's needed and leaves the structure in a consistent state.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/b853b4ec407cc80d033d021bdd2c14e22378fc78.1732886067.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/memmap.c

index fca93bc4c6f13196f0f5337acd431764dc067363..96c4f6b6117171f82711ab6dfda642c24f612406 100644 (file)
@@ -229,7 +229,6 @@ void io_free_region(struct io_ring_ctx *ctx, struct io_mapped_region *mr)
 int io_create_region(struct io_ring_ctx *ctx, struct io_mapped_region *mr,
                     struct io_uring_region_desc *reg)
 {
-       int pages_accounted = 0;
        struct page **pages;
        int nr_pages, ret;
        void *vptr;
@@ -257,32 +256,27 @@ int io_create_region(struct io_ring_ctx *ctx, struct io_mapped_region *mr,
                ret = __io_account_mem(ctx->user, nr_pages);
                if (ret)
                        return ret;
-               pages_accounted = nr_pages;
        }
+       mr->nr_pages = nr_pages;
 
        pages = io_pin_pages(reg->user_addr, reg->size, &nr_pages);
        if (IS_ERR(pages)) {
                ret = PTR_ERR(pages);
-               pages = NULL;
                goto out_free;
        }
+       mr->pages = pages;
+       mr->flags |= IO_REGION_F_USER_PROVIDED;
 
        vptr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
        if (!vptr) {
                ret = -ENOMEM;
                goto out_free;
        }
-
-       mr->pages = pages;
        mr->ptr = vptr;
-       mr->nr_pages = nr_pages;
-       mr->flags |= IO_REGION_F_VMAP | IO_REGION_F_USER_PROVIDED;
+       mr->flags |= IO_REGION_F_VMAP;
        return 0;
 out_free:
-       if (pages_accounted)
-               __io_unaccount_mem(ctx->user, pages_accounted);
-       if (pages)
-               io_pages_free(&pages, nr_pages);
+       io_free_region(ctx, mr);
        return ret;
 }