Commit 499fde66 authored by WANG Cong's avatar WANG Cong Committed by David S. Miller

vsock: use new wait API for vsock_stream_sendmsg()

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
d9dc8b0f ("net: fix sleeping for sk_wait_event()").
Reported-by: default avatarMichal Kubecek <mkubecek@suse.cz>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Jorgen Hansen <jhansen@vmware.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 72ccc471
...@@ -1540,8 +1540,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -1540,8 +1540,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
long timeout; long timeout;
int err; int err;
struct vsock_transport_send_notify_data send_data; struct vsock_transport_send_notify_data send_data;
DEFINE_WAIT_FUNC(wait, woken_wake_function);
DEFINE_WAIT(wait);
sk = sock->sk; sk = sock->sk;
vsk = vsock_sk(sk); vsk = vsock_sk(sk);
...@@ -1584,11 +1583,10 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -1584,11 +1583,10 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
if (err < 0) if (err < 0)
goto out; goto out;
while (total_written < len) { while (total_written < len) {
ssize_t written; 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 && while (vsock_stream_has_space(vsk) == 0 &&
sk->sk_err == 0 && sk->sk_err == 0 &&
!(sk->sk_shutdown & SEND_SHUTDOWN) && !(sk->sk_shutdown & SEND_SHUTDOWN) &&
...@@ -1597,33 +1595,30 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -1597,33 +1595,30 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
/* Don't wait for non-blocking sockets. */ /* Don't wait for non-blocking sockets. */
if (timeout == 0) { if (timeout == 0) {
err = -EAGAIN; err = -EAGAIN;
finish_wait(sk_sleep(sk), &wait); remove_wait_queue(sk_sleep(sk), &wait);
goto out_err; goto out_err;
} }
err = transport->notify_send_pre_block(vsk, &send_data); err = transport->notify_send_pre_block(vsk, &send_data);
if (err < 0) { if (err < 0) {
finish_wait(sk_sleep(sk), &wait); remove_wait_queue(sk_sleep(sk), &wait);
goto out_err; goto out_err;
} }
release_sock(sk); release_sock(sk);
timeout = schedule_timeout(timeout); timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
lock_sock(sk); lock_sock(sk);
if (signal_pending(current)) { if (signal_pending(current)) {
err = sock_intr_errno(timeout); err = sock_intr_errno(timeout);
finish_wait(sk_sleep(sk), &wait); remove_wait_queue(sk_sleep(sk), &wait);
goto out_err; goto out_err;
} else if (timeout == 0) { } else if (timeout == 0) {
err = -EAGAIN; err = -EAGAIN;
finish_wait(sk_sleep(sk), &wait); remove_wait_queue(sk_sleep(sk), &wait);
goto out_err; 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 /* These checks occur both as part of and after the loop
* conditional since we need to check before and after * conditional since we need to check before and after
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment