Skip to content

Commit

Permalink
vsock: use new wait API for vsock_stream_sendmsg()
Browse files Browse the repository at this point in the history
As reported by Michal, vsock_stream_sendmsg() could still
sleep at vsock_stream_has_space() after prepare_to_wait():

  vsock_stream_has_space
    vmci_transport_stream_has_space
      vmci_qpair_produce_free_space
        qp_lock
          qp_acquire_queue_mutex
            mutex_lock

Just switch to the new wait API like we did for commit
d9dc8b0 ("net: fix sleeping for sk_wait_event()").

Reported-by: Michal Kubecek <[email protected]>
Cc: Stefan Hajnoczi <[email protected]>
Cc: Jorgen Hansen <[email protected]>
Cc: "Michael S. Tsirkin" <[email protected]>
Cc: Claudio Imbrenda <[email protected]>
Signed-off-by: Cong Wang <[email protected]>
Reviewed-by: Stefan Hajnoczi <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
congwang authored and davem330 committed May 22, 2017
1 parent 72ccc47 commit 499fde6
Showing 1 changed file with 8 additions and 13 deletions.
21 changes: 8 additions & 13 deletions net/vmw_vsock/af_vsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1540,8 +1540,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
long timeout;
int err;
struct vsock_transport_send_notify_data send_data;

DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);

sk = sock->sk;
vsk = vsock_sk(sk);
Expand Down Expand Up @@ -1584,11 +1583,10 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
if (err < 0)
goto out;


while (total_written < len) {
ssize_t written;

prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
add_wait_queue(sk_sleep(sk), &wait);
while (vsock_stream_has_space(vsk) == 0 &&
sk->sk_err == 0 &&
!(sk->sk_shutdown & SEND_SHUTDOWN) &&
Expand All @@ -1597,33 +1595,30 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
/* Don't wait for non-blocking sockets. */
if (timeout == 0) {
err = -EAGAIN;
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
goto out_err;
}

err = transport->notify_send_pre_block(vsk, &send_data);
if (err < 0) {
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
goto out_err;
}

release_sock(sk);
timeout = schedule_timeout(timeout);
timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
lock_sock(sk);
if (signal_pending(current)) {
err = sock_intr_errno(timeout);
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
goto out_err;
} else if (timeout == 0) {
err = -EAGAIN;
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
goto out_err;
}

prepare_to_wait(sk_sleep(sk), &wait,
TASK_INTERRUPTIBLE);
}
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);

/* These checks occur both as part of and after the loop
* conditional since we need to check before and after
Expand Down

0 comments on commit 499fde6

Please sign in to comment.