| From foo@baz Thu Dec 21 09:02:40 CET 2017 |
| From: Peng Tao <bergwolf@gmail.com> |
| Date: Wed, 15 Mar 2017 09:32:15 +0800 |
| Subject: vhost-vsock: add pkt cancel capability |
| |
| From: Peng Tao <bergwolf@gmail.com> |
| |
| |
| [ Upstream commit 16320f363ae128d9b9c70e60f00f2a572f57c23d ] |
| |
| To allow canceling all packets of a connection. |
| |
| Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> |
| Reviewed-by: Jorgen Hansen <jhansen@vmware.com> |
| Signed-off-by: Peng Tao <bergwolf@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/vhost/vsock.c | 41 +++++++++++++++++++++++++++++++++++++++++ |
| include/net/af_vsock.h | 3 +++ |
| 2 files changed, 44 insertions(+) |
| |
| --- a/drivers/vhost/vsock.c |
| +++ b/drivers/vhost/vsock.c |
| @@ -218,6 +218,46 @@ vhost_transport_send_pkt(struct virtio_v |
| return len; |
| } |
| |
| +static int |
| +vhost_transport_cancel_pkt(struct vsock_sock *vsk) |
| +{ |
| + struct vhost_vsock *vsock; |
| + struct virtio_vsock_pkt *pkt, *n; |
| + int cnt = 0; |
| + LIST_HEAD(freeme); |
| + |
| + /* Find the vhost_vsock according to guest context id */ |
| + vsock = vhost_vsock_get(vsk->remote_addr.svm_cid); |
| + if (!vsock) |
| + return -ENODEV; |
| + |
| + spin_lock_bh(&vsock->send_pkt_list_lock); |
| + list_for_each_entry_safe(pkt, n, &vsock->send_pkt_list, list) { |
| + if (pkt->vsk != vsk) |
| + continue; |
| + list_move(&pkt->list, &freeme); |
| + } |
| + spin_unlock_bh(&vsock->send_pkt_list_lock); |
| + |
| + list_for_each_entry_safe(pkt, n, &freeme, list) { |
| + if (pkt->reply) |
| + cnt++; |
| + list_del(&pkt->list); |
| + virtio_transport_free_pkt(pkt); |
| + } |
| + |
| + if (cnt) { |
| + struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX]; |
| + int new_cnt; |
| + |
| + new_cnt = atomic_sub_return(cnt, &vsock->queued_replies); |
| + if (new_cnt + cnt >= tx_vq->num && new_cnt < tx_vq->num) |
| + vhost_poll_queue(&tx_vq->poll); |
| + } |
| + |
| + return 0; |
| +} |
| + |
| static struct virtio_vsock_pkt * |
| vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq, |
| unsigned int out, unsigned int in) |
| @@ -669,6 +709,7 @@ static struct virtio_transport vhost_tra |
| .release = virtio_transport_release, |
| .connect = virtio_transport_connect, |
| .shutdown = virtio_transport_shutdown, |
| + .cancel_pkt = vhost_transport_cancel_pkt, |
| |
| .dgram_enqueue = virtio_transport_dgram_enqueue, |
| .dgram_dequeue = virtio_transport_dgram_dequeue, |
| --- a/include/net/af_vsock.h |
| +++ b/include/net/af_vsock.h |
| @@ -100,6 +100,9 @@ struct vsock_transport { |
| void (*destruct)(struct vsock_sock *); |
| void (*release)(struct vsock_sock *); |
| |
| + /* Cancel all pending packets sent on vsock. */ |
| + int (*cancel_pkt)(struct vsock_sock *vsk); |
| + |
| /* Connections. */ |
| int (*connect)(struct vsock_sock *); |
| |