Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc5367bc authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller
Browse files

net/af_iucv: don't use paged skbs for TX on HiperSockets



With commit e5374399
("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: default avatarJulian Wiedmann <jwi@linux.vnet.ibm.com>
Signed-off-by: default avatarUrsula Braun <ubraun@linux.vnet.ibm.com>
Cc: <stable@vger.kernel.org> # v4.8+
Fixes: e5374399 ("af_iucv: use paged SKBs for big outbound messages")
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5d722b30
Loading
Loading
Loading
Loading
+14 −11
Original line number Diff line number Diff line
@@ -1044,7 +1044,8 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg,
{
	struct sock *sk = sock->sk;
	struct iucv_sock *iucv = iucv_sk(sk);
	size_t headroom, linear;
	size_t headroom = 0;
	size_t linear;
	struct sk_buff *skb;
	struct iucv_message txmsg = {0};
	struct cmsghdr *cmsg;
@@ -1122,19 +1123,21 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg,
	 * this is fine for SOCK_SEQPACKET (unless we want to support
	 * segmented records using the MSG_EOR flag), but
	 * for SOCK_STREAM we might want to improve it in future */
	headroom = (iucv->transport == AF_IUCV_TRANS_HIPER)
		   ? sizeof(struct af_iucv_trans_hdr) + ETH_HLEN : 0;
	if (headroom + len < PAGE_SIZE) {
	if (iucv->transport == AF_IUCV_TRANS_HIPER) {
		headroom = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
		linear = len;
	} else {
		if (len < PAGE_SIZE) {
			linear = len;
		} else {
			/* In nonlinear "classic" iucv skb,
			 * reserve space for iucv_array
			 */
		if (iucv->transport != AF_IUCV_TRANS_HIPER)
			headroom += sizeof(struct iucv_array) *
			headroom = sizeof(struct iucv_array) *
				   (MAX_SKB_FRAGS + 1);
			linear = PAGE_SIZE - headroom;
		}
	}
	skb = sock_alloc_send_pskb(sk, headroom + linear, len - linear,
				   noblock, &err, 0);
	if (!skb)