• Nathaniel Wesley Filardo's avatar
    AFS: Fix kafs module unloading · 150a6b47
    Nathaniel Wesley Filardo authored
    At present, it is not possible to successfully unload the kafs module if there
    are outstanding async outgoing calls (those made with afs_make_call()).  This
    appears to be due to the changes introduced by:
    
    	commit 05949945
    	Author: Tejun Heo <tj@kernel.org>
    	Date:   Fri Mar 7 10:24:50 2014 -0500
    	Subject: afs: don't use PREPARE_WORK
    
    which didn't go far enough.  The problem is due to:
    
     (1) The aforementioned commit introduced a separate handler function pointer
         in the call, call->async_workfn, in addition to the original workqueue
         item, call->async_work, for asynchronous operations because workqueues
         subsystem cannot handle the workqueue item pointer being changed whilst
         the item is queued or being processed.
    
     (2) afs_async_workfn() was introduced in that commit to be the callback for
         call->async_work.  Its sole purpose is to run whatever call->async_workfn
         points to.
    
     (3) call->async_workfn is only used from afs_async_workfn(), which is only
         set on async_work by afs_collect_incoming_call() - ie. for incoming
         calls.
    
     (4) call->async_workfn is *not* set by afs_make_call() when outgoing calls are
         made, and call->async_work is set afs_process_async_call() - and not
         afs_async_workfn().
    
     (5) afs_process_async_call() now changes call->async_workfn rather than
         call->async_work to point to afs_delete_async_call() to clean up, but this
         is only effective for incoming calls because call->async_work does not
         point to afs_async_workfn() for outgoing calls.
    
     (6) Because, for incoming calls, call->async_work remains pointing to
         afs_process_async_call() this results in an infinite loop.
    
    Instead, make the workqueue uniformly vector through call->async_workfn, via
    afs_async_workfn() and simply initialise call->async_workfn to point to
    afs_process_async_call() in afs_make_call().
    Signed-off-by: default avatarNathaniel Wesley Filardo <nwf@cs.jhu.edu>
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    Reviewed-by: default avatarTejun Heo <tj@kernel.org>
    150a6b47
rxrpc.c 20.3 KB