aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/sched.c78
1 files changed, 59 insertions, 19 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 2d74a1672028..82d158dad16d 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -264,6 +264,35 @@ void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
264} 264}
265EXPORT_SYMBOL(rpc_init_wait_queue); 265EXPORT_SYMBOL(rpc_init_wait_queue);
266 266
267static int rpc_wait_bit_interruptible(void *word)
268{
269 if (signal_pending(current))
270 return -ERESTARTSYS;
271 schedule();
272 return 0;
273}
274
275/*
276 * Mark an RPC call as having completed by clearing the 'active' bit
277 */
278static inline void rpc_mark_complete_task(struct rpc_task *task)
279{
280 rpc_clear_active(task);
281 wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE);
282}
283
284/*
285 * Allow callers to wait for completion of an RPC call
286 */
287int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *))
288{
289 if (action == NULL)
290 action = rpc_wait_bit_interruptible;
291 return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE,
292 action, TASK_INTERRUPTIBLE);
293}
294EXPORT_SYMBOL(__rpc_wait_for_completion_task);
295
267/* 296/*
268 * Make an RPC task runnable. 297 * Make an RPC task runnable.
269 * 298 *
@@ -299,10 +328,7 @@ static void rpc_make_runnable(struct rpc_task *task)
299static inline void 328static inline void
300rpc_schedule_run(struct rpc_task *task) 329rpc_schedule_run(struct rpc_task *task)
301{ 330{
302 /* Don't run a child twice! */ 331 rpc_set_active(task);
303 if (RPC_IS_ACTIVATED(task))
304 return;
305 task->tk_active = 1;
306 rpc_make_runnable(task); 332 rpc_make_runnable(task);
307} 333}
308 334
@@ -324,8 +350,7 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
324 } 350 }
325 351
326 /* Mark the task as being activated if so needed */ 352 /* Mark the task as being activated if so needed */
327 if (!RPC_IS_ACTIVATED(task)) 353 rpc_set_active(task);
328 task->tk_active = 1;
329 354
330 __rpc_add_wait_queue(q, task); 355 __rpc_add_wait_queue(q, task);
331 356
@@ -580,14 +605,6 @@ void rpc_exit_task(struct rpc_task *task)
580} 605}
581EXPORT_SYMBOL(rpc_exit_task); 606EXPORT_SYMBOL(rpc_exit_task);
582 607
583static int rpc_wait_bit_interruptible(void *word)
584{
585 if (signal_pending(current))
586 return -ERESTARTSYS;
587 schedule();
588 return 0;
589}
590
591/* 608/*
592 * This is the RPC `scheduler' (or rather, the finite state machine). 609 * This is the RPC `scheduler' (or rather, the finite state machine).
593 */ 610 */
@@ -680,6 +697,8 @@ static int __rpc_execute(struct rpc_task *task)
680 dprintk("RPC: %4d exit() = %d\n", task->tk_pid, task->tk_status); 697 dprintk("RPC: %4d exit() = %d\n", task->tk_pid, task->tk_status);
681 status = task->tk_status; 698 status = task->tk_status;
682 699
700 /* Wake up anyone who is waiting for task completion */
701 rpc_mark_complete_task(task);
683 /* Release all resources associated with the task */ 702 /* Release all resources associated with the task */
684 rpc_release_task(task); 703 rpc_release_task(task);
685 return status; 704 return status;
@@ -697,9 +716,7 @@ static int __rpc_execute(struct rpc_task *task)
697int 716int
698rpc_execute(struct rpc_task *task) 717rpc_execute(struct rpc_task *task)
699{ 718{
700 BUG_ON(task->tk_active); 719 rpc_set_active(task);
701
702 task->tk_active = 1;
703 rpc_set_running(task); 720 rpc_set_running(task);
704 return __rpc_execute(task); 721 return __rpc_execute(task);
705} 722}
@@ -761,6 +778,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
761 init_timer(&task->tk_timer); 778 init_timer(&task->tk_timer);
762 task->tk_timer.data = (unsigned long) task; 779 task->tk_timer.data = (unsigned long) task;
763 task->tk_timer.function = (void (*)(unsigned long)) rpc_run_timer; 780 task->tk_timer.function = (void (*)(unsigned long)) rpc_run_timer;
781 atomic_set(&task->tk_count, 1);
764 task->tk_client = clnt; 782 task->tk_client = clnt;
765 task->tk_flags = flags; 783 task->tk_flags = flags;
766 task->tk_ops = tk_ops; 784 task->tk_ops = tk_ops;
@@ -848,11 +866,13 @@ void rpc_release_task(struct rpc_task *task)
848{ 866{
849 const struct rpc_call_ops *tk_ops = task->tk_ops; 867 const struct rpc_call_ops *tk_ops = task->tk_ops;
850 void *calldata = task->tk_calldata; 868 void *calldata = task->tk_calldata;
851 dprintk("RPC: %4d release task\n", task->tk_pid);
852 869
853#ifdef RPC_DEBUG 870#ifdef RPC_DEBUG
854 BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID); 871 BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
855#endif 872#endif
873 if (!atomic_dec_and_test(&task->tk_count))
874 return;
875 dprintk("RPC: %4d release task\n", task->tk_pid);
856 876
857 /* Remove from global task list */ 877 /* Remove from global task list */
858 spin_lock(&rpc_sched_lock); 878 spin_lock(&rpc_sched_lock);
@@ -860,7 +880,6 @@ void rpc_release_task(struct rpc_task *task)
860 spin_unlock(&rpc_sched_lock); 880 spin_unlock(&rpc_sched_lock);
861 881
862 BUG_ON (RPC_IS_QUEUED(task)); 882 BUG_ON (RPC_IS_QUEUED(task));
863 task->tk_active = 0;
864 883
865 /* Synchronously delete any running timer */ 884 /* Synchronously delete any running timer */
866 rpc_delete_timer(task); 885 rpc_delete_timer(task);
@@ -886,6 +905,27 @@ void rpc_release_task(struct rpc_task *task)
886} 905}
887 906
888/** 907/**
908 * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
909 * @clnt - pointer to RPC client
910 * @flags - RPC flags
911 * @ops - RPC call ops
912 * @data - user call data
913 */
914struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
915 const struct rpc_call_ops *ops,
916 void *data)
917{
918 struct rpc_task *task;
919 task = rpc_new_task(clnt, flags, ops, data);
920 if (task == NULL)
921 return ERR_PTR(-ENOMEM);
922 atomic_inc(&task->tk_count);
923 rpc_execute(task);
924 return task;
925}
926EXPORT_SYMBOL(rpc_run_task);
927
928/**
889 * rpc_find_parent - find the parent of a child task. 929 * rpc_find_parent - find the parent of a child task.
890 * @child: child task 930 * @child: child task
891 * 931 *