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.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 86aa897e7b08..29b1c1441f4d 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -40,6 +40,7 @@ static mempool_t *rpc_buffer_mempool __read_mostly;
40 40
41static void rpc_async_schedule(struct work_struct *); 41static void rpc_async_schedule(struct work_struct *);
42static void rpc_release_task(struct rpc_task *task); 42static void rpc_release_task(struct rpc_task *task);
43static void __rpc_queue_timer_fn(unsigned long ptr);
43 44
44/* 45/*
45 * RPC tasks sit here while waiting for conditions to improve. 46 * RPC tasks sit here while waiting for conditions to improve.
@@ -59,8 +60,18 @@ struct workqueue_struct *rpciod_workqueue;
59static void 60static void
60__rpc_disable_timer(struct rpc_task *task) 61__rpc_disable_timer(struct rpc_task *task)
61{ 62{
63 if (task->tk_timeout == 0)
64 return;
62 dprintk("RPC: %5u disabling timer\n", task->tk_pid); 65 dprintk("RPC: %5u disabling timer\n", task->tk_pid);
63 task->tk_timeout = 0; 66 task->tk_timeout = 0;
67 list_del(&task->u.tk_wait.timer_list);
68}
69
70static void
71rpc_set_queue_timer(struct rpc_wait_queue *queue, unsigned long expires)
72{
73 queue->timer_list.expires = expires;
74 mod_timer(&queue->timer_list.timer, expires);
64} 75}
65 76
66/* 77/*
@@ -153,7 +164,6 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
153 list_move(&t->u.tk_wait.list, &task->u.tk_wait.list); 164 list_move(&t->u.tk_wait.list, &task->u.tk_wait.list);
154 list_splice_init(&task->u.tk_wait.links, &t->u.tk_wait.links); 165 list_splice_init(&task->u.tk_wait.links, &t->u.tk_wait.links);
155 } 166 }
156 list_del(&task->u.tk_wait.list);
157} 167}
158 168
159/* 169/*
@@ -162,10 +172,10 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
162 */ 172 */
163static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task) 173static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
164{ 174{
175 __rpc_disable_timer(task);
165 if (RPC_IS_PRIORITY(queue)) 176 if (RPC_IS_PRIORITY(queue))
166 __rpc_remove_wait_queue_priority(task); 177 __rpc_remove_wait_queue_priority(task);
167 else 178 list_del(&task->u.tk_wait.list);
168 list_del(&task->u.tk_wait.list);
169 queue->qlen--; 179 queue->qlen--;
170 dprintk("RPC: %5u removed from queue %p \"%s\"\n", 180 dprintk("RPC: %5u removed from queue %p \"%s\"\n",
171 task->tk_pid, queue, rpc_qname(queue)); 181 task->tk_pid, queue, rpc_qname(queue));
@@ -198,6 +208,9 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c
198 INIT_LIST_HEAD(&queue->tasks[i]); 208 INIT_LIST_HEAD(&queue->tasks[i]);
199 queue->maxpriority = nr_queues - 1; 209 queue->maxpriority = nr_queues - 1;
200 rpc_reset_waitqueue_priority(queue); 210 rpc_reset_waitqueue_priority(queue);
211 queue->qlen = 0;
212 setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue);
213 INIT_LIST_HEAD(&queue->timer_list.list);
201#ifdef RPC_DEBUG 214#ifdef RPC_DEBUG
202 queue->name = qname; 215 queue->name = qname;
203#endif 216#endif
@@ -216,6 +229,7 @@ EXPORT_SYMBOL_GPL(rpc_init_wait_queue);
216 229
217void rpc_destroy_wait_queue(struct rpc_wait_queue *queue) 230void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
218{ 231{
232 del_timer_sync(&queue->timer_list.timer);
219} 233}
220EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue); 234EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
221 235
@@ -369,7 +383,6 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task
369 return; 383 return;
370 } 384 }
371 385
372 __rpc_disable_timer(task);
373 __rpc_remove_wait_queue(queue, task); 386 __rpc_remove_wait_queue(queue, task);
374 387
375 rpc_make_runnable(task); 388 rpc_make_runnable(task);
@@ -562,6 +575,31 @@ static void rpc_run_timer(unsigned long ptr)
562 smp_mb__after_clear_bit(); 575 smp_mb__after_clear_bit();
563} 576}
564 577
578static void __rpc_queue_timer_fn(unsigned long ptr)
579{
580 struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr;
581 struct rpc_task *task, *n;
582 unsigned long expires, now, timeo;
583
584 spin_lock(&queue->lock);
585 expires = now = jiffies;
586 list_for_each_entry_safe(task, n, &queue->timer_list.list, u.tk_wait.timer_list) {
587 timeo = task->u.tk_wait.expires;
588 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);
591 task->tk_status = -ETIMEDOUT;
592 rpc_wake_up_task_queue_locked(queue, task);
593 continue;
594 }
595 if (expires == now || time_after(expires, timeo))
596 expires = timeo;
597 }
598 if (!list_empty(&queue->timer_list.list))
599 rpc_set_queue_timer(queue, expires);
600 spin_unlock(&queue->lock);
601}
602
565static void __rpc_atrun(struct rpc_task *task) 603static void __rpc_atrun(struct rpc_task *task)
566{ 604{
567 task->tk_status = 0; 605 task->tk_status = 0;