Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

9p: Use kvmalloc for message buffers on supported transports

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>

authored by

Pierre Barre and committed by
Dominique Martinet
e21d451a 43c36a56

+20 -2
+4
include/net/9p/transport.h
··· 24 24 * we're less flexible when choosing the response message 25 25 * size in this case 26 26 * @def: set if this transport should be considered the default 27 + * @supports_vmalloc: set if this transport can work with vmalloc'd buffers 28 + * (non-physically contiguous memory). Transports requiring 29 + * DMA should leave this as false. 27 30 * @create: member function to create a new connection on this transport 28 31 * @close: member function to discard a connection on this transport 29 32 * @request: member function to issue a request to the transport ··· 47 44 int maxsize; /* max message size of transport */ 48 45 bool pooled_rbuffers; 49 46 int def; /* this transport should be default */ 47 + bool supports_vmalloc; /* can work with vmalloc'd buffers */ 50 48 struct module *owner; 51 49 int (*create)(struct p9_client *client, 52 50 const char *devname, char *args);
+9 -2
net/9p/client.c
··· 229 229 if (likely(c->fcall_cache) && alloc_msize == c->msize) { 230 230 fc->sdata = kmem_cache_alloc(c->fcall_cache, GFP_NOFS); 231 231 fc->cache = c->fcall_cache; 232 + if (!fc->sdata && c->trans_mod->supports_vmalloc) { 233 + fc->sdata = kvmalloc(alloc_msize, GFP_NOFS); 234 + fc->cache = NULL; 235 + } 232 236 } else { 233 - fc->sdata = kmalloc(alloc_msize, GFP_NOFS); 237 + if (c->trans_mod->supports_vmalloc) 238 + fc->sdata = kvmalloc(alloc_msize, GFP_NOFS); 239 + else 240 + fc->sdata = kmalloc(alloc_msize, GFP_NOFS); 234 241 fc->cache = NULL; 235 242 } 236 243 if (!fc->sdata) ··· 259 252 if (fc->cache) 260 253 kmem_cache_free(fc->cache, fc->sdata); 261 254 else 262 - kfree(fc->sdata); 255 + kvfree(fc->sdata); 263 256 } 264 257 EXPORT_SYMBOL(p9_fcall_fini); 265 258
+3
net/9p/trans_fd.c
··· 1101 1101 .maxsize = MAX_SOCK_BUF, 1102 1102 .pooled_rbuffers = false, 1103 1103 .def = 0, 1104 + .supports_vmalloc = true, 1104 1105 .create = p9_fd_create_tcp, 1105 1106 .close = p9_fd_close, 1106 1107 .request = p9_fd_request, ··· 1116 1115 .name = "unix", 1117 1116 .maxsize = MAX_SOCK_BUF, 1118 1117 .def = 0, 1118 + .supports_vmalloc = true, 1119 1119 .create = p9_fd_create_unix, 1120 1120 .close = p9_fd_close, 1121 1121 .request = p9_fd_request, ··· 1131 1129 .name = "fd", 1132 1130 .maxsize = MAX_SOCK_BUF, 1133 1131 .def = 0, 1132 + .supports_vmalloc = true, 1134 1133 .create = p9_fd_create, 1135 1134 .close = p9_fd_close, 1136 1135 .request = p9_fd_request,
+1
net/9p/trans_rdma.c
··· 749 749 .maxsize = P9_RDMA_MAXSIZE, 750 750 .pooled_rbuffers = true, 751 751 .def = 0, 752 + .supports_vmalloc = false, 752 753 .owner = THIS_MODULE, 753 754 .create = rdma_create_trans, 754 755 .close = rdma_close,
+1
net/9p/trans_usbg.c
··· 514 514 .close = p9_usbg_close, 515 515 .request = p9_usbg_request, 516 516 .cancel = p9_usbg_cancel, 517 + .supports_vmalloc = false, 517 518 .owner = THIS_MODULE, 518 519 }; 519 520
+1
net/9p/trans_virtio.c
··· 803 803 .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3), 804 804 .pooled_rbuffers = false, 805 805 .def = 1, 806 + .supports_vmalloc = false, 806 807 .owner = THIS_MODULE, 807 808 }; 808 809
+1
net/9p/trans_xen.c
··· 258 258 .maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT - 2), 259 259 .pooled_rbuffers = false, 260 260 .def = 1, 261 + .supports_vmalloc = false, 261 262 .create = p9_xen_create, 262 263 .close = p9_xen_close, 263 264 .request = p9_xen_request,