Skip to content

Commit

Permalink
afs: Wait for outstanding async calls before closing rxrpc socket
Browse files Browse the repository at this point in the history
The afs filesystem needs to wait for any outstanding asynchronous calls
(such as FS.GiveUpCallBacks cleaning up the callbacks lodged with a server)
to complete before closing the AF_RXRPC socket when unloading the module.

This may occur if the module is removed too quickly after unmounting all
filesystems.  This will produce an error report that looks like:

	AFS: Assertion failed
	1 == 0 is false
	0x1 == 0x0 is false
	------------[ cut here ]------------
	kernel BUG at ../fs/afs/rxrpc.c:135!
	...
	RIP: 0010:[<ffffffffa004111c>] afs_close_socket+0xec/0x107 [kafs]
	...
	Call Trace:
	 [<ffffffffa004a160>] afs_exit+0x1f/0x57 [kafs]
	 [<ffffffff810c30a0>] SyS_delete_module+0xec/0x17d
	 [<ffffffff81610417>] entry_SYSCALL_64_fastpath+0x12/0x6b

Signed-off-by: David Howells <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
dhowells authored and davem330 committed Apr 11, 2016
1 parent c64a73d commit 2f02f7a
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions fs/afs/rxrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ static void afs_async_workfn(struct work_struct *work)
call->async_workfn(call);
}

static int afs_wait_atomic_t(atomic_t *p)
{
schedule();
return 0;
}

/*
* open an RxRPC socket and bind it to be a server for callback notifications
* - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT
Expand Down Expand Up @@ -126,13 +132,16 @@ void afs_close_socket(void)
{
_enter("");

wait_on_atomic_t(&afs_outstanding_calls, afs_wait_atomic_t,
TASK_UNINTERRUPTIBLE);
_debug("no outstanding calls");

sock_release(afs_socket);

_debug("dework");
destroy_workqueue(afs_async_calls);

ASSERTCMP(atomic_read(&afs_outstanding_skbs), ==, 0);
ASSERTCMP(atomic_read(&afs_outstanding_calls), ==, 0);
_leave("");
}

Expand Down Expand Up @@ -178,8 +187,6 @@ static void afs_free_call(struct afs_call *call)
{
_debug("DONE %p{%s} [%d]",
call, call->type->name, atomic_read(&afs_outstanding_calls));
if (atomic_dec_return(&afs_outstanding_calls) == -1)
BUG();

ASSERTCMP(call->rxcall, ==, NULL);
ASSERT(!work_pending(&call->async_work));
Expand All @@ -188,6 +195,9 @@ static void afs_free_call(struct afs_call *call)

kfree(call->request);
kfree(call);

if (atomic_dec_and_test(&afs_outstanding_calls))
wake_up_atomic_t(&afs_outstanding_calls);
}

/*
Expand Down

0 comments on commit 2f02f7a

Please sign in to comment.