@@ -447,6 +447,7 @@ static struct virtio_transport vhost_transport = {
.stream_rcvhiwat = virtio_transport_stream_rcvhiwat,
.stream_is_active = virtio_transport_stream_is_active,
.stream_allow = virtio_transport_stream_allow,
+ .seqpacket_drop = virtio_transport_seqpacket_drop,
.seqpacket_dequeue = virtio_transport_seqpacket_dequeue,
.seqpacket_enqueue = virtio_transport_seqpacket_enqueue,
@@ -36,6 +36,7 @@ struct virtio_vsock_sock {
u32 rx_bytes;
u32 buf_alloc;
struct list_head rx_queue;
+ bool drop_until_eor;
};
struct virtio_vsock_pkt {
@@ -89,6 +90,7 @@ virtio_transport_seqpacket_dequeue(struct vsock_sock *vsk,
struct msghdr *msg,
int flags,
bool *msg_ready);
+void virtio_transport_seqpacket_drop(struct vsock_sock *vsk);
s64 virtio_transport_stream_has_data(struct vsock_sock *vsk);
s64 virtio_transport_stream_has_space(struct vsock_sock *vsk);
@@ -141,6 +141,7 @@ struct vsock_transport {
int (*seqpacket_enqueue)(struct vsock_sock *vsk, struct msghdr *msg,
size_t len);
bool (*seqpacket_allow)(u32 remote_cid);
+ void (*seqpacket_drop)(struct vsock_sock *vsk);
/* Notification. */
int (*notify_poll_in)(struct vsock_sock *, size_t, bool *);
@@ -2024,6 +2024,7 @@ static int __vsock_seqpacket_recvmsg(struct sock *sk, struct msghdr *msg,
intr_err = vsock_connectible_wait_data(sk, &wait, timeout, NULL, 0);
if (intr_err <= 0) {
err = intr_err;
+ transport->seqpacket_drop(vsk);
break;
}
@@ -475,6 +475,7 @@ static struct virtio_transport virtio_transport = {
.seqpacket_dequeue = virtio_transport_seqpacket_dequeue,
.seqpacket_enqueue = virtio_transport_seqpacket_enqueue,
.seqpacket_allow = virtio_transport_seqpacket_allow,
+ .seqpacket_drop = virtio_transport_seqpacket_drop,
.notify_poll_in = virtio_transport_notify_poll_in,
.notify_poll_out = virtio_transport_notify_poll_out,
@@ -425,7 +425,7 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
pkt = list_first_entry(&vvs->rx_queue, struct virtio_vsock_pkt, list);
pkt_len = (size_t)le32_to_cpu(pkt->hdr.len);
- bytes_to_copy = min(user_buf_len, pkt_len);
+ bytes_to_copy = vvs->drop_until_eor ? 0 : min(user_buf_len, pkt_len);
if (bytes_to_copy) {
int err;
@@ -438,17 +438,22 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
spin_lock_bh(&vvs->rx_lock);
- if (err)
+ if (err) {
dequeued_len = err;
- else
+ vvs->drop_until_eor = true;
+ } else {
user_buf_len -= bytes_to_copy;
+ }
}
if (dequeued_len >= 0)
dequeued_len += pkt_len;
if (le32_to_cpu(pkt->hdr.flags) & VIRTIO_VSOCK_SEQ_EOR) {
- *msg_ready = true;
+ if (vvs->drop_until_eor)
+ vvs->drop_until_eor = false;
+ else
+ *msg_ready = true;
}
virtio_transport_dec_rx_pkt(vvs, pkt);
@@ -487,6 +492,16 @@ virtio_transport_seqpacket_dequeue(struct vsock_sock *vsk,
}
EXPORT_SYMBOL_GPL(virtio_transport_seqpacket_dequeue);
+void virtio_transport_seqpacket_drop(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ spin_lock_bh(&vvs->rx_lock);
+ vvs->drop_until_eor = true;
+ spin_unlock_bh(&vvs->rx_lock);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_seqpacket_drop);
+
int
virtio_transport_seqpacket_enqueue(struct vsock_sock *vsk,
struct msghdr *msg,
@@ -94,6 +94,7 @@ static struct virtio_transport loopback_transport = {
.seqpacket_dequeue = virtio_transport_seqpacket_dequeue,
.seqpacket_enqueue = virtio_transport_seqpacket_enqueue,
.seqpacket_allow = vsock_loopback_seqpacket_allow,
+ .seqpacket_drop = virtio_transport_seqpacket_drop,
.notify_poll_in = virtio_transport_notify_poll_in,
.notify_poll_out = virtio_transport_notify_poll_out,
Add special callback for SEQPACKET socket which is called when we need to drop current in-progress record: part of record was copied successfully, reader wait rest of record, but signal interrupts it and reader leaves it's loop, leaving packets of current record still in queue. So to avoid copy of "orphaned" record, we tell transport to drop every packet until EOR will be found. Signed-off-by: Arseny Krasnov <arseny.krasnov@kaspersky.com> --- drivers/vhost/vsock.c | 1 + include/linux/virtio_vsock.h | 2 ++ include/net/af_vsock.h | 1 + net/vmw_vsock/af_vsock.c | 1 + net/vmw_vsock/virtio_transport.c | 1 + net/vmw_vsock/virtio_transport_common.c | 23 +++++++++++++++++++---- net/vmw_vsock/vsock_loopback.c | 1 + 7 files changed, 26 insertions(+), 4 deletions(-)