Commit d3fc6b3f authored by David S. Miller's avatar David S. Miller
Browse files


More work from Al Viro to move away from modifying iovecs
by using iov_iter instead.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents aa99c479 083735f4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
			goto unlock;
	}

	err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
	err = memcpy_to_msg(msg, ctx->result, len);

unlock:
	release_sock(sk);
+5 −5
Original line number Diff line number Diff line
@@ -298,9 +298,9 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
			len = min_t(unsigned long, len,
				    PAGE_SIZE - sg->offset - sg->length);

			err = memcpy_fromiovec(page_address(sg_page(sg)) +
			err = memcpy_from_msg(page_address(sg_page(sg)) +
					      sg->offset + sg->length,
					       msg->msg_iov, len);
					      msg, len);
			if (err)
				goto unlock;

@@ -337,8 +337,8 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
			if (!sg_page(sg + i))
				goto unlock;

			err = memcpy_fromiovec(page_address(sg_page(sg + i)),
					       msg->msg_iov, plen);
			err = memcpy_from_msg(page_address(sg_page(sg + i)),
					      msg, plen);
			if (err) {
				__free_page(sg_page(sg + i));
				sg_assign_page(sg + i, NULL);
+1 −1
Original line number Diff line number Diff line
@@ -203,7 +203,7 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
	if (!skb)
		goto done;

	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
		err = -EFAULT;
		goto done;
	}
+48 −57
Original line number Diff line number Diff line
@@ -640,12 +640,12 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,

/* Get packet from user space buffer */
static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
				const struct iovec *iv, unsigned long total_len,
				size_t count, int noblock)
				struct iov_iter *from, int noblock)
{
	int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN);
	struct sk_buff *skb;
	struct macvlan_dev *vlan;
	unsigned long total_len = iov_iter_count(from);
	unsigned long len = total_len;
	int err;
	struct virtio_net_hdr vnet_hdr = { 0 };
@@ -653,6 +653,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
	int copylen = 0;
	bool zerocopy = false;
	size_t linear;
	ssize_t n;

	if (q->flags & IFF_VNET_HDR) {
		vnet_hdr_len = q->vnet_hdr_sz;
@@ -662,10 +663,11 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
			goto err;
		len -= vnet_hdr_len;

		err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0,
					   sizeof(vnet_hdr));
		if (err < 0)
		err = -EFAULT;
		n = copy_from_iter(&vnet_hdr, sizeof(vnet_hdr), from);
		if (n != sizeof(vnet_hdr))
			goto err;
		iov_iter_advance(from, vnet_hdr_len - sizeof(vnet_hdr));
		if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
		     vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 >
							vnet_hdr.hdr_len)
@@ -680,17 +682,16 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
	if (unlikely(len < ETH_HLEN))
		goto err;

	err = -EMSGSIZE;
	if (unlikely(count > UIO_MAXIOV))
		goto err;

	if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) {
		struct iov_iter i;

		copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN;
		if (copylen > good_linear)
			copylen = good_linear;
		linear = copylen;
		if (iov_pages(iv, vnet_hdr_len + copylen, count)
		    <= MAX_SKB_FRAGS)
		i = *from;
		iov_iter_advance(&i, copylen);
		if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS)
			zerocopy = true;
	}

@@ -708,10 +709,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
		goto err;

	if (zerocopy)
		err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
		err = zerocopy_sg_from_iter(skb, from);
	else {
		err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
						   len);
		err = skb_copy_datagram_from_iter(skb, 0, from, len);
		if (!err && m && m->msg_control) {
			struct ubuf_info *uarg = m->msg_control;
			uarg->callback(uarg, false);
@@ -764,16 +764,12 @@ err:
	return err;
}

static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv,
				 unsigned long count, loff_t pos)
static ssize_t macvtap_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
	struct file *file = iocb->ki_filp;
	ssize_t result = -ENOLINK;
	struct macvtap_queue *q = file->private_data;

	result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count,
				  file->f_flags & O_NONBLOCK);
	return result;
	return macvtap_get_user(q, NULL, from, file->f_flags & O_NONBLOCK);
}

