io_uring/rsrc: export io_check_coalesce_buffer
authorPavel Begunkov <asml.silence@gmail.com>
Fri, 29 Nov 2024 13:34:23 +0000 (13:34 +0000)
committerJens Axboe <axboe@kernel.dk>
Mon, 23 Dec 2024 15:17:15 +0000 (08:17 -0700)
io_try_coalesce_buffer() is a useful helper collecting useful info about
a set of pages, I want to reuse it for analysing ring/etc. mappings. I
don't need the entire thing and only interested if it can be coalesced
into a single page, but that's better than duplicating the parsing.

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

index 077f84684c18a0b3f5e622adb4978b6a00353b2f..2d2333970eb5321fd559020433261db3dae23cb8 100644 (file)
@@ -626,11 +626,12 @@ static int io_buffer_account_pin(struct io_ring_ctx *ctx, struct page **pages,
        return ret;
 }
 
-static bool io_do_coalesce_buffer(struct page ***pages, int *nr_pages,
-                               struct io_imu_folio_data *data, int nr_folios)
+static bool io_coalesce_buffer(struct page ***pages, int *nr_pages,
+                               struct io_imu_folio_data *data)
 {
        struct page **page_array = *pages, **new_array = NULL;
        int nr_pages_left = *nr_pages, i, j;
+       int nr_folios = data->nr_folios;
 
        /* Store head pages only*/
        new_array = kvmalloc_array(nr_folios, sizeof(struct page *),
@@ -667,15 +668,14 @@ static bool io_do_coalesce_buffer(struct page ***pages, int *nr_pages,
        return true;
 }
 
-static bool io_try_coalesce_buffer(struct page ***pages, int *nr_pages,
-                                        struct io_imu_folio_data *data)
+bool io_check_coalesce_buffer(struct page **page_array, int nr_pages,
+                             struct io_imu_folio_data *data)
 {
-       struct page **page_array = *pages;
        struct folio *folio = page_folio(page_array[0]);
        unsigned int count = 1, nr_folios = 1;
        int i;
 
-       if (*nr_pages <= 1)
+       if (nr_pages <= 1)
                return false;
 
        data->nr_pages_mid = folio_nr_pages(folio);
@@ -687,7 +687,7 @@ static bool io_try_coalesce_buffer(struct page ***pages, int *nr_pages,
         * Check if pages are contiguous inside a folio, and all folios have
         * the same page count except for the head and tail.
         */
-       for (i = 1; i < *nr_pages; i++) {
+       for (i = 1; i < nr_pages; i++) {
                if (page_folio(page_array[i]) == folio &&
                        page_array[i] == page_array[i-1] + 1) {
                        count++;
@@ -715,7 +715,8 @@ static bool io_try_coalesce_buffer(struct page ***pages, int *nr_pages,
        if (nr_folios == 1)
                data->nr_pages_head = count;
 
-       return io_do_coalesce_buffer(pages, nr_pages, data, nr_folios);
+       data->nr_folios = nr_folios;
+       return true;
 }
 
 static struct io_rsrc_node *io_sqe_buffer_register(struct io_ring_ctx *ctx,
@@ -729,7 +730,7 @@ static struct io_rsrc_node *io_sqe_buffer_register(struct io_ring_ctx *ctx,
        size_t size;
        int ret, nr_pages, i;
        struct io_imu_folio_data data;
-       bool coalesced;
+       bool coalesced = false;
 
        if (!iov->iov_base)
                return NULL;
@@ -749,7 +750,8 @@ static struct io_rsrc_node *io_sqe_buffer_register(struct io_ring_ctx *ctx,
        }
 
        /* If it's huge page(s), try to coalesce them into fewer bvec entries */
-       coalesced = io_try_coalesce_buffer(&pages, &nr_pages, &data);
+       if (io_check_coalesce_buffer(pages, nr_pages, &data))
+               coalesced = io_coalesce_buffer(&pages, &nr_pages, &data);
 
        imu = kvmalloc(struct_size(imu, bvec, nr_pages), GFP_KERNEL);
        if (!imu)
index 7a4668deaa1a9efb3728eaae53bcb8b84792898f..c8b093584461810ce6726c87797a033840b6f3ac 100644 (file)
@@ -40,6 +40,7 @@ struct io_imu_folio_data {
        /* For non-head/tail folios, has to be fully included */
        unsigned int    nr_pages_mid;
        unsigned int    folio_shift;
+       unsigned int    nr_folios;
 };
 
 struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx, int type);
@@ -66,6 +67,9 @@ int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
 int io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg,
                        unsigned int size, unsigned int type);
 
+bool io_check_coalesce_buffer(struct page **page_array, int nr_pages,
+                             struct io_imu_folio_data *data);
+
 static inline struct io_rsrc_node *io_rsrc_node_lookup(struct io_rsrc_data *data,
                                                       int index)
 {