diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 12 | ||||
-rw-r--r-- | include/linux/sunrpc/sched.h | 8 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 19 | ||||
-rw-r--r-- | net/sunrpc/pmap_clnt.c | 2 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 80 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 1 |
6 files changed, 65 insertions, 57 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8118036cc449..93ac05889cbc 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -636,7 +636,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
636 | smp_wmb(); | 636 | smp_wmb(); |
637 | } else | 637 | } else |
638 | status = data->rpc_status; | 638 | status = data->rpc_status; |
639 | rpc_release_task(task); | 639 | rpc_put_task(task); |
640 | return status; | 640 | return status; |
641 | } | 641 | } |
642 | 642 | ||
@@ -742,7 +742,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
742 | smp_wmb(); | 742 | smp_wmb(); |
743 | } else | 743 | } else |
744 | status = data->rpc_status; | 744 | status = data->rpc_status; |
745 | rpc_release_task(task); | 745 | rpc_put_task(task); |
746 | if (status != 0) | 746 | if (status != 0) |
747 | return status; | 747 | return status; |
748 | 748 | ||
@@ -3067,7 +3067,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3067 | if (status == 0) | 3067 | if (status == 0) |
3068 | nfs_post_op_update_inode(inode, &data->fattr); | 3068 | nfs_post_op_update_inode(inode, &data->fattr); |
3069 | } | 3069 | } |
3070 | rpc_release_task(task); | 3070 | rpc_put_task(task); |
3071 | return status; | 3071 | return status; |
3072 | } | 3072 | } |
3073 | 3073 | ||
@@ -3314,7 +3314,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
3314 | if (IS_ERR(task)) | 3314 | if (IS_ERR(task)) |
3315 | goto out; | 3315 | goto out; |
3316 | status = nfs4_wait_for_completion_rpc_task(task); | 3316 | status = nfs4_wait_for_completion_rpc_task(task); |
3317 | rpc_release_task(task); | 3317 | rpc_put_task(task); |
3318 | out: | 3318 | out: |
3319 | return status; | 3319 | return status; |
3320 | } | 3320 | } |
@@ -3430,7 +3430,7 @@ static void nfs4_lock_release(void *calldata) | |||
3430 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, | 3430 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, |
3431 | data->arg.lock_seqid); | 3431 | data->arg.lock_seqid); |
3432 | if (!IS_ERR(task)) | 3432 | if (!IS_ERR(task)) |
3433 | rpc_release_task(task); | 3433 | rpc_put_task(task); |
3434 | dprintk("%s: cancelling lock!\n", __FUNCTION__); | 3434 | dprintk("%s: cancelling lock!\n", __FUNCTION__); |
3435 | } else | 3435 | } else |
3436 | nfs_free_seqid(data->arg.lock_seqid); | 3436 | nfs_free_seqid(data->arg.lock_seqid); |
@@ -3472,7 +3472,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
3472 | ret = -EAGAIN; | 3472 | ret = -EAGAIN; |
3473 | } else | 3473 | } else |
3474 | data->cancelled = 1; | 3474 | data->cancelled = 1; |
3475 | rpc_release_task(task); | 3475 | rpc_put_task(task); |
3476 | dprintk("%s: done, ret = %d!\n", __FUNCTION__, ret); | 3476 | dprintk("%s: done, ret = %d!\n", __FUNCTION__, ret); |
3477 | return ret; | 3477 | return ret; |
3478 | } | 3478 | } |
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index f399c138f79d..9fdb8c9d09f2 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -178,13 +178,6 @@ struct rpc_call_ops { | |||
178 | } while (0) | 178 | } while (0) |
179 | 179 | ||
180 | #define RPC_IS_ACTIVATED(t) (test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)) | 180 | #define RPC_IS_ACTIVATED(t) (test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)) |
181 | #define rpc_set_active(t) (set_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)) | ||
182 | #define rpc_clear_active(t) \ | ||
183 | do { \ | ||
184 | smp_mb__before_clear_bit(); \ | ||
185 | clear_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate); \ | ||
186 | smp_mb__after_clear_bit(); \ | ||
187 | } while(0) | ||
188 | 181 | ||
189 | /* | 182 | /* |
190 | * Task priorities. | 183 | * Task priorities. |
@@ -254,6 +247,7 @@ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, | |||
254 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, | 247 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, |
255 | int flags, const struct rpc_call_ops *ops, | 248 | int flags, const struct rpc_call_ops *ops, |
256 | void *data); | 249 | void *data); |
250 | void rpc_put_task(struct rpc_task *); | ||
257 | void rpc_release_task(struct rpc_task *); | 251 | void rpc_release_task(struct rpc_task *); |
258 | void rpc_exit_task(struct rpc_task *); | 252 | void rpc_exit_task(struct rpc_task *); |
259 | void rpc_killall_tasks(struct rpc_clnt *); | 253 | void rpc_killall_tasks(struct rpc_clnt *); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index dfeea4fea95a..a323abc7ea85 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -466,10 +466,9 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | |||
466 | 466 | ||
467 | BUG_ON(flags & RPC_TASK_ASYNC); | 467 | BUG_ON(flags & RPC_TASK_ASYNC); |
468 | 468 | ||
469 | status = -ENOMEM; | ||
470 | task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL); | 469 | task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL); |
471 | if (task == NULL) | 470 | if (task == NULL) |
472 | goto out; | 471 | return -ENOMEM; |
473 | 472 | ||
474 | /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */ | 473 | /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */ |
475 | rpc_task_sigmask(task, &oldset); | 474 | rpc_task_sigmask(task, &oldset); |
@@ -478,15 +477,17 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | |||
478 | 477 | ||
479 | /* Set up the call info struct and execute the task */ | 478 | /* Set up the call info struct and execute the task */ |
480 | status = task->tk_status; | 479 | status = task->tk_status; |
481 | if (status == 0) { | 480 | if (status != 0) { |
482 | atomic_inc(&task->tk_count); | 481 | rpc_release_task(task); |
483 | status = rpc_execute(task); | 482 | goto out; |
484 | if (status == 0) | ||
485 | status = task->tk_status; | ||
486 | } | 483 | } |
487 | rpc_restore_sigmask(&oldset); | 484 | atomic_inc(&task->tk_count); |
488 | rpc_release_task(task); | 485 | status = rpc_execute(task); |
486 | if (status == 0) | ||
487 | status = task->tk_status; | ||
488 | rpc_put_task(task); | ||
489 | out: | 489 | out: |
490 | rpc_restore_sigmask(&oldset); | ||
490 | return status; | 491 | return status; |
491 | } | 492 | } |
492 | 493 | ||
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c index e52afab413de..8d2e10fc3df9 100644 --- a/net/sunrpc/pmap_clnt.c +++ b/net/sunrpc/pmap_clnt.c | |||
@@ -134,7 +134,7 @@ void rpc_getport(struct rpc_task *task) | |||
134 | child = rpc_run_task(pmap_clnt, RPC_TASK_ASYNC, &pmap_getport_ops, map); | 134 | child = rpc_run_task(pmap_clnt, RPC_TASK_ASYNC, &pmap_getport_ops, map); |
135 | if (IS_ERR(child)) | 135 | if (IS_ERR(child)) |
136 | goto bailout; | 136 | goto bailout; |
137 | rpc_release_task(child); | 137 | rpc_put_task(child); |
138 | 138 | ||
139 | task->tk_xprt->stat.bind_count++; | 139 | task->tk_xprt->stat.bind_count++; |
140 | return; | 140 | return; |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index b57d4062d429..66d01365f3a5 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -266,12 +266,28 @@ static int rpc_wait_bit_interruptible(void *word) | |||
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | 268 | ||
269 | static void rpc_set_active(struct rpc_task *task) | ||
270 | { | ||
271 | if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0) | ||
272 | return; | ||
273 | spin_lock(&rpc_sched_lock); | ||
274 | #ifdef RPC_DEBUG | ||
275 | task->tk_magic = RPC_TASK_MAGIC_ID; | ||
276 | task->tk_pid = rpc_task_id++; | ||
277 | #endif | ||
278 | /* Add to global list of all tasks */ | ||
279 | list_add_tail(&task->tk_task, &all_tasks); | ||
280 | spin_unlock(&rpc_sched_lock); | ||
281 | } | ||
282 | |||
269 | /* | 283 | /* |
270 | * Mark an RPC call as having completed by clearing the 'active' bit | 284 | * Mark an RPC call as having completed by clearing the 'active' bit |
271 | */ | 285 | */ |
272 | static inline void rpc_mark_complete_task(struct rpc_task *task) | 286 | static void rpc_mark_complete_task(struct rpc_task *task) |
273 | { | 287 | { |
274 | rpc_clear_active(task); | 288 | smp_mb__before_clear_bit(); |
289 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | ||
290 | smp_mb__after_clear_bit(); | ||
275 | wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE); | 291 | wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE); |
276 | } | 292 | } |
277 | 293 | ||
@@ -335,9 +351,6 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
335 | return; | 351 | return; |
336 | } | 352 | } |
337 | 353 | ||
338 | /* Mark the task as being activated if so needed */ | ||
339 | rpc_set_active(task); | ||
340 | |||
341 | __rpc_add_wait_queue(q, task); | 354 | __rpc_add_wait_queue(q, task); |
342 | 355 | ||
343 | BUG_ON(task->tk_callback != NULL); | 356 | BUG_ON(task->tk_callback != NULL); |
@@ -348,6 +361,9 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
348 | void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | 361 | void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, |
349 | rpc_action action, rpc_action timer) | 362 | rpc_action action, rpc_action timer) |
350 | { | 363 | { |
364 | /* Mark the task as being activated if so needed */ | ||
365 | rpc_set_active(task); | ||
366 | |||
351 | /* | 367 | /* |
352 | * Protect the queue operations. | 368 | * Protect the queue operations. |
353 | */ | 369 | */ |
@@ -673,8 +689,6 @@ static int __rpc_execute(struct rpc_task *task) | |||
673 | } | 689 | } |
674 | 690 | ||
675 | dprintk("RPC: %4d, return %d, status %d\n", task->tk_pid, status, task->tk_status); | 691 | dprintk("RPC: %4d, return %d, status %d\n", task->tk_pid, status, task->tk_status); |
676 | /* Wake up anyone who is waiting for task completion */ | ||
677 | rpc_mark_complete_task(task); | ||
678 | /* Release all resources associated with the task */ | 692 | /* Release all resources associated with the task */ |
679 | rpc_release_task(task); | 693 | rpc_release_task(task); |
680 | return status; | 694 | return status; |
@@ -788,15 +802,6 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons | |||
788 | task->tk_flags |= RPC_TASK_NOINTR; | 802 | task->tk_flags |= RPC_TASK_NOINTR; |
789 | } | 803 | } |
790 | 804 | ||
791 | #ifdef RPC_DEBUG | ||
792 | task->tk_magic = RPC_TASK_MAGIC_ID; | ||
793 | task->tk_pid = rpc_task_id++; | ||
794 | #endif | ||
795 | /* Add to global list of all tasks */ | ||
796 | spin_lock(&rpc_sched_lock); | ||
797 | list_add_tail(&task->tk_task, &all_tasks); | ||
798 | spin_unlock(&rpc_sched_lock); | ||
799 | |||
800 | BUG_ON(task->tk_ops == NULL); | 805 | BUG_ON(task->tk_ops == NULL); |
801 | 806 | ||
802 | /* starting timestamp */ | 807 | /* starting timestamp */ |
@@ -849,16 +854,35 @@ cleanup: | |||
849 | goto out; | 854 | goto out; |
850 | } | 855 | } |
851 | 856 | ||
852 | void rpc_release_task(struct rpc_task *task) | 857 | |
858 | void rpc_put_task(struct rpc_task *task) | ||
853 | { | 859 | { |
854 | const struct rpc_call_ops *tk_ops = task->tk_ops; | 860 | const struct rpc_call_ops *tk_ops = task->tk_ops; |
855 | void *calldata = task->tk_calldata; | 861 | void *calldata = task->tk_calldata; |
856 | 862 | ||
863 | if (!atomic_dec_and_test(&task->tk_count)) | ||
864 | return; | ||
865 | /* Release resources */ | ||
866 | if (task->tk_rqstp) | ||
867 | xprt_release(task); | ||
868 | if (task->tk_msg.rpc_cred) | ||
869 | rpcauth_unbindcred(task); | ||
870 | if (task->tk_client) { | ||
871 | rpc_release_client(task->tk_client); | ||
872 | task->tk_client = NULL; | ||
873 | } | ||
874 | if (task->tk_flags & RPC_TASK_DYNAMIC) | ||
875 | rpc_free_task(task); | ||
876 | if (tk_ops->rpc_release) | ||
877 | tk_ops->rpc_release(calldata); | ||
878 | } | ||
879 | EXPORT_SYMBOL(rpc_put_task); | ||
880 | |||
881 | void rpc_release_task(struct rpc_task *task) | ||
882 | { | ||
857 | #ifdef RPC_DEBUG | 883 | #ifdef RPC_DEBUG |
858 | BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID); | 884 | BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID); |
859 | #endif | 885 | #endif |
860 | if (!atomic_dec_and_test(&task->tk_count)) | ||
861 | return; | ||
862 | dprintk("RPC: %4d release task\n", task->tk_pid); | 886 | dprintk("RPC: %4d release task\n", task->tk_pid); |
863 | 887 | ||
864 | /* Remove from global task list */ | 888 | /* Remove from global task list */ |
@@ -871,23 +895,13 @@ void rpc_release_task(struct rpc_task *task) | |||
871 | /* Synchronously delete any running timer */ | 895 | /* Synchronously delete any running timer */ |
872 | rpc_delete_timer(task); | 896 | rpc_delete_timer(task); |
873 | 897 | ||
874 | /* Release resources */ | ||
875 | if (task->tk_rqstp) | ||
876 | xprt_release(task); | ||
877 | if (task->tk_msg.rpc_cred) | ||
878 | rpcauth_unbindcred(task); | ||
879 | if (task->tk_client) { | ||
880 | rpc_release_client(task->tk_client); | ||
881 | task->tk_client = NULL; | ||
882 | } | ||
883 | |||
884 | #ifdef RPC_DEBUG | 898 | #ifdef RPC_DEBUG |
885 | task->tk_magic = 0; | 899 | task->tk_magic = 0; |
886 | #endif | 900 | #endif |
887 | if (task->tk_flags & RPC_TASK_DYNAMIC) | 901 | /* Wake up anyone who is waiting for task completion */ |
888 | rpc_free_task(task); | 902 | rpc_mark_complete_task(task); |
889 | if (tk_ops->rpc_release) | 903 | |
890 | tk_ops->rpc_release(calldata); | 904 | rpc_put_task(task); |
891 | } | 905 | } |
892 | 906 | ||
893 | /** | 907 | /** |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 192dff5dabcb..faaf81e97720 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -33,7 +33,6 @@ EXPORT_SYMBOL(rpciod_down); | |||
33 | EXPORT_SYMBOL(rpciod_up); | 33 | EXPORT_SYMBOL(rpciod_up); |
34 | EXPORT_SYMBOL(rpc_new_task); | 34 | EXPORT_SYMBOL(rpc_new_task); |
35 | EXPORT_SYMBOL(rpc_wake_up_status); | 35 | EXPORT_SYMBOL(rpc_wake_up_status); |
36 | EXPORT_SYMBOL(rpc_release_task); | ||
37 | 36 | ||
38 | /* RPC client functions */ | 37 | /* RPC client functions */ |
39 | EXPORT_SYMBOL(rpc_clone_client); | 38 | EXPORT_SYMBOL(rpc_clone_client); |