diff options
Diffstat (limited to 'net/rxrpc/call_object.c')
| -rw-r--r-- | net/rxrpc/call_object.c | 28 | 
1 files changed, 12 insertions, 16 deletions
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 15067ff7b1f2..918f41d97a2f 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -561,7 +561,7 @@ static void rxrpc_cleanup_rx_buffers(struct rxrpc_call *call)  void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)  {  	struct rxrpc_connection *conn = call->conn; -	bool put = false, putu = false; +	bool putu = false;  	_enter("{%d,%d}", call->debug_id, refcount_read(&call->ref)); @@ -573,23 +573,13 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)  	rxrpc_put_call_slot(call); -	/* Make sure we don't get any more notifications */ +	/* Note that at this point, the call may still be on or may have been +	 * added back on to the socket receive queue.  recvmsg() must discard +	 * released calls.  The CALL_RELEASED flag should prevent further +	 * notifications. +	 */  	spin_lock_irq(&rx->recvmsg_lock); - -	if (!list_empty(&call->recvmsg_link)) { -		_debug("unlinking once-pending call %p { e=%lx f=%lx }", -		       call, call->events, call->flags); -		list_del(&call->recvmsg_link); -		put = true; -	} - -	/* list_empty() must return false in rxrpc_notify_socket() */ -	call->recvmsg_link.next = NULL; -	call->recvmsg_link.prev = NULL; -  	spin_unlock_irq(&rx->recvmsg_lock); -	if (put) -		rxrpc_put_call(call, rxrpc_call_put_unnotify);  	write_lock(&rx->call_lock); @@ -638,6 +628,12 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx)  		rxrpc_put_call(call, rxrpc_call_put_release_sock);  	} +	while ((call = list_first_entry_or_null(&rx->recvmsg_q, +						struct rxrpc_call, recvmsg_link))) { +		list_del_init(&call->recvmsg_link); +		rxrpc_put_call(call, rxrpc_call_put_release_recvmsg_q); +	} +  	_leave("");  }  | 
