diff options
Diffstat (limited to 'net/sunrpc/sched.c')
| -rw-r--r-- | net/sunrpc/sched.c | 8 | 
1 files changed, 7 insertions, 1 deletions
| diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index f8529fc8e542..5356b120dbf8 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -324,11 +324,17 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task);   * Note: If the task is ASYNC, and is being made runnable after sitting on an   * rpc_wait_queue, this must be called with the queue spinlock held to protect   * the wait queue operation. + * Note the ordering of rpc_test_and_set_running() and rpc_clear_queued(), + * which is needed to ensure that __rpc_execute() doesn't loop (due to the + * lockless RPC_IS_QUEUED() test) before we've had a chance to test + * the RPC_TASK_RUNNING flag.   */  static void rpc_make_runnable(struct rpc_task *task)  { +	bool need_wakeup = !rpc_test_and_set_running(task); +  	rpc_clear_queued(task); -	if (rpc_test_and_set_running(task)) +	if (!need_wakeup)  		return;  	if (RPC_IS_ASYNC(task)) {  		INIT_WORK(&task->u.tk_work, rpc_async_schedule); | 
