]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
9p: Use kvmalloc for message buffers on supported transports
authorPierre Barre <pierre@barre.sh>
Thu, 16 Oct 2025 13:58:36 +0000 (15:58 +0200)
committerDominique Martinet <asmadeus@codewreck.org>
Mon, 3 Nov 2025 07:41:24 +0000 (16:41 +0900)
While developing a 9P server (https://github.com/Barre/ZeroFS) and
testing it under high-load, I was running into allocation failures.
The failures occur even with plenty of free memory available because
kmalloc requires contiguous physical memory.

This results in errors like:
ls: page allocation failure: order:7, mode:0x40c40(GFP_NOFS|__GFP_COMP)

This patch introduces a transport capability flag (supports_vmalloc)
that indicates whether a transport can work with vmalloc'd buffers
(non-physically contiguous memory). Transports requiring DMA should
leave this flag as false.

The fd-based transports (tcp, unix, fd) set this flag to true, and
p9_fcall_init will use kvmalloc instead of kmalloc for these
transports. This allows the allocator to fall back to vmalloc when
contiguous physical memory is not available.

Additionally, if kmem_cache_alloc fails, the code falls back to
kvmalloc for transports that support it.

Signed-off-by: Pierre Barre <pierre@barre.sh>
Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>
Message-ID: <d2017c29-11fb-44a5-bd0f-4204329bbefb@app.fastmail.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
include/net/9p/transport.h
net/9p/client.c
net/9p/trans_fd.c
net/9p/trans_rdma.c
net/9p/trans_usbg.c
net/9p/trans_virtio.c
net/9p/trans_xen.c

index 766ec07c95999dcc686432b12d480ff86217984e..f0981515148d69abdaf06a2874eaab39f7ee2e94 100644 (file)
@@ -24,6 +24,9 @@
  *                   we're less flexible when choosing the response message
  *                   size in this case
  * @def: set if this transport should be considered the default
+ * @supports_vmalloc: set if this transport can work with vmalloc'd buffers
+ *                    (non-physically contiguous memory). Transports requiring
+ *                    DMA should leave this as false.
  * @create: member function to create a new connection on this transport
  * @close: member function to discard a connection on this transport
  * @request: member function to issue a request to the transport
@@ -44,6 +47,7 @@ struct p9_trans_module {
        int maxsize;            /* max message size of transport */
        bool pooled_rbuffers;
        int def;                /* this transport should be default */
+       bool supports_vmalloc;  /* can work with vmalloc'd buffers */
        struct module *owner;
        int (*create)(struct p9_client *client,
                      const char *devname, char *args);
index 5c1ca57ccd28531edfdcf14fbed2dbf87e60af22..2a4884c880c1f0a16859a8c18c1d80ad4a829d90 100644 (file)
@@ -229,8 +229,15 @@ static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc,
        if (likely(c->fcall_cache) && alloc_msize == c->msize) {
                fc->sdata = kmem_cache_alloc(c->fcall_cache, GFP_NOFS);
                fc->cache = c->fcall_cache;
+               if (!fc->sdata && c->trans_mod->supports_vmalloc) {
+                       fc->sdata = kvmalloc(alloc_msize, GFP_NOFS);
+                       fc->cache = NULL;
+               }
        } else {
-               fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
+               if (c->trans_mod->supports_vmalloc)
+                       fc->sdata = kvmalloc(alloc_msize, GFP_NOFS);
+               else
+                       fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
                fc->cache = NULL;
        }
        if (!fc->sdata)
@@ -252,7 +259,7 @@ void p9_fcall_fini(struct p9_fcall *fc)
        if (fc->cache)
                kmem_cache_free(fc->cache, fc->sdata);
        else
-               kfree(fc->sdata);
+               kvfree(fc->sdata);
 }
 EXPORT_SYMBOL(p9_fcall_fini);
 
index a516745f732f718034281cb5055b3a09cd505d37..e7334033eba5ae41f03fe8fe0fef7f8f35924886 100644 (file)
@@ -1101,6 +1101,7 @@ static struct p9_trans_module p9_tcp_trans = {
        .maxsize = MAX_SOCK_BUF,
        .pooled_rbuffers = false,
        .def = 0,
+       .supports_vmalloc = true,
        .create = p9_fd_create_tcp,
        .close = p9_fd_close,
        .request = p9_fd_request,
@@ -1115,6 +1116,7 @@ static struct p9_trans_module p9_unix_trans = {
        .name = "unix",
        .maxsize = MAX_SOCK_BUF,
        .def = 0,
+       .supports_vmalloc = true,
        .create = p9_fd_create_unix,
        .close = p9_fd_close,
        .request = p9_fd_request,
@@ -1129,6 +1131,7 @@ static struct p9_trans_module p9_fd_trans = {
        .name = "fd",
        .maxsize = MAX_SOCK_BUF,
        .def = 0,
+       .supports_vmalloc = true,
        .create = p9_fd_create,
        .close = p9_fd_close,
        .request = p9_fd_request,
index b84748baf9cbe3dc38a816daeeeefb3d7157ae13..6c5ad232c19463ff42c611f5e409555381911c39 100644 (file)
@@ -749,6 +749,7 @@ static struct p9_trans_module p9_rdma_trans = {
        .maxsize = P9_RDMA_MAXSIZE,
        .pooled_rbuffers = true,
        .def = 0,
+       .supports_vmalloc = false,
        .owner = THIS_MODULE,
        .create = rdma_create_trans,
        .close = rdma_close,
index 468f7e8f0277b9ae5f1bb3c94c649fca97d28857..2542ef09923339b22c37f3e9e5518ac37305a240 100644 (file)
@@ -514,6 +514,7 @@ static struct p9_trans_module p9_usbg_trans = {
        .close = p9_usbg_close,
        .request = p9_usbg_request,
        .cancel = p9_usbg_cancel,
+       .supports_vmalloc = false,
        .owner = THIS_MODULE,
 };
 
index 0b8086f58ad55a92efa253ed372f99c60113f971..12806207f4f03c5b291db938842d78f5146dc0b7 100644 (file)
@@ -803,6 +803,7 @@ static struct p9_trans_module p9_virtio_trans = {
        .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3),
        .pooled_rbuffers = false,
        .def = 1,
+       .supports_vmalloc = false,
        .owner = THIS_MODULE,
 };
 
index b9ff69c7522a19c53906b0dc0cfa0998a9063826..4b1cec0ab82977e366dfa6673a71b5a90cb2cd45 100644 (file)
@@ -258,6 +258,7 @@ static struct p9_trans_module p9_xen_trans = {
        .maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT - 2),
        .pooled_rbuffers = false,
        .def = 1,
+       .supports_vmalloc = false,
        .create = p9_xen_create,
        .close = p9_xen_close,
        .request = p9_xen_request,