aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2014-03-07 15:02:33 -0500
committerDavid S. Miller <davem@davemloft.net>2014-03-10 13:56:26 -0400
commit9063e21fb026c4966fc93261c18322214f9835eb (patch)
treec63b6774f68574b9197fb083af77029d9d4e52c6 /net/netlink
parentcd84ff4da1f46cbdc2d73366eabe9a8f818447cd (diff)
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 <edumazet@google.com> Cc: Thomas Graf <tgraf@suug.ch> Acked-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/af_netlink.c27
-rw-r--r--net/netlink/af_netlink.h1
2 files changed, 27 insertions, 1 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 9db8bab27fa2..c2d585c4f7c5 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2343,6 +2343,11 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
2343 } 2343 }
2344#endif 2344#endif
2345 2345
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
2346 copied = data_skb->len; 2351 copied = data_skb->len;
2347 if (len < copied) { 2352 if (len < copied) {
2348 msg->msg_flags |= MSG_TRUNC; 2353 msg->msg_flags |= MSG_TRUNC;
@@ -2587,7 +2592,27 @@ static int netlink_dump(struct sock *sk)
2587 if (!netlink_rx_is_mmaped(sk) && 2592 if (!netlink_rx_is_mmaped(sk) &&
2588 atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) 2593 atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
2589 goto errout_skb; 2594 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);
2591 if (!skb) 2616 if (!skb)
2592 goto errout_skb; 2617 goto errout_skb;
2593 netlink_skb_set_owner_r(skb, sk); 2618 netlink_skb_set_owner_r(skb, sk);
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index acbd774eeb7c..ed13a790b00e 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -31,6 +31,7 @@ struct netlink_sock {
31 u32 ngroups; 31 u32 ngroups;
32 unsigned long *groups; 32 unsigned long *groups;
33 unsigned long state; 33 unsigned long state;
34 size_t max_recvmsg_len;
34 wait_queue_head_t wait; 35 wait_queue_head_t wait;
35 bool cb_running; 36 bool cb_running;
36 struct netlink_callback cb; 37 struct netlink_callback cb;