mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	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
d9dc8b0f8b ("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>
			
			
This commit is contained in:
		
							parent
							
								
									72ccc471e1
								
							
						
					
					
						commit
						499fde662f
					
				
					 1 changed files with 8 additions and 13 deletions
				
			
		|  | @ -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); | ||||
|  | @ -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) && | ||||
|  | @ -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 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 WANG Cong
						WANG Cong