diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-02-22 17:27:59 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-02-29 02:26:21 -0500 |
commit | eb276c0e10187702928aeaa133e1d3dbaf3eafc7 (patch) | |
tree | f7cfb639d97747f32573dc72970aa9bf589fb0da | |
parent | 36df9aae3158ce8fc4ede241169dc94ac910d884 (diff) |
SUNRPC: Switch tasks to using the rpc_waitqueue's timer function
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | include/linux/sunrpc/sched.h | 9 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 60 |
2 files changed, 11 insertions, 58 deletions
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 7751d3a05497..0d7be1642dc0 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -67,12 +67,6 @@ struct rpc_task { | |||
67 | const struct rpc_call_ops *tk_ops; | 67 | const struct rpc_call_ops *tk_ops; |
68 | void * tk_calldata; | 68 | void * tk_calldata; |
69 | 69 | ||
70 | /* | ||
71 | * tk_timer is used for async processing by the RPC scheduling | ||
72 | * primitives. You should not access this directly unless | ||
73 | * you have a pathological interest in kernel oopses. | ||
74 | */ | ||
75 | struct timer_list tk_timer; /* kernel timer */ | ||
76 | unsigned long tk_timeout; /* timeout for rpc_sleep() */ | 70 | unsigned long tk_timeout; /* timeout for rpc_sleep() */ |
77 | unsigned short tk_flags; /* misc flags */ | 71 | unsigned short tk_flags; /* misc flags */ |
78 | unsigned long tk_runstate; /* Task run status */ | 72 | unsigned long tk_runstate; /* Task run status */ |
@@ -149,8 +143,7 @@ struct rpc_task_setup { | |||
149 | #define RPC_TASK_RUNNING 0 | 143 | #define RPC_TASK_RUNNING 0 |
150 | #define RPC_TASK_QUEUED 1 | 144 | #define RPC_TASK_QUEUED 1 |
151 | #define RPC_TASK_WAKEUP 2 | 145 | #define RPC_TASK_WAKEUP 2 |
152 | #define RPC_TASK_HAS_TIMER 3 | 146 | #define RPC_TASK_ACTIVE 3 |
153 | #define RPC_TASK_ACTIVE 4 | ||
154 | 147 | ||
155 | #define RPC_IS_RUNNING(t) test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate) | 148 | #define RPC_IS_RUNNING(t) test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate) |
156 | #define rpc_set_running(t) set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate) | 149 | #define rpc_set_running(t) set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate) |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 29b1c1441f4d..043eef4c15a2 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -58,13 +58,15 @@ struct workqueue_struct *rpciod_workqueue; | |||
58 | * rpc_run_timer(). | 58 | * rpc_run_timer(). |
59 | */ | 59 | */ |
60 | static void | 60 | static void |
61 | __rpc_disable_timer(struct rpc_task *task) | 61 | __rpc_disable_timer(struct rpc_wait_queue *queue, struct rpc_task *task) |
62 | { | 62 | { |
63 | if (task->tk_timeout == 0) | 63 | if (task->tk_timeout == 0) |
64 | return; | 64 | return; |
65 | dprintk("RPC: %5u disabling timer\n", task->tk_pid); | 65 | dprintk("RPC: %5u disabling timer\n", task->tk_pid); |
66 | task->tk_timeout = 0; | 66 | task->tk_timeout = 0; |
67 | list_del(&task->u.tk_wait.timer_list); | 67 | list_del(&task->u.tk_wait.timer_list); |
68 | if (list_empty(&queue->timer_list.list)) | ||
69 | del_timer(&queue->timer_list.timer); | ||
68 | } | 70 | } |
69 | 71 | ||
70 | static void | 72 | static void |
@@ -78,7 +80,7 @@ rpc_set_queue_timer(struct rpc_wait_queue *queue, unsigned long expires) | |||
78 | * Set up a timer for the current task. | 80 | * Set up a timer for the current task. |
79 | */ | 81 | */ |
80 | static void | 82 | static void |
81 | __rpc_add_timer(struct rpc_task *task) | 83 | __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task) |
82 | { | 84 | { |
83 | if (!task->tk_timeout) | 85 | if (!task->tk_timeout) |
84 | return; | 86 | return; |
@@ -86,23 +88,10 @@ __rpc_add_timer(struct rpc_task *task) | |||
86 | dprintk("RPC: %5u setting alarm for %lu ms\n", | 88 | dprintk("RPC: %5u setting alarm for %lu ms\n", |
87 | task->tk_pid, task->tk_timeout * 1000 / HZ); | 89 | task->tk_pid, task->tk_timeout * 1000 / HZ); |
88 | 90 | ||
89 | set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate); | 91 | task->u.tk_wait.expires = jiffies + task->tk_timeout; |
90 | mod_timer(&task->tk_timer, jiffies + task->tk_timeout); | 92 | if (list_empty(&queue->timer_list.list) || time_before(task->u.tk_wait.expires, queue->timer_list.expires)) |
91 | } | 93 | rpc_set_queue_timer(queue, task->u.tk_wait.expires); |
92 | 94 | list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list); | |
93 | /* | ||
94 | * Delete any timer for the current task. Because we use del_timer_sync(), | ||
95 | * this function should never be called while holding queue->lock. | ||
96 | */ | ||
97 | static void | ||
98 | rpc_delete_timer(struct rpc_task *task) | ||
99 | { | ||
100 | if (RPC_IS_QUEUED(task)) | ||
101 | return; | ||
102 | if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) { | ||
103 | del_singleshot_timer_sync(&task->tk_timer); | ||
104 | dprintk("RPC: %5u deleting timer\n", task->tk_pid); | ||
105 | } | ||
106 | } | 95 | } |
107 | 96 | ||
108 | /* | 97 | /* |
@@ -172,7 +161,7 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task) | |||
172 | */ | 161 | */ |
173 | static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task) | 162 | static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task) |
174 | { | 163 | { |
175 | __rpc_disable_timer(task); | 164 | __rpc_disable_timer(queue, task); |
176 | if (RPC_IS_PRIORITY(queue)) | 165 | if (RPC_IS_PRIORITY(queue)) |
177 | __rpc_remove_wait_queue_priority(task); | 166 | __rpc_remove_wait_queue_priority(task); |
178 | list_del(&task->u.tk_wait.list); | 167 | list_del(&task->u.tk_wait.list); |
@@ -344,7 +333,7 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
344 | 333 | ||
345 | BUG_ON(task->tk_callback != NULL); | 334 | BUG_ON(task->tk_callback != NULL); |
346 | task->tk_callback = action; | 335 | task->tk_callback = action; |
347 | __rpc_add_timer(task); | 336 | __rpc_add_timer(q, task); |
348 | } | 337 | } |
349 | 338 | ||
350 | void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | 339 | void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, |
@@ -555,26 +544,6 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) | |||
555 | } | 544 | } |
556 | EXPORT_SYMBOL_GPL(rpc_wake_up_status); | 545 | EXPORT_SYMBOL_GPL(rpc_wake_up_status); |
557 | 546 | ||
558 | /* | ||
559 | * Run a timeout function. | ||
560 | */ | ||
561 | static void rpc_run_timer(unsigned long ptr) | ||
562 | { | ||
563 | struct rpc_task *task = (struct rpc_task *)ptr; | ||
564 | struct rpc_wait_queue *queue = task->tk_waitqueue; | ||
565 | |||
566 | spin_lock(&queue->lock); | ||
567 | if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue) { | ||
568 | dprintk("RPC: %5u timeout\n", task->tk_pid); | ||
569 | task->tk_status = -ETIMEDOUT; | ||
570 | rpc_wake_up_task_queue_locked(queue, task); | ||
571 | } | ||
572 | spin_unlock(&queue->lock); | ||
573 | smp_mb__before_clear_bit(); | ||
574 | clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate); | ||
575 | smp_mb__after_clear_bit(); | ||
576 | } | ||
577 | |||
578 | static void __rpc_queue_timer_fn(unsigned long ptr) | 547 | static void __rpc_queue_timer_fn(unsigned long ptr) |
579 | { | 548 | { |
580 | struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr; | 549 | struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr; |
@@ -586,7 +555,6 @@ static void __rpc_queue_timer_fn(unsigned long ptr) | |||
586 | list_for_each_entry_safe(task, n, &queue->timer_list.list, u.tk_wait.timer_list) { | 555 | list_for_each_entry_safe(task, n, &queue->timer_list.list, u.tk_wait.timer_list) { |
587 | timeo = task->u.tk_wait.expires; | 556 | timeo = task->u.tk_wait.expires; |
588 | if (time_after_eq(now, timeo)) { | 557 | if (time_after_eq(now, timeo)) { |
589 | list_del_init(&task->u.tk_wait.timer_list); | ||
590 | dprintk("RPC: %5u timeout\n", task->tk_pid); | 558 | dprintk("RPC: %5u timeout\n", task->tk_pid); |
591 | task->tk_status = -ETIMEDOUT; | 559 | task->tk_status = -ETIMEDOUT; |
592 | rpc_wake_up_task_queue_locked(queue, task); | 560 | rpc_wake_up_task_queue_locked(queue, task); |
@@ -666,10 +634,6 @@ static void __rpc_execute(struct rpc_task *task) | |||
666 | BUG_ON(RPC_IS_QUEUED(task)); | 634 | BUG_ON(RPC_IS_QUEUED(task)); |
667 | 635 | ||
668 | for (;;) { | 636 | for (;;) { |
669 | /* | ||
670 | * Garbage collection of pending timers... | ||
671 | */ | ||
672 | rpc_delete_timer(task); | ||
673 | 637 | ||
674 | /* | 638 | /* |
675 | * Execute any pending callback. | 639 | * Execute any pending callback. |
@@ -838,7 +802,6 @@ EXPORT_SYMBOL_GPL(rpc_free); | |||
838 | static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data) | 802 | static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data) |
839 | { | 803 | { |
840 | memset(task, 0, sizeof(*task)); | 804 | memset(task, 0, sizeof(*task)); |
841 | setup_timer(&task->tk_timer, rpc_run_timer, (unsigned long)task); | ||
842 | atomic_set(&task->tk_count, 1); | 805 | atomic_set(&task->tk_count, 1); |
843 | task->tk_flags = task_setup_data->flags; | 806 | task->tk_flags = task_setup_data->flags; |
844 | task->tk_ops = task_setup_data->callback_ops; | 807 | task->tk_ops = task_setup_data->callback_ops; |
@@ -971,9 +934,6 @@ static void rpc_release_task(struct rpc_task *task) | |||
971 | } | 934 | } |
972 | BUG_ON (RPC_IS_QUEUED(task)); | 935 | BUG_ON (RPC_IS_QUEUED(task)); |
973 | 936 | ||
974 | /* Synchronously delete any running timer */ | ||
975 | rpc_delete_timer(task); | ||
976 | |||
977 | #ifdef RPC_DEBUG | 937 | #ifdef RPC_DEBUG |
978 | task->tk_magic = 0; | 938 | task->tk_magic = 0; |
979 | #endif | 939 | #endif |