aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/sched.c')
-rw-r--r--net/sunrpc/sched.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 385f427bedad..ff50a0546865 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -293,11 +293,6 @@ static void rpc_make_runnable(struct rpc_task *task)
293 rpc_clear_queued(task); 293 rpc_clear_queued(task);
294 if (rpc_test_and_set_running(task)) 294 if (rpc_test_and_set_running(task))
295 return; 295 return;
296 /* We might have raced */
297 if (RPC_IS_QUEUED(task)) {
298 rpc_clear_running(task);
299 return;
300 }
301 if (RPC_IS_ASYNC(task)) { 296 if (RPC_IS_ASYNC(task)) {
302 int status; 297 int status;
303 298
@@ -607,7 +602,9 @@ void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata)
607 */ 602 */
608static void __rpc_execute(struct rpc_task *task) 603static void __rpc_execute(struct rpc_task *task)
609{ 604{
610 int status = 0; 605 struct rpc_wait_queue *queue;
606 int task_is_async = RPC_IS_ASYNC(task);
607 int status = 0;
611 608
612 dprintk("RPC: %5u __rpc_execute flags=0x%x\n", 609 dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
613 task->tk_pid, task->tk_flags); 610 task->tk_pid, task->tk_flags);
@@ -647,15 +644,25 @@ static void __rpc_execute(struct rpc_task *task)
647 */ 644 */
648 if (!RPC_IS_QUEUED(task)) 645 if (!RPC_IS_QUEUED(task))
649 continue; 646 continue;
650 rpc_clear_running(task); 647 /*
651 if (RPC_IS_ASYNC(task)) { 648 * The queue->lock protects against races with
652 /* Careful! we may have raced... */ 649 * rpc_make_runnable().
653 if (RPC_IS_QUEUED(task)) 650 *
654 return; 651 * Note that once we clear RPC_TASK_RUNNING on an asynchronous
655 if (rpc_test_and_set_running(task)) 652 * rpc_task, rpc_make_runnable() can assign it to a
656 return; 653 * different workqueue. We therefore cannot assume that the
654 * rpc_task pointer may still be dereferenced.
655 */
656 queue = task->tk_waitqueue;
657 spin_lock_bh(&queue->lock);
658 if (!RPC_IS_QUEUED(task)) {
659 spin_unlock_bh(&queue->lock);
657 continue; 660 continue;
658 } 661 }
662 rpc_clear_running(task);
663 spin_unlock_bh(&queue->lock);
664 if (task_is_async)
665 return;
659 666
660 /* sync task: sleep here */ 667 /* sync task: sleep here */
661 dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid); 668 dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);