Skip to content

Commit 9063e21

Browse files
edumazetdavem330
authored andcommitted
netlink: autosize skb lengthes
One known problem with netlink is the fact that NLMSG_GOODSIZE is really small on PAGE_SIZE==4096 architectures, and it is difficult to know in advance what buffer size is used by the application. This patch adds an automatic learning of the size. First netlink message will still be limited to ~4K, but if user used bigger buffers, then following messages will be able to use up to 16KB. This speedups dump() operations by a large factor and should be safe for legacy applications. Signed-off-by: Eric Dumazet <[email protected]> Cc: Thomas Graf <[email protected]> Acked-by: Thomas Graf <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent cd84ff4 commit 9063e21

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

net/netlink/af_netlink.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2343,6 +2343,11 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
23432343
}
23442344
#endif
23452345

2346+
/* Record the max length of recvmsg() calls for future allocations */
2347+
nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len);
2348+
nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len,
2349+
16384);
2350+
23462351
copied = data_skb->len;
23472352
if (len < copied) {
23482353
msg->msg_flags |= MSG_TRUNC;
@@ -2587,7 +2592,27 @@ static int netlink_dump(struct sock *sk)
25872592
if (!netlink_rx_is_mmaped(sk) &&
25882593
atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
25892594
goto errout_skb;
2590-
skb = netlink_alloc_skb(sk, alloc_size, nlk->portid, GFP_KERNEL);
2595+
2596+
/* NLMSG_GOODSIZE is small to avoid high order allocations being
2597+
* required, but it makes sense to _attempt_ a 16K bytes allocation
2598+
* to reduce number of system calls on dump operations, if user
2599+
* ever provided a big enough buffer.
2600+
*/
2601+
if (alloc_size < nlk->max_recvmsg_len) {
2602+
skb = netlink_alloc_skb(sk,
2603+
nlk->max_recvmsg_len,
2604+
nlk->portid,
2605+
GFP_KERNEL |
2606+
__GFP_NOWARN |
2607+
__GFP_NORETRY);
2608+
/* available room should be exact amount to avoid MSG_TRUNC */
2609+
if (skb)
2610+
skb_reserve(skb, skb_tailroom(skb) -
2611+
nlk->max_recvmsg_len);
2612+
}
2613+
if (!skb)
2614+
skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
2615+
GFP_KERNEL);
25912616
if (!skb)
25922617
goto errout_skb;
25932618
netlink_skb_set_owner_r(skb, sk);

net/netlink/af_netlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct netlink_sock {
3131
u32 ngroups;
3232
unsigned long *groups;
3333
unsigned long state;
34+
size_t max_recvmsg_len;
3435
wait_queue_head_t wait;
3536
bool cb_running;
3637
struct netlink_callback cb;

0 commit comments

Comments
 (0)