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

Commit 8feb2fb2 authored by Al Viro's avatar Al Viro
Browse files

switch AF_PACKET and AF_UNIX to skb_copy_datagram_from_iter()



... and kill skb_copy_datagram_iovec()

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 195e952d
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -2656,9 +2656,6 @@ static inline int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
{
	return skb_copy_and_csum_datagram_iovec(skb, hlen, msg->msg_iov);
}
int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
				 const struct iovec *from, int from_offset,
				 int len);
int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset,
				 struct iov_iter *from, int len);
int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
+2 −86
Original line number Diff line number Diff line
@@ -480,98 +480,14 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
EXPORT_SYMBOL(skb_copy_datagram_iter);

/**
 *	skb_copy_datagram_from_iovec - Copy a datagram from an iovec.
 *	skb_copy_datagram_from_iter - Copy a datagram from an iov_iter.
 *	@skb: buffer to copy
 *	@offset: offset in the buffer to start copying to
 *	@from: io vector to copy to
 *	@from_offset: offset in the io vector to start copying from
 *	@from: the copy source
 *	@len: amount of data to copy to buffer from iovec
 *
 *	Returns 0 or -EFAULT.
 *	Note: the iovec is not modified during the copy.
 */
int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
				 const struct iovec *from, int from_offset,
				 int len)
{
	int start = skb_headlen(skb);
	int i, copy = start - offset;
	struct sk_buff *frag_iter;

	/* Copy header. */
	if (copy > 0) {
		if (copy > len)
			copy = len;
		if (memcpy_fromiovecend(skb->data + offset, from, from_offset,
					copy))
			goto fault;
		if ((len -= copy) == 0)
			return 0;
		offset += copy;
		from_offset += copy;
	}

	/* Copy paged appendix. Hmm... why does this look so complicated? */
	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
		int end;
		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];

		WARN_ON(start > offset + len);

		end = start + skb_frag_size(frag);
		if ((copy = end - offset) > 0) {
			int err;
			u8  *vaddr;
			struct page *page = skb_frag_page(frag);

			if (copy > len)
				copy = len;
			vaddr = kmap(page);
			err = memcpy_fromiovecend(vaddr + frag->page_offset +
						  offset - start,
						  from, from_offset, copy);
			kunmap(page);
			if (err)
				goto fault;

			if (!(len -= copy))
				return 0;
			offset += copy;
			from_offset += copy;
		}
		start = end;
	}

	skb_walk_frags(skb, frag_iter) {
		int end;

		WARN_ON(start > offset + len);

		end = start + frag_iter->len;
		if ((copy = end - offset) > 0) {
			if (copy > len)
				copy = len;
			if (skb_copy_datagram_from_iovec(frag_iter,
							 offset - start,
							 from,
							 from_offset,
							 copy))
				goto fault;
			if ((len -= copy) == 0)
				return 0;
			offset += copy;
			from_offset += copy;
		}
		start = end;
	}
	if (!len)
		return 0;

fault:
	return -EFAULT;
}
EXPORT_SYMBOL(skb_copy_datagram_from_iovec);

int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset,
				 struct iov_iter *from,
				 int len)
+8 −3
Original line number Diff line number Diff line
@@ -2408,6 +2408,10 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
	unsigned short gso_type = 0;
	int hlen, tlen;
	int extra_len = 0;
	struct iov_iter from;
	ssize_t n;

	iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);

	/*
	 *	Get and verify the address.
@@ -2446,8 +2450,9 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)

		len -= vnet_hdr_len;

		err = memcpy_from_msg((void *)&vnet_hdr, msg, vnet_hdr_len);
		if (err < 0)
		err = -EFAULT;
		n = copy_from_iter(&vnet_hdr, vnet_hdr_len, &from);
		if (n != vnet_hdr_len)
			goto out_unlock;

		if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
@@ -2517,7 +2522,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
	}

	/* Returns -EFAULT on error */
	err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len);
	err = skb_copy_datagram_from_iter(skb, offset, &from, len);
	if (err)
		goto out_free;

+8 −3
Original line number Diff line number Diff line
@@ -1459,6 +1459,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
	struct scm_cookie tmp_scm;
	int max_level;
	int data_len = 0;
	struct iov_iter from;

	iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);

	if (NULL == siocb->scm)
		siocb->scm = &tmp_scm;
@@ -1516,7 +1519,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
	skb_put(skb, len - data_len);
	skb->data_len = data_len;
	skb->len = len;
	err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len);
	err = skb_copy_datagram_from_iter(skb, 0, &from, len);
	if (err)
		goto out_free;

@@ -1638,6 +1641,9 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
	bool fds_sent = false;
	int max_level;
	int data_len;
	struct iov_iter from;

	iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);

	if (NULL == siocb->scm)
		siocb->scm = &tmp_scm;
@@ -1694,8 +1700,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
		skb_put(skb, size - data_len);
		skb->data_len = data_len;
		skb->len = size;
		err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov,
						   sent, size);
		err = skb_copy_datagram_from_iter(skb, 0, &from, size);
		if (err) {
			kfree_skb(skb);
			goto out_err;