diff options
Diffstat (limited to 'fs/afs/rxrpc.c')
| -rw-r--r-- | fs/afs/rxrpc.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 588f8de51167..d82916657a3d 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -127,8 +127,15 @@ void afs_close_socket(struct afs_net *net) { _enter(""); + cancel_work_sync(&net->charge_preallocation_work); + cancel_work_sync(&net->rx_oob_work); + /* Future work items should now see ->live is false. */ + kernel_listen(net->socket, 0); + + /* Make sure work items are no longer running. */ flush_workqueue(afs_async_calls); + cancel_work_sync(&net->charge_preallocation_work); if (net->spare_incoming_call) { afs_put_call(net->spare_incoming_call); @@ -142,6 +149,7 @@ void afs_close_socket(struct afs_net *net) kernel_sock_shutdown(net->socket, SHUT_RDWR); flush_workqueue(afs_async_calls); + cancel_work_sync(&net->rx_oob_work); net->socket->sk->sk_user_data = NULL; sock_release(net->socket); key_put(net->fs_cm_token_key); @@ -742,7 +750,7 @@ void afs_charge_preallocation(struct work_struct *work) container_of(work, struct afs_net, charge_preallocation_work); struct afs_call *call = net->spare_incoming_call; - for (;;) { + while (READ_ONCE(net->live)) { if (!call) { call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL); if (!call) @@ -792,7 +800,8 @@ static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall, if (!call->server) trace_afs_cm_no_server(call, rxrpc_kernel_remote_srx(call->peer)); - queue_work(afs_wq, &net->charge_preallocation_work); + if (net->live) + queue_work(afs_wq, &net->charge_preallocation_work); } /* @@ -982,5 +991,6 @@ static void afs_rx_notify_oob(struct sock *sk, struct sk_buff *oob) { struct afs_net *net = sk->sk_user_data; - schedule_work(&net->rx_oob_work); + if (READ_ONCE(net->live)) + queue_work(afs_wq, &net->rx_oob_work); } |
