Commit a786ab36 authored by Matias Ezequiel Vara Larsen's avatar Matias Ezequiel Vara Larsen Committed by David S. Miller
Browse files

vsock/virtio: add support for MSG_PEEK



This patch adds support for MSG_PEEK. In such a case, packets are not
removed from the rx_queue and credit updates are not sent.

Signed-off-by: default avatarMatias Ezequiel Vara Larsen <matiasevara@gmail.com>
Reviewed-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Tested-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 67879919
Loading
Loading
Loading
Loading
+52 −3
Original line number Diff line number Diff line
@@ -263,6 +263,55 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk,
	return virtio_transport_send_pkt_info(vsk, &info);
}

static ssize_t
virtio_transport_stream_do_peek(struct vsock_sock *vsk,
				struct msghdr *msg,
				size_t len)
{
	struct virtio_vsock_sock *vvs = vsk->trans;
	struct virtio_vsock_pkt *pkt;
	size_t bytes, total = 0, off;
	int err = -EFAULT;

	spin_lock_bh(&vvs->rx_lock);

	list_for_each_entry(pkt, &vvs->rx_queue, list) {
		off = pkt->off;

		if (total == len)
			break;

		while (total < len && off < pkt->len) {
			bytes = len - total;
			if (bytes > pkt->len - off)
				bytes = pkt->len - off;

			/* sk_lock is held by caller so no one else can dequeue.
			 * Unlock rx_lock since memcpy_to_msg() may sleep.
			 */
			spin_unlock_bh(&vvs->rx_lock);

			err = memcpy_to_msg(msg, pkt->buf + off, bytes);
			if (err)
				goto out;

			spin_lock_bh(&vvs->rx_lock);

			total += bytes;
			off += bytes;
		}
	}

	spin_unlock_bh(&vvs->rx_lock);

	return total;

out:
	if (total)
		err = total;
	return err;
}

static ssize_t
virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
				   struct msghdr *msg,
@@ -335,8 +384,8 @@ virtio_transport_stream_dequeue(struct vsock_sock *vsk,
				size_t len, int flags)
{
	if (flags & MSG_PEEK)
		return -EOPNOTSUPP;

		return virtio_transport_stream_do_peek(vsk, msg, len);
	else
		return virtio_transport_stream_do_dequeue(vsk, msg, len);
}
EXPORT_SYMBOL_GPL(virtio_transport_stream_dequeue);