/* Put packet to the user space buffer */
@@ -831,23 +827,25 @@ done:
}

static ssize_t macvtap_do_read(struct macvtap_queue *q,
			       const struct iovec *iv, unsigned long segs,
			       unsigned long len,
			       struct iov_iter *to,
			       int noblock)
{
	DEFINE_WAIT(wait);
	struct sk_buff *skb;
	ssize_t ret = 0;
	struct iov_iter iter;

	while (len) {
	if (!iov_iter_count(to))
		return 0;

	while (1) {
		if (!noblock)
			prepare_to_wait(sk_sleep(&q->sk), &wait,
					TASK_INTERRUPTIBLE);

		/* Read frames from the queue */
		skb = skb_dequeue(&q->sk.sk_receive_queue);
		if (!skb) {
		if (skb)
			break;
		if (noblock) {
			ret = -EAGAIN;
			break;
@@ -858,37 +856,26 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q,
		}
		/* Nothing to read, let's sleep */
		schedule();
			continue;
	}
		iov_iter_init(&iter, READ, iv, segs, len);
		ret = macvtap_put_user(q, skb, &iter);
	if (skb) {
		ret = macvtap_put_user(q, skb, to);
		kfree_skb(skb);
		break;
	}

	if (!noblock)
		finish_wait(sk_sleep(&q->sk), &wait);
	return ret;
}

static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv,
				unsigned long count, loff_t pos)
static ssize_t macvtap_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
	struct file *file = iocb->ki_filp;
	struct macvtap_queue *q = file->private_data;
	ssize_t len, ret = 0;

	len = iov_length(iv, count);
	if (len < 0) {
		ret = -EINVAL;
		goto out;
	}
	ssize_t len = iov_iter_count(to), ret;

	ret = macvtap_do_read(q, iv, count, len, file->f_flags & O_NONBLOCK);
	ret = macvtap_do_read(q, to, file->f_flags & O_NONBLOCK);
	ret = min_t(ssize_t, ret, len);
	if (ret > 0)
		iocb->ki_pos = ret;
out:
	return ret;
}

@@ -1089,8 +1076,10 @@ static const struct file_operations macvtap_fops = {
	.owner		= THIS_MODULE,
	.open		= macvtap_open,
	.release	= macvtap_release,
	.aio_read	= macvtap_aio_read,
	.aio_write	= macvtap_aio_write,
	.read		= new_sync_read,
	.write		= new_sync_write,
	.read_iter	= macvtap_read_iter,
	.write_iter	= macvtap_write_iter,
	.poll		= macvtap_poll,
	.llseek		= no_llseek,
	.unlocked_ioctl	= macvtap_ioctl,
@@ -1103,8 +1092,9 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
			   struct msghdr *m, size_t total_len)
{
	struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
	return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen,
			    m->msg_flags & MSG_DONTWAIT);
	struct iov_iter from;
	iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len);
	return macvtap_get_user(q, m, &from, m->msg_flags & MSG_DONTWAIT);
}

static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,
@@ -1112,11 +1102,12 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,
			   int flags)
{
	struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
	struct iov_iter to;
	int ret;
	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
		return -EINVAL;
	ret = macvtap_do_read(q, m->msg_iov, m->msg_iovlen, total_len,
			  flags & MSG_DONTWAIT);
	iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len);
	ret = macvtap_do_read(q, &to, flags & MSG_DONTWAIT);
	if (ret > total_len) {
		m->msg_flags |= MSG_TRUNC;
		ret = flags & MSG_TRUNC ? ret : total_len;
+1 −1
Original line number Diff line number Diff line
@@ -869,7 +869,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
	ph = (struct pppoe_hdr *)skb_put(skb, total_len + sizeof(struct pppoe_hdr));
	start = (char *)&ph->tag[0];

	error = memcpy_fromiovec(start, m->msg_iov, total_len);
	error = memcpy_from_msg(start, m, total_len);
	if (error < 0) {
		kfree_skb(skb);
		goto end;
Loading