Skip to content

Commit df137da

Browse files
stefano-garzarellaPaolo Abeni
authored andcommitted
vsock/virtio: cancel close work in the destructor
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: [email protected] Reported-by: Hyunwoo Kim <[email protected]> Closes: https://lore.kernel.org/netdev/Z37Sh+utS+iV3+eb@v4bel-B760M-AORUS-ELITE-AX/ Signed-off-by: Stefano Garzarella <[email protected]> Reviewed-by: Luigi Leonardi <[email protected]> Tested-by: Hyunwoo Kim <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent f6abafc commit df137da

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

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
{
@@ -1109,6 +1112,8 @@ void virtio_transport_destruct(struct vsock_sock *vsk)
11091112
{
11101113
struct virtio_vsock_sock *vvs = vsk->trans;
11111114

1115+
virtio_transport_cancel_close_work(vsk, true);
1116+
11121117
kfree(vvs);
11131118
vsk->trans = NULL;
11141119
}
@@ -1204,17 +1209,11 @@ static void virtio_transport_wait_close(struct sock *sk, long timeout)
12041209
}
12051210
}
12061211

1207-
static void virtio_transport_do_close(struct vsock_sock *vsk,
1208-
bool cancel_timeout)
1212+
static void virtio_transport_cancel_close_work(struct vsock_sock *vsk,
1213+
bool cancel_timeout)
12091214
{
12101215
struct sock *sk = sk_vsock(vsk);
12111216

1212-
sock_set_flag(sk, SOCK_DONE);
1213-
vsk->peer_shutdown = SHUTDOWN_MASK;
1214-
if (vsock_stream_has_data(vsk) <= 0)
1215-
sk->sk_state = TCP_CLOSING;
1216-
sk->sk_state_change(sk);
1217-
12181217
if (vsk->close_work_scheduled &&
12191218
(!cancel_timeout || cancel_delayed_work(&vsk->close_work))) {
12201219
vsk->close_work_scheduled = false;
@@ -1226,6 +1225,20 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
12261225
}
12271226
}
12281227

1228+
static void virtio_transport_do_close(struct vsock_sock *vsk,
1229+
bool cancel_timeout)
1230+
{
1231+
struct sock *sk = sk_vsock(vsk);
1232+
1233+
sock_set_flag(sk, SOCK_DONE);
1234+
vsk->peer_shutdown = SHUTDOWN_MASK;
1235+
if (vsock_stream_has_data(vsk) <= 0)
1236+
sk->sk_state = TCP_CLOSING;
1237+
sk->sk_state_change(sk);
1238+
1239+
virtio_transport_cancel_close_work(vsk, cancel_timeout);
1240+
}
1241+
12291242
static void virtio_transport_close_timeout(struct work_struct *work)
12301243
{
12311244
struct vsock_sock *vsk =

0 commit comments

Comments
 (0)