diff options
author | Julian Wiedmann <jwi@linux.vnet.ibm.com> | 2017-01-10 11:10:34 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-19 14:18:04 -0500 |
commit | 9297e0c189f59f42e5d39aee901d54a4493a60e2 (patch) | |
tree | 6b08c3f3717b3cc6ccd2bfc52e387699cd731bb7 | |
parent | 00cf64fbaa1e99d0420f2934f301c671ba298342 (diff) |
net/af_iucv: don't use paged skbs for TX on HiperSockets
commit dc5367bcc556e97555fc94a32cd1aadbebdff47e upstream.
With commit e53743994e21
("af_iucv: use paged SKBs for big outbound messages"),
we transmit paged skbs for both of AF_IUCV's transport modes
(IUCV or HiperSockets).
The qeth driver for Layer 3 HiperSockets currently doesn't
support NETIF_F_SG, so these skbs would just be linearized again
by the stack.
Avoid that overhead by using paged skbs only for IUCV transport.
cc stable, since this also circumvents a significant skb leak when
sending large messages (where the skb then needs to be linearized).
Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
Fixes: e53743994e21 ("af_iucv: use paged SKBs for big outbound messages")
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | net/iucv/af_iucv.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 02b45a8e8b35..91cbbf1c3f82 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -1036,7 +1036,8 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1036 | { | 1036 | { |
1037 | struct sock *sk = sock->sk; | 1037 | struct sock *sk = sock->sk; |
1038 | struct iucv_sock *iucv = iucv_sk(sk); | 1038 | struct iucv_sock *iucv = iucv_sk(sk); |
1039 | size_t headroom, linear; | 1039 | size_t headroom = 0; |
1040 | size_t linear; | ||
1040 | struct sk_buff *skb; | 1041 | struct sk_buff *skb; |
1041 | struct iucv_message txmsg = {0}; | 1042 | struct iucv_message txmsg = {0}; |
1042 | struct cmsghdr *cmsg; | 1043 | struct cmsghdr *cmsg; |
@@ -1114,18 +1115,20 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1114 | * this is fine for SOCK_SEQPACKET (unless we want to support | 1115 | * this is fine for SOCK_SEQPACKET (unless we want to support |
1115 | * segmented records using the MSG_EOR flag), but | 1116 | * segmented records using the MSG_EOR flag), but |
1116 | * for SOCK_STREAM we might want to improve it in future */ | 1117 | * for SOCK_STREAM we might want to improve it in future */ |
1117 | headroom = (iucv->transport == AF_IUCV_TRANS_HIPER) | 1118 | if (iucv->transport == AF_IUCV_TRANS_HIPER) { |
1118 | ? sizeof(struct af_iucv_trans_hdr) + ETH_HLEN : 0; | 1119 | headroom = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN; |
1119 | if (headroom + len < PAGE_SIZE) { | ||
1120 | linear = len; | 1120 | linear = len; |
1121 | } else { | 1121 | } else { |
1122 | /* In nonlinear "classic" iucv skb, | 1122 | if (len < PAGE_SIZE) { |
1123 | * reserve space for iucv_array | 1123 | linear = len; |
1124 | */ | 1124 | } else { |
1125 | if (iucv->transport != AF_IUCV_TRANS_HIPER) | 1125 | /* In nonlinear "classic" iucv skb, |
1126 | headroom += sizeof(struct iucv_array) * | 1126 | * reserve space for iucv_array |
1127 | (MAX_SKB_FRAGS + 1); | 1127 | */ |
1128 | linear = PAGE_SIZE - headroom; | 1128 | headroom = sizeof(struct iucv_array) * |
1129 | (MAX_SKB_FRAGS + 1); | ||
1130 | linear = PAGE_SIZE - headroom; | ||
1131 | } | ||
1129 | } | 1132 | } |
1130 | skb = sock_alloc_send_pskb(sk, headroom + linear, len - linear, | 1133 | skb = sock_alloc_send_pskb(sk, headroom + linear, len - linear, |
1131 | noblock, &err, 0); | 1134 | noblock, &err, 0); |