aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/sched.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-02-22 16:34:17 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-02-26 00:40:44 -0500
commit5d00837b90340af9106dcd93af75fd664c8eb87f (patch)
treef537dc84421cf150d66b630e56ea8107078c07a8 /net/sunrpc/sched.c
parentfda1393938035559b417dd5b26b9cc293a7aee00 (diff)
SUNRPC: Run rpc timeout functions as callbacks instead of in softirqs
An audit of the current RPC timeout functions shows that they don't really ever need to run in the softirq context. As long as the softirq is able to signal that the wakeup is due to a timeout (which it can do by setting task->tk_status to -ETIMEDOUT) then the callback functions can just run as standard task->tk_callback functions (in the rpciod/process context). The only possible border-line case would be xprt_timer() for the case of UDP, when the callback is used to reduce the size of the transport congestion window. In testing, however, the effect of moving that update to a callback would appear to be minor. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/sched.c')
-rw-r--r--net/sunrpc/sched.c50
1 files changed, 15 insertions, 35 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 35acdc39bfcb..caf12fd6b6af 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -56,29 +56,18 @@ struct workqueue_struct *rpciod_workqueue;
56 * queue->lock and bh_disabled in order to avoid races within 56 * queue->lock and bh_disabled in order to avoid races within
57 * rpc_run_timer(). 57 * rpc_run_timer().
58 */ 58 */
59static inline void 59static void
60__rpc_disable_timer(struct rpc_task *task) 60__rpc_disable_timer(struct rpc_task *task)
61{ 61{
62 dprintk("RPC: %5u disabling timer\n", task->tk_pid); 62 dprintk("RPC: %5u disabling timer\n", task->tk_pid);
63 task->tk_timeout_fn = NULL;
64 task->tk_timeout = 0; 63 task->tk_timeout = 0;
65} 64}
66 65
67/* 66/*
68 * Default timeout handler if none specified by user
69 */
70static void
71__rpc_default_timer(struct rpc_task *task)
72{
73 dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
74 task->tk_status = -ETIMEDOUT;
75}
76
77/*
78 * Set up a timer for the current task. 67 * Set up a timer for the current task.
79 */ 68 */
80static inline void 69static void
81__rpc_add_timer(struct rpc_task *task, rpc_action timer) 70__rpc_add_timer(struct rpc_task *task)
82{ 71{
83 if (!task->tk_timeout) 72 if (!task->tk_timeout)
84 return; 73 return;
@@ -86,10 +75,6 @@ __rpc_add_timer(struct rpc_task *task, rpc_action timer)
86 dprintk("RPC: %5u setting alarm for %lu ms\n", 75 dprintk("RPC: %5u setting alarm for %lu ms\n",
87 task->tk_pid, task->tk_timeout * 1000 / HZ); 76 task->tk_pid, task->tk_timeout * 1000 / HZ);
88 77
89 if (timer)
90 task->tk_timeout_fn = timer;
91 else
92 task->tk_timeout_fn = __rpc_default_timer;
93 set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate); 78 set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
94 mod_timer(&task->tk_timer, jiffies + task->tk_timeout); 79 mod_timer(&task->tk_timer, jiffies + task->tk_timeout);
95} 80}
@@ -297,7 +282,6 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task);
297 */ 282 */
298static void rpc_make_runnable(struct rpc_task *task) 283static void rpc_make_runnable(struct rpc_task *task)
299{ 284{
300 BUG_ON(task->tk_timeout_fn);
301 rpc_clear_queued(task); 285 rpc_clear_queued(task);
302 if (rpc_test_and_set_running(task)) 286 if (rpc_test_and_set_running(task))
303 return; 287 return;
@@ -327,7 +311,7 @@ static void rpc_make_runnable(struct rpc_task *task)
327 * as it's on a wait queue. 311 * as it's on a wait queue.
328 */ 312 */
329static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, 313static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
330 rpc_action action, rpc_action timer) 314 rpc_action action)
331{ 315{
332 dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", 316 dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n",
333 task->tk_pid, rpc_qname(q), jiffies); 317 task->tk_pid, rpc_qname(q), jiffies);
@@ -341,11 +325,11 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
341 325
342 BUG_ON(task->tk_callback != NULL); 326 BUG_ON(task->tk_callback != NULL);
343 task->tk_callback = action; 327 task->tk_callback = action;
344 __rpc_add_timer(task, timer); 328 __rpc_add_timer(task);
345} 329}
346 330
347void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, 331void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
348 rpc_action action, rpc_action timer) 332 rpc_action action)
349{ 333{
350 /* Mark the task as being activated if so needed */ 334 /* Mark the task as being activated if so needed */
351 rpc_set_active(task); 335 rpc_set_active(task);
@@ -354,7 +338,7 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
354 * Protect the queue operations. 338 * Protect the queue operations.
355 */ 339 */
356 spin_lock_bh(&q->lock); 340 spin_lock_bh(&q->lock);
357 __rpc_sleep_on(q, task, action, timer); 341 __rpc_sleep_on(q, task, action);
358 spin_unlock_bh(&q->lock); 342 spin_unlock_bh(&q->lock);
359} 343}
360EXPORT_SYMBOL_GPL(rpc_sleep_on); 344EXPORT_SYMBOL_GPL(rpc_sleep_on);
@@ -559,20 +543,15 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_status);
559static void rpc_run_timer(unsigned long ptr) 543static void rpc_run_timer(unsigned long ptr)
560{ 544{
561 struct rpc_task *task = (struct rpc_task *)ptr; 545 struct rpc_task *task = (struct rpc_task *)ptr;
562 void (*callback)(struct rpc_task *); 546 struct rpc_wait_queue *queue = task->tk_waitqueue;
563 547
564 if (RPC_IS_QUEUED(task)) { 548 spin_lock(&queue->lock);
565 struct rpc_wait_queue *queue = task->tk_waitqueue; 549 if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue) {
566 callback = task->tk_timeout_fn; 550 dprintk("RPC: %5u timeout\n", task->tk_pid);
567 551 task->tk_status = -ETIMEDOUT;
568 dprintk("RPC: %5u running timer\n", task->tk_pid);
569 if (callback != NULL)
570 callback(task);
571 /* Note: we're already in a bh-safe context */
572 spin_lock(&queue->lock);
573 rpc_wake_up_task_queue_locked(queue, task); 552 rpc_wake_up_task_queue_locked(queue, task);
574 spin_unlock(&queue->lock);
575 } 553 }
554 spin_unlock(&queue->lock);
576 smp_mb__before_clear_bit(); 555 smp_mb__before_clear_bit();
577 clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate); 556 clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
578 smp_mb__after_clear_bit(); 557 smp_mb__after_clear_bit();
@@ -580,6 +559,7 @@ static void rpc_run_timer(unsigned long ptr)
580 559
581static void __rpc_atrun(struct rpc_task *task) 560static void __rpc_atrun(struct rpc_task *task)
582{ 561{
562 task->tk_status = 0;
583} 563}
584 564
585/* 565/*
@@ -588,7 +568,7 @@ static void __rpc_atrun(struct rpc_task *task)
588void rpc_delay(struct rpc_task *task, unsigned long delay) 568void rpc_delay(struct rpc_task *task, unsigned long delay)
589{ 569{
590 task->tk_timeout = delay; 570 task->tk_timeout = delay;
591 rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); 571 rpc_sleep_on(&delay_queue, task, __rpc_atrun);
592} 572}
593EXPORT_SYMBOL_GPL(rpc_delay); 573EXPORT_SYMBOL_GPL(rpc_delay);
594 574