|
@@ -2343,6 +2343,11 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+ /* Record the max length of recvmsg() calls for future allocations */
|
|
|
|
+ nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len);
|
|
|
|
+ nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len,
|
|
|
|
+ 16384);
|
|
|
|
+
|
|
copied = data_skb->len;
|
|
copied = data_skb->len;
|
|
if (len < copied) {
|
|
if (len < copied) {
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
@@ -2587,7 +2592,27 @@ static int netlink_dump(struct sock *sk)
|
|
if (!netlink_rx_is_mmaped(sk) &&
|
|
if (!netlink_rx_is_mmaped(sk) &&
|
|
atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
|
|
atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
|
|
goto errout_skb;
|
|
goto errout_skb;
|
|
- skb = netlink_alloc_skb(sk, alloc_size, nlk->portid, GFP_KERNEL);
|
|
|
|
|
|
+
|
|
|
|
+ /* NLMSG_GOODSIZE is small to avoid high order allocations being
|
|
|
|
+ * required, but it makes sense to _attempt_ a 16K bytes allocation
|
|
|
|
+ * to reduce number of system calls on dump operations, if user
|
|
|
|
+ * ever provided a big enough buffer.
|
|
|
|
+ */
|
|
|
|
+ if (alloc_size < nlk->max_recvmsg_len) {
|
|
|
|
+ skb = netlink_alloc_skb(sk,
|
|
|
|
+ nlk->max_recvmsg_len,
|
|
|
|
+ nlk->portid,
|
|
|
|
+ GFP_KERNEL |
|
|
|
|
+ __GFP_NOWARN |
|
|
|
|
+ __GFP_NORETRY);
|
|
|
|
+ /* available room should be exact amount to avoid MSG_TRUNC */
|
|
|
|
+ if (skb)
|
|
|
|
+ skb_reserve(skb, skb_tailroom(skb) -
|
|
|
|
+ nlk->max_recvmsg_len);
|
|
|
|
+ }
|
|
|
|
+ if (!skb)
|
|
|
|
+ skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
|
|
|
|
+ GFP_KERNEL);
|
|
if (!skb)
|
|
if (!skb)
|
|
goto errout_skb;
|
|
goto errout_skb;
|
|
netlink_skb_set_owner_r(skb, sk);
|
|
netlink_skb_set_owner_r(skb, sk);
|