aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-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;