Message ID | 573F12F5.7050704@sonymobile.com |
---|---|
State | Deferred, archived |
Delegated to: | David Miller |
Headers | show |
It is not appropriate to submit new features at this time as we are in the merge window and we are only bug fixes. Please resubmit this when the net-next tree opens back up.
On Fri, 2016-05-20 at 15:36 +0200, peter enderborg wrote: > From: Peter Enderborg <peter.enderborg@sonymobile.com> > > When sending data the socket allocates memory for > payload on a cache or a page alloc. The page alloc > then might trigger compation that takes long time. > This can be avoided with smaller chunks. But > userspace can not know what is the right size for > the smaller sends. For this we add a SIZEHINT > getsocketopt where the userspace can get the size > for send that will fit into one page (order 0) or > the max for a slab cache allocation. Very obscure thing if you ask me. Exposing kernel internals like that seems to work around a more serious issue. What kind of sockets would ever use KMALLOC_MAX_CACHE_SIZE allocations exactly ? af_unix and tcp are definitely clean. 28d6427109d13b0f447cba5761f88d3548e83605 net: attempt high order allocations in sock_alloc_send_pskb() e370a7236321773245c5522d8bb299380830d3b2 af_unix: improve STREAM behavior with fragmented memory eb6a24816b247c0be6b2e97e68933072874bbe54 af_unix: reduce high order page allocations
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index 67d632f..f6a4921 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -92,4 +92,6 @@ #define SO_CNX_ADVICE 53 +#define SO_SIZEHINT 54 + #endif /* __ASM_GENERIC_SOCKET_H */ diff --git a/include/uapi/linux/socket.h b/include/uapi/linux/socket.h index 76ab0c6..16db7e8 100644 --- a/include/uapi/linux/socket.h +++ b/include/uapi/linux/socket.h @@ -1,6 +1,8 @@ #ifndef _UAPI_LINUX_SOCKET_H #define _UAPI_LINUX_SOCKET_H +#include <linux/types.h> + /* * Desired design of maximum size and alignment (see RFC2553) */ @@ -18,4 +20,11 @@ struct __kernel_sockaddr_storage { /* _SS_MAXSIZE value minus size of ss_family */ } __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */ +struct sock_sizehint { + __u32 order_zero_size; + /* max payload size that can fit into one page in kernel */ + __u32 cache_size; + /* max payload size that can fit in socket slab cache */ +}; + #endif /* _UAPI_LINUX_SOCKET_H */ diff --git a/net/core/sock.c b/net/core/sock.c index 7e73c26..4c9cd92 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1254,6 +1254,23 @@ int sock_getsockopt(struct socket *sock, int level, int optname, v.val = sk->sk_incoming_cpu; break; + case SO_SIZEHINT: + { + struct sock_sizehint hint; + + if (len > sizeof(hint)) + len = sizeof(hint); + + hint.order_zero_size = PAGE_SIZE - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + hint.cache_size = KMALLOC_MAX_CACHE_SIZE - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + if (copy_to_user(optval, &hint, len)) + return -EFAULT; + goto lenout; + } + default: /* We implement the SO_SNDLOWAT etc to not be settable * (1003.1g 7).