Skip to content

Commit 990fa0d

Browse files
stefano-garzarellaopsiff
authored andcommitted
vsock/virtio: cancel close work in the destructor
commit df137da upstream. During virtio_transport_release() we can schedule a delayed work to perform the closing of the socket before destruction. The destructor is called either when the socket is really destroyed (reference counter to zero), or it can also be called when we are de-assigning the transport. In the former case, we are sure the delayed work has completed, because it holds a reference until it completes, so the destructor will definitely be called after the delayed work is finished. But in the latter case, the destructor is called by AF_VSOCK core, just after the release(), so there may still be delayed work scheduled. Refactor the code, moving the code to delete the close work already in the do_close() to a new function. Invoke it during destruction to make sure we don't leave any pending work. Fixes: c0cfa2d ("vsock: add multi-transports support") Cc: stable@vger.kernel.org Reported-by: Hyunwoo Kim <v4bel@theori.io> Closes: https://lore.kernel.org/netdev/Z37Sh+utS+iV3+eb@v4bel-B760M-AORUS-ELITE-AX/ Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> Reviewed-by: Luigi Leonardi <leonardi@redhat.com> Tested-by: Hyunwoo Kim <v4bel@theori.io> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit b7aeebee0b6c27d6b815b0fd614a668e5ca92b08)
1 parent 18ad0af commit 990fa0d

1 file changed

Lines changed: 21 additions & 8 deletions

File tree

net/vmw_vsock/virtio_transport_common.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
/* Threshold for detecting small packets to copy */
2727
#define GOOD_COPY_LEN 128
2828

29+
static void virtio_transport_cancel_close_work(struct vsock_sock *vsk,
30+
bool cancel_timeout);
31+
2932
static const struct virtio_transport *
3033
virtio_transport_get_ops(struct vsock_sock *vsk)
3134
{
@@ -922,6 +925,8 @@ void virtio_transport_destruct(struct vsock_sock *vsk)
922925
{
923926
struct virtio_vsock_sock *vvs = vsk->trans;
924927

928+
virtio_transport_cancel_close_work(vsk, true);
929+
925930
kfree(vvs);
926931
vsk->trans = NULL;
927932
}
@@ -1004,17 +1009,11 @@ static void virtio_transport_wait_close(struct sock *sk, long timeout)
10041009
}
10051010
}
10061011

1007-
static void virtio_transport_do_close(struct vsock_sock *vsk,
1008-
bool cancel_timeout)
1012+
static void virtio_transport_cancel_close_work(struct vsock_sock *vsk,
1013+
bool cancel_timeout)
10091014
{
10101015
struct sock *sk = sk_vsock(vsk);
10111016

1012-
sock_set_flag(sk, SOCK_DONE);
1013-
vsk->peer_shutdown = SHUTDOWN_MASK;
1014-
if (vsock_stream_has_data(vsk) <= 0)
1015-
sk->sk_state = TCP_CLOSING;
1016-
sk->sk_state_change(sk);
1017-
10181017
if (vsk->close_work_scheduled &&
10191018
(!cancel_timeout || cancel_delayed_work(&vsk->close_work))) {
10201019
vsk->close_work_scheduled = false;
@@ -1026,6 +1025,20 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
10261025
}
10271026
}
10281027

1028+
static void virtio_transport_do_close(struct vsock_sock *vsk,
1029+
bool cancel_timeout)
1030+
{
1031+
struct sock *sk = sk_vsock(vsk);
1032+
1033+
sock_set_flag(sk, SOCK_DONE);
1034+
vsk->peer_shutdown = SHUTDOWN_MASK;
1035+
if (vsock_stream_has_data(vsk) <= 0)
1036+
sk->sk_state = TCP_CLOSING;
1037+
sk->sk_state_change(sk);
1038+
1039+
virtio_transport_cancel_close_work(vsk, cancel_timeout);
1040+
}
1041+
10291042
static void virtio_transport_close_timeout(struct work_struct *work)
10301043
{
10311044
struct vsock_sock *vsk =

0 commit comments

Comments
 (0)