diff options
Diffstat (limited to 'net/rxrpc/call_object.c')
-rw-r--r-- | net/rxrpc/call_object.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 47f7f4205653..692110808baa 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -44,8 +44,6 @@ const char *const rxrpc_call_completions[NR__RXRPC_CALL_COMPLETIONS] = { }; struct kmem_cache *rxrpc_call_jar; -LIST_HEAD(rxrpc_calls); -DEFINE_RWLOCK(rxrpc_call_lock); static void rxrpc_call_timer_expired(unsigned long _call) { @@ -207,6 +205,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, __releases(&rx->sk.sk_lock.slock) { struct rxrpc_call *call, *xcall; + struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk)); struct rb_node *parent, **pp; const void *here = __builtin_return_address(0); int ret; @@ -255,9 +254,9 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, write_unlock(&rx->call_lock); - write_lock(&rxrpc_call_lock); - list_add_tail(&call->link, &rxrpc_calls); - write_unlock(&rxrpc_call_lock); + write_lock(&rxnet->call_lock); + list_add_tail(&call->link, &rxnet->calls); + write_unlock(&rxnet->call_lock); /* From this point on, the call is protected by its own lock. */ release_sock(&rx->sk); @@ -508,6 +507,7 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx) */ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) { + struct rxrpc_net *rxnet; const void *here = __builtin_return_address(0); int n; @@ -520,9 +520,12 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) _debug("call %d dead", call->debug_id); ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); - write_lock(&rxrpc_call_lock); - list_del_init(&call->link); - write_unlock(&rxrpc_call_lock); + if (!list_empty(&call->link)) { + rxnet = rxrpc_net(sock_net(&call->socket->sk)); + write_lock(&rxnet->call_lock); + list_del_init(&call->link); + write_unlock(&rxnet->call_lock); + } rxrpc_cleanup_call(call); } @@ -570,21 +573,23 @@ void rxrpc_cleanup_call(struct rxrpc_call *call) } /* - * Make sure that all calls are gone. + * Make sure that all calls are gone from a network namespace. To reach this + * point, any open UDP sockets in that namespace must have been closed, so any + * outstanding calls cannot be doing I/O. */ -void __exit rxrpc_destroy_all_calls(void) +void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet) { struct rxrpc_call *call; _enter(""); - if (list_empty(&rxrpc_calls)) + if (list_empty(&rxnet->calls)) return; - write_lock(&rxrpc_call_lock); + write_lock(&rxnet->call_lock); - while (!list_empty(&rxrpc_calls)) { - call = list_entry(rxrpc_calls.next, struct rxrpc_call, link); + while (!list_empty(&rxnet->calls)) { + call = list_entry(rxnet->calls.next, struct rxrpc_call, link); _debug("Zapping call %p", call); rxrpc_see_call(call); @@ -595,10 +600,10 @@ void __exit rxrpc_destroy_all_calls(void) rxrpc_call_states[call->state], call->flags, call->events); - write_unlock(&rxrpc_call_lock); + write_unlock(&rxnet->call_lock); cond_resched(); - write_lock(&rxrpc_call_lock); + write_lock(&rxnet->call_lock); } - write_unlock(&rxrpc_call_lock); + write_unlock(&rxnet->call_lock); } |