]> git.hungrycats.org Git - linux/commitdiff
vsock: use new wait API for vsock_stream_sendmsg()
authorWANG Cong <xiyou.wangcong@gmail.com>
Fri, 19 May 2017 18:21:59 +0000 (11:21 -0700)
committerSasha Levin <alexander.levin@verizon.com>
Fri, 8 Dec 2017 23:01:01 +0000 (18:01 -0500)
[ Upstream commit 499fde662f1957e3cb8d192a94a099ebe19c714b ]

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
d9dc8b0f8b4e ("net: fix sleeping for sk_wait_event()").

Reported-by: Michal 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: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
net/vmw_vsock/af_vsock.c

index f3205db44647c38869b9ee4004e355f3c9ee878d..dfc542ecf9c401045a46d726a66a33163b1d8b5c 100644 (file)
@@ -1512,8 +1512,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);
@@ -1556,11 +1555,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) &&
@@ -1569,33 +1567,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