aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/clntproc.c38
-rw-r--r--fs/lockd/svc4proc.c15
-rw-r--r--fs/lockd/svclock.c14
-rw-r--r--fs/lockd/svcproc.c14
-rw-r--r--fs/nfs/direct.c1
-rw-r--r--fs/nfs/nfs3proc.c44
-rw-r--r--fs/nfs/nfs4proc.c107
-rw-r--r--fs/nfs/proc.c28
-rw-r--r--fs/nfs/read.c10
-rw-r--r--fs/nfs/unlink.c19
-rw-r--r--fs/nfs/write.c21
-rw-r--r--fs/nfsd/nfs4callback.c10
-rw-r--r--include/linux/lockd/lockd.h2
-rw-r--r--include/linux/nfs_fs.h12
-rw-r--r--include/linux/sunrpc/clnt.h3
-rw-r--r--include/linux/sunrpc/sched.h20
-rw-r--r--net/sunrpc/clnt.c15
-rw-r--r--net/sunrpc/sched.c53
18 files changed, 241 insertions, 185 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index c5a33648e9fd..816333cd377b 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -26,11 +26,12 @@
26static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); 26static int nlmclnt_test(struct nlm_rqst *, struct file_lock *);
27static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); 27static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
28static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); 28static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
29static void nlmclnt_unlock_callback(struct rpc_task *);
30static void nlmclnt_cancel_callback(struct rpc_task *);
31static int nlm_stat_to_errno(u32 stat); 29static int nlm_stat_to_errno(u32 stat);
32static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); 30static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
33 31
32static const struct rpc_call_ops nlmclnt_unlock_ops;
33static const struct rpc_call_ops nlmclnt_cancel_ops;
34
34/* 35/*
35 * Cookie counter for NLM requests 36 * Cookie counter for NLM requests
36 */ 37 */
@@ -399,8 +400,7 @@ in_grace_period:
399/* 400/*
400 * Generic NLM call, async version. 401 * Generic NLM call, async version.
401 */ 402 */
402int 403int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
403nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
404{ 404{
405 struct nlm_host *host = req->a_host; 405 struct nlm_host *host = req->a_host;
406 struct rpc_clnt *clnt; 406 struct rpc_clnt *clnt;
@@ -419,13 +419,12 @@ nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
419 msg.rpc_proc = &clnt->cl_procinfo[proc]; 419 msg.rpc_proc = &clnt->cl_procinfo[proc];
420 420
421 /* bootstrap and kick off the async RPC call */ 421 /* bootstrap and kick off the async RPC call */
422 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req); 422 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req);
423 423
424 return status; 424 return status;
425} 425}
426 426
427static int 427static int nlmclnt_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
428nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
429{ 428{
430 struct nlm_host *host = req->a_host; 429 struct nlm_host *host = req->a_host;
431 struct rpc_clnt *clnt; 430 struct rpc_clnt *clnt;
@@ -448,7 +447,7 @@ nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
448 /* Increment host refcount */ 447 /* Increment host refcount */
449 nlm_get_host(host); 448 nlm_get_host(host);
450 /* bootstrap and kick off the async RPC call */ 449 /* bootstrap and kick off the async RPC call */
451 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req); 450 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req);
452 if (status < 0) 451 if (status < 0)
453 nlm_release_host(host); 452 nlm_release_host(host);
454 return status; 453 return status;
@@ -664,7 +663,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
664 663
665 if (req->a_flags & RPC_TASK_ASYNC) { 664 if (req->a_flags & RPC_TASK_ASYNC) {
666 status = nlmclnt_async_call(req, NLMPROC_UNLOCK, 665 status = nlmclnt_async_call(req, NLMPROC_UNLOCK,
667 nlmclnt_unlock_callback); 666 &nlmclnt_unlock_ops);
668 /* Hrmf... Do the unlock early since locks_remove_posix() 667 /* Hrmf... Do the unlock early since locks_remove_posix()
669 * really expects us to free the lock synchronously */ 668 * really expects us to free the lock synchronously */
670 do_vfs_lock(fl); 669 do_vfs_lock(fl);
@@ -692,10 +691,9 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
692 return -ENOLCK; 691 return -ENOLCK;
693} 692}
694 693
695static void 694static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
696nlmclnt_unlock_callback(struct rpc_task *task)
697{ 695{
698 struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata; 696 struct nlm_rqst *req = data;
699 int status = req->a_res.status; 697 int status = req->a_res.status;
700 698
701 if (RPC_ASSASSINATED(task)) 699 if (RPC_ASSASSINATED(task))
@@ -722,6 +720,10 @@ die:
722 rpc_restart_call(task); 720 rpc_restart_call(task);
723} 721}
724 722
723static const struct rpc_call_ops nlmclnt_unlock_ops = {
724 .rpc_call_done = nlmclnt_unlock_callback,
725};
726
725/* 727/*
726 * Cancel a blocked lock request. 728 * Cancel a blocked lock request.
727 * We always use an async RPC call for this in order not to hang a 729 * We always use an async RPC call for this in order not to hang a
@@ -750,8 +752,7 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
750 752
751 nlmclnt_setlockargs(req, fl); 753 nlmclnt_setlockargs(req, fl);
752 754
753 status = nlmclnt_async_call(req, NLMPROC_CANCEL, 755 status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops);
754 nlmclnt_cancel_callback);
755 if (status < 0) { 756 if (status < 0) {
756 nlmclnt_release_lockargs(req); 757 nlmclnt_release_lockargs(req);
757 kfree(req); 758 kfree(req);
@@ -765,10 +766,9 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
765 return status; 766 return status;
766} 767}
767 768
768static void 769static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
769nlmclnt_cancel_callback(struct rpc_task *task)
770{ 770{
771 struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata; 771 struct nlm_rqst *req = data;
772 772
773 if (RPC_ASSASSINATED(task)) 773 if (RPC_ASSASSINATED(task))
774 goto die; 774 goto die;
@@ -807,6 +807,10 @@ retry_cancel:
807 rpc_delay(task, 30 * HZ); 807 rpc_delay(task, 30 * HZ);
808} 808}
809 809
810static const struct rpc_call_ops nlmclnt_cancel_ops = {
811 .rpc_call_done = nlmclnt_cancel_callback,
812};
813
810/* 814/*
811 * Convert an NLM status code to a generic kernel errno 815 * Convert an NLM status code to a generic kernel errno
812 */ 816 */
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 489670e21769..4063095d849e 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -22,7 +22,8 @@
22#define NLMDBG_FACILITY NLMDBG_CLIENT 22#define NLMDBG_FACILITY NLMDBG_CLIENT
23 23
24static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *); 24static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *);
25static void nlm4svc_callback_exit(struct rpc_task *); 25
26static const struct rpc_call_ops nlm4svc_callback_ops;
26 27
27/* 28/*
28 * Obtain client and file from arguments 29 * Obtain client and file from arguments
@@ -470,7 +471,6 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
470} 471}
471 472
472 473
473
474/* 474/*
475 * This is the generic lockd callback for async RPC calls 475 * This is the generic lockd callback for async RPC calls
476 */ 476 */
@@ -494,7 +494,7 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
494 call->a_host = host; 494 call->a_host = host;
495 memcpy(&call->a_args, resp, sizeof(*resp)); 495 memcpy(&call->a_args, resp, sizeof(*resp));
496 496
497 if (nlmsvc_async_call(call, proc, nlm4svc_callback_exit) < 0) 497 if (nlmsvc_async_call(call, proc, &nlm4svc_callback_ops) < 0)
498 goto error; 498 goto error;
499 499
500 return rpc_success; 500 return rpc_success;
@@ -504,10 +504,9 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
504 return rpc_system_err; 504 return rpc_system_err;
505} 505}
506 506
507static void 507static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
508nlm4svc_callback_exit(struct rpc_task *task)
509{ 508{
510 struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata; 509 struct nlm_rqst *call = data;
511 510
512 if (task->tk_status < 0) { 511 if (task->tk_status < 0) {
513 dprintk("lockd: %4d callback failed (errno = %d)\n", 512 dprintk("lockd: %4d callback failed (errno = %d)\n",
@@ -517,6 +516,10 @@ nlm4svc_callback_exit(struct rpc_task *task)
517 kfree(call); 516 kfree(call);
518} 517}
519 518
519static const struct rpc_call_ops nlm4svc_callback_ops = {
520 .rpc_call_done = nlm4svc_callback_exit,
521};
522
520/* 523/*
521 * NLM Server procedures. 524 * NLM Server procedures.
522 */ 525 */
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 49f959796b66..87d09a0d8f64 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -41,7 +41,8 @@
41 41
42static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); 42static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
43static int nlmsvc_remove_block(struct nlm_block *block); 43static int nlmsvc_remove_block(struct nlm_block *block);
44static void nlmsvc_grant_callback(struct rpc_task *task); 44
45static const struct rpc_call_ops nlmsvc_grant_ops;
45 46
46/* 47/*
47 * The list of blocked locks to retry 48 * The list of blocked locks to retry
@@ -562,7 +563,7 @@ callback:
562 /* Call the client */ 563 /* Call the client */
563 nlm_get_host(block->b_call.a_host); 564 nlm_get_host(block->b_call.a_host);
564 if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG, 565 if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG,
565 nlmsvc_grant_callback) < 0) 566 &nlmsvc_grant_ops) < 0)
566 nlm_release_host(block->b_call.a_host); 567 nlm_release_host(block->b_call.a_host);
567 up(&file->f_sema); 568 up(&file->f_sema);
568} 569}
@@ -575,10 +576,9 @@ callback:
575 * chain once more in order to have it removed by lockd itself (which can 576 * chain once more in order to have it removed by lockd itself (which can
576 * then sleep on the file semaphore without disrupting e.g. the nfs client). 577 * then sleep on the file semaphore without disrupting e.g. the nfs client).
577 */ 578 */
578static void 579static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
579nlmsvc_grant_callback(struct rpc_task *task)
580{ 580{
581 struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata; 581 struct nlm_rqst *call = data;
582 struct nlm_block *block; 582 struct nlm_block *block;
583 unsigned long timeout; 583 unsigned long timeout;
584 struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client); 584 struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client);
@@ -614,6 +614,10 @@ nlmsvc_grant_callback(struct rpc_task *task)
614 nlm_release_host(call->a_host); 614 nlm_release_host(call->a_host);
615} 615}
616 616
617static const struct rpc_call_ops nlmsvc_grant_ops = {
618 .rpc_call_done = nlmsvc_grant_callback,
619};
620
617/* 621/*
618 * We received a GRANT_RES callback. Try to find the corresponding 622 * We received a GRANT_RES callback. Try to find the corresponding
619 * block. 623 * block.
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 757e344cf200..3bc437e0cf5b 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -23,7 +23,8 @@
23#define NLMDBG_FACILITY NLMDBG_CLIENT 23#define NLMDBG_FACILITY NLMDBG_CLIENT
24 24
25static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *); 25static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *);
26static void nlmsvc_callback_exit(struct rpc_task *); 26
27static const struct rpc_call_ops nlmsvc_callback_ops;
27 28
28#ifdef CONFIG_LOCKD_V4 29#ifdef CONFIG_LOCKD_V4
29static u32 30static u32
@@ -518,7 +519,7 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
518 call->a_host = host; 519 call->a_host = host;
519 memcpy(&call->a_args, resp, sizeof(*resp)); 520 memcpy(&call->a_args, resp, sizeof(*resp));
520 521
521 if (nlmsvc_async_call(call, proc, nlmsvc_callback_exit) < 0) 522 if (nlmsvc_async_call(call, proc, &nlmsvc_callback_ops) < 0)
522 goto error; 523 goto error;
523 524
524 return rpc_success; 525 return rpc_success;
@@ -528,10 +529,9 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
528 return rpc_system_err; 529 return rpc_system_err;
529} 530}
530 531
531static void 532static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
532nlmsvc_callback_exit(struct rpc_task *task)
533{ 533{
534 struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata; 534 struct nlm_rqst *call = data;
535 535
536 if (task->tk_status < 0) { 536 if (task->tk_status < 0) {
537 dprintk("lockd: %4d callback failed (errno = %d)\n", 537 dprintk("lockd: %4d callback failed (errno = %d)\n",
@@ -541,6 +541,10 @@ nlmsvc_callback_exit(struct rpc_task *task)
541 kfree(call); 541 kfree(call);
542} 542}
543 543
544static const struct rpc_call_ops nlmsvc_callback_ops = {
545 .rpc_call_done = nlmsvc_callback_exit,
546};
547
544/* 548/*
545 * NLM Server procedures. 549 * NLM Server procedures.
546 */ 550 */
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 079228817603..a834423942c7 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -269,7 +269,6 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq,
269 269
270 data->task.tk_cookie = (unsigned long) inode; 270 data->task.tk_cookie = (unsigned long) inode;
271 data->task.tk_calldata = data; 271 data->task.tk_calldata = data;
272 data->task.tk_release = nfs_readdata_release;
273 data->complete = nfs_direct_read_result; 272 data->complete = nfs_direct_read_result;
274 273
275 lock_kernel(); 274 lock_kernel();
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 92c870d19ccd..c172a7584646 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -732,19 +732,23 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
732 732
733extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); 733extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
734 734
735static void 735static void nfs3_read_done(struct rpc_task *task, void *calldata)
736nfs3_read_done(struct rpc_task *task)
737{ 736{
738 struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; 737 struct nfs_read_data *data = calldata;
739 738
740 if (nfs3_async_handle_jukebox(task)) 739 if (nfs3_async_handle_jukebox(task))
741 return; 740 return;
742 /* Call back common NFS readpage processing */ 741 /* Call back common NFS readpage processing */
743 if (task->tk_status >= 0) 742 if (task->tk_status >= 0)
744 nfs_refresh_inode(data->inode, &data->fattr); 743 nfs_refresh_inode(data->inode, &data->fattr);
745 nfs_readpage_result(task); 744 nfs_readpage_result(task, calldata);
746} 745}
747 746
747static const struct rpc_call_ops nfs3_read_ops = {
748 .rpc_call_done = nfs3_read_done,
749 .rpc_release = nfs_readdata_release,
750};
751
748static void 752static void
749nfs3_proc_read_setup(struct nfs_read_data *data) 753nfs3_proc_read_setup(struct nfs_read_data *data)
750{ 754{
@@ -762,23 +766,26 @@ nfs3_proc_read_setup(struct nfs_read_data *data)
762 flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); 766 flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
763 767
764 /* Finalize the task. */ 768 /* Finalize the task. */
765 rpc_init_task(task, NFS_CLIENT(inode), nfs3_read_done, flags); 769 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_read_ops, data);
766 rpc_call_setup(task, &msg, 0); 770 rpc_call_setup(task, &msg, 0);
767} 771}
768 772
769static void 773static void nfs3_write_done(struct rpc_task *task, void *calldata)
770nfs3_write_done(struct rpc_task *task)
771{ 774{
772 struct nfs_write_data *data; 775 struct nfs_write_data *data = calldata;
773 776
774 if (nfs3_async_handle_jukebox(task)) 777 if (nfs3_async_handle_jukebox(task))
775 return; 778 return;
776 data = (struct nfs_write_data *)task->tk_calldata;
777 if (task->tk_status >= 0) 779 if (task->tk_status >= 0)
778 nfs_post_op_update_inode(data->inode, data->res.fattr); 780 nfs_post_op_update_inode(data->inode, data->res.fattr);
779 nfs_writeback_done(task); 781 nfs_writeback_done(task, calldata);
780} 782}
781 783
784static const struct rpc_call_ops nfs3_write_ops = {
785 .rpc_call_done = nfs3_write_done,
786 .rpc_release = nfs_writedata_release,
787};
788
782static void 789static void
783nfs3_proc_write_setup(struct nfs_write_data *data, int how) 790nfs3_proc_write_setup(struct nfs_write_data *data, int how)
784{ 791{
@@ -806,23 +813,26 @@ nfs3_proc_write_setup(struct nfs_write_data *data, int how)
806 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; 813 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
807 814
808 /* Finalize the task. */ 815 /* Finalize the task. */
809 rpc_init_task(task, NFS_CLIENT(inode), nfs3_write_done, flags); 816 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_write_ops, data);
810 rpc_call_setup(task, &msg, 0); 817 rpc_call_setup(task, &msg, 0);
811} 818}
812 819
813static void 820static void nfs3_commit_done(struct rpc_task *task, void *calldata)
814nfs3_commit_done(struct rpc_task *task)
815{ 821{
816 struct nfs_write_data *data; 822 struct nfs_write_data *data = calldata;
817 823
818 if (nfs3_async_handle_jukebox(task)) 824 if (nfs3_async_handle_jukebox(task))
819 return; 825 return;
820 data = (struct nfs_write_data *)task->tk_calldata;
821 if (task->tk_status >= 0) 826 if (task->tk_status >= 0)
822 nfs_post_op_update_inode(data->inode, data->res.fattr); 827 nfs_post_op_update_inode(data->inode, data->res.fattr);
823 nfs_commit_done(task); 828 nfs_commit_done(task, calldata);
824} 829}
825 830
831static const struct rpc_call_ops nfs3_commit_ops = {
832 .rpc_call_done = nfs3_commit_done,
833 .rpc_release = nfs_commit_release,
834};
835
826static void 836static void
827nfs3_proc_commit_setup(struct nfs_write_data *data, int how) 837nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
828{ 838{
@@ -840,7 +850,7 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
840 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; 850 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
841 851
842 /* Finalize the task. */ 852 /* Finalize the task. */
843 rpc_init_task(task, NFS_CLIENT(inode), nfs3_commit_done, flags); 853 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_commit_ops, data);
844 rpc_call_setup(task, &msg, 0); 854 rpc_call_setup(task, &msg, 0);
845} 855}
846 856
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f988a9417b13..3d5d3c07d621 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -196,14 +196,12 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf
196 196
197/* Helper for asynchronous RPC calls */ 197/* Helper for asynchronous RPC calls */
198static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin, 198static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin,
199 rpc_action tk_exit, void *calldata) 199 const struct rpc_call_ops *tk_ops, void *calldata)
200{ 200{
201 struct rpc_task *task; 201 struct rpc_task *task;
202 202
203 if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC))) 203 if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata)))
204 return -ENOMEM; 204 return -ENOMEM;
205
206 task->tk_calldata = calldata;
207 task->tk_action = tk_begin; 205 task->tk_action = tk_begin;
208 rpc_execute(task); 206 rpc_execute(task);
209 return 0; 207 return 0;
@@ -867,10 +865,10 @@ struct nfs4_closedata {
867 struct nfs_fattr fattr; 865 struct nfs_fattr fattr;
868}; 866};
869 867
870static void nfs4_free_closedata(struct nfs4_closedata *calldata) 868static void nfs4_free_closedata(void *data)
871{ 869{
872 struct nfs4_state *state = calldata->state; 870 struct nfs4_closedata *calldata = data;
873 struct nfs4_state_owner *sp = state->owner; 871 struct nfs4_state_owner *sp = calldata->state->owner;
874 872
875 nfs4_put_open_state(calldata->state); 873 nfs4_put_open_state(calldata->state);
876 nfs_free_seqid(calldata->arg.seqid); 874 nfs_free_seqid(calldata->arg.seqid);
@@ -878,9 +876,9 @@ static void nfs4_free_closedata(struct nfs4_closedata *calldata)
878 kfree(calldata); 876 kfree(calldata);
879} 877}
880 878
881static void nfs4_close_done(struct rpc_task *task) 879static void nfs4_close_done(struct rpc_task *task, void *data)
882{ 880{
883 struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; 881 struct nfs4_closedata *calldata = data;
884 struct nfs4_state *state = calldata->state; 882 struct nfs4_state *state = calldata->state;
885 struct nfs_server *server = NFS_SERVER(calldata->inode); 883 struct nfs_server *server = NFS_SERVER(calldata->inode);
886 884
@@ -904,7 +902,6 @@ static void nfs4_close_done(struct rpc_task *task)
904 } 902 }
905 } 903 }
906 nfs_refresh_inode(calldata->inode, calldata->res.fattr); 904 nfs_refresh_inode(calldata->inode, calldata->res.fattr);
907 nfs4_free_closedata(calldata);
908} 905}
909 906
910static void nfs4_close_begin(struct rpc_task *task) 907static void nfs4_close_begin(struct rpc_task *task)
@@ -918,10 +915,8 @@ static void nfs4_close_begin(struct rpc_task *task)
918 .rpc_cred = state->owner->so_cred, 915 .rpc_cred = state->owner->so_cred,
919 }; 916 };
920 int mode = 0, old_mode; 917 int mode = 0, old_mode;
921 int status;
922 918
923 status = nfs_wait_on_sequence(calldata->arg.seqid, task); 919 if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
924 if (status != 0)
925 return; 920 return;
926 /* Recalculate the new open mode in case someone reopened the file 921 /* Recalculate the new open mode in case someone reopened the file
927 * while we were waiting in line to be scheduled. 922 * while we were waiting in line to be scheduled.
@@ -937,9 +932,8 @@ static void nfs4_close_begin(struct rpc_task *task)
937 spin_unlock(&calldata->inode->i_lock); 932 spin_unlock(&calldata->inode->i_lock);
938 spin_unlock(&state->owner->so_lock); 933 spin_unlock(&state->owner->so_lock);
939 if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) { 934 if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) {
940 nfs4_free_closedata(calldata); 935 /* Note: exit _without_ calling nfs4_close_done */
941 task->tk_exit = NULL; 936 task->tk_action = NULL;
942 rpc_exit(task, 0);
943 return; 937 return;
944 } 938 }
945 nfs_fattr_init(calldata->res.fattr); 939 nfs_fattr_init(calldata->res.fattr);
@@ -949,6 +943,11 @@ static void nfs4_close_begin(struct rpc_task *task)
949 rpc_call_setup(task, &msg, 0); 943 rpc_call_setup(task, &msg, 0);
950} 944}
951 945
946static const struct rpc_call_ops nfs4_close_ops = {
947 .rpc_call_done = nfs4_close_done,
948 .rpc_release = nfs4_free_closedata,
949};
950
952/* 951/*
953 * It is possible for data to be read/written from a mem-mapped file 952 * It is possible for data to be read/written from a mem-mapped file
954 * after the sys_close call (which hits the vfs layer as a flush). 953 * after the sys_close call (which hits the vfs layer as a flush).
@@ -982,7 +981,7 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state)
982 calldata->res.server = server; 981 calldata->res.server = server;
983 982
984 status = nfs4_call_async(server->client, nfs4_close_begin, 983 status = nfs4_call_async(server->client, nfs4_close_begin,
985 nfs4_close_done, calldata); 984 &nfs4_close_ops, calldata);
986 if (status == 0) 985 if (status == 0)
987 goto out; 986 goto out;
988 987
@@ -2125,10 +2124,9 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
2125 return err; 2124 return err;
2126} 2125}
2127 2126
2128static void 2127static void nfs4_read_done(struct rpc_task *task, void *calldata)
2129nfs4_read_done(struct rpc_task *task)
2130{ 2128{
2131 struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; 2129 struct nfs_read_data *data = calldata;
2132 struct inode *inode = data->inode; 2130 struct inode *inode = data->inode;
2133 2131
2134 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { 2132 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2138,9 +2136,14 @@ nfs4_read_done(struct rpc_task *task)
2138 if (task->tk_status > 0) 2136 if (task->tk_status > 0)
2139 renew_lease(NFS_SERVER(inode), data->timestamp); 2137 renew_lease(NFS_SERVER(inode), data->timestamp);
2140 /* Call back common NFS readpage processing */ 2138 /* Call back common NFS readpage processing */
2141 nfs_readpage_result(task); 2139 nfs_readpage_result(task, calldata);
2142} 2140}
2143 2141
2142static const struct rpc_call_ops nfs4_read_ops = {
2143 .rpc_call_done = nfs4_read_done,
2144 .rpc_release = nfs_readdata_release,
2145};
2146
2144static void 2147static void
2145nfs4_proc_read_setup(struct nfs_read_data *data) 2148nfs4_proc_read_setup(struct nfs_read_data *data)
2146{ 2149{
@@ -2160,14 +2163,13 @@ nfs4_proc_read_setup(struct nfs_read_data *data)
2160 flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); 2163 flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
2161 2164
2162 /* Finalize the task. */ 2165 /* Finalize the task. */
2163 rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags); 2166 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_read_ops, data);
2164 rpc_call_setup(task, &msg, 0); 2167 rpc_call_setup(task, &msg, 0);
2165} 2168}
2166 2169
2167static void 2170static void nfs4_write_done(struct rpc_task *task, void *calldata)
2168nfs4_write_done(struct rpc_task *task)
2169{ 2171{
2170 struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; 2172 struct nfs_write_data *data = calldata;
2171 struct inode *inode = data->inode; 2173 struct inode *inode = data->inode;
2172 2174
2173 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { 2175 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2179,9 +2181,14 @@ nfs4_write_done(struct rpc_task *task)
2179 nfs_post_op_update_inode(inode, data->res.fattr); 2181 nfs_post_op_update_inode(inode, data->res.fattr);
2180 } 2182 }
2181 /* Call back common NFS writeback processing */ 2183 /* Call back common NFS writeback processing */
2182 nfs_writeback_done(task); 2184 nfs_writeback_done(task, calldata);
2183} 2185}
2184 2186
2187static const struct rpc_call_ops nfs4_write_ops = {
2188 .rpc_call_done = nfs4_write_done,
2189 .rpc_release = nfs_writedata_release,
2190};
2191
2185static void 2192static void
2186nfs4_proc_write_setup(struct nfs_write_data *data, int how) 2193nfs4_proc_write_setup(struct nfs_write_data *data, int how)
2187{ 2194{
@@ -2214,14 +2221,13 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
2214 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; 2221 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
2215 2222
2216 /* Finalize the task. */ 2223 /* Finalize the task. */
2217 rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags); 2224 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_write_ops, data);
2218 rpc_call_setup(task, &msg, 0); 2225 rpc_call_setup(task, &msg, 0);
2219} 2226}
2220 2227
2221static void 2228static void nfs4_commit_done(struct rpc_task *task, void *calldata)
2222nfs4_commit_done(struct rpc_task *task)
2223{ 2229{
2224 struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; 2230 struct nfs_write_data *data = calldata;
2225 struct inode *inode = data->inode; 2231 struct inode *inode = data->inode;
2226 2232
2227 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { 2233 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2231,9 +2237,14 @@ nfs4_commit_done(struct rpc_task *task)
2231 if (task->tk_status >= 0) 2237 if (task->tk_status >= 0)
2232 nfs_post_op_update_inode(inode, data->res.fattr); 2238 nfs_post_op_update_inode(inode, data->res.fattr);
2233 /* Call back common NFS writeback processing */ 2239 /* Call back common NFS writeback processing */
2234 nfs_commit_done(task); 2240 nfs_commit_done(task, calldata);
2235} 2241}
2236 2242
2243static const struct rpc_call_ops nfs4_commit_ops = {
2244 .rpc_call_done = nfs4_commit_done,
2245 .rpc_release = nfs_commit_release,
2246};
2247
2237static void 2248static void
2238nfs4_proc_commit_setup(struct nfs_write_data *data, int how) 2249nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
2239{ 2250{
@@ -2255,7 +2266,7 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
2255 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; 2266 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
2256 2267
2257 /* Finalize the task. */ 2268 /* Finalize the task. */
2258 rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags); 2269 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_commit_ops, data);
2259 rpc_call_setup(task, &msg, 0); 2270 rpc_call_setup(task, &msg, 0);
2260} 2271}
2261 2272
@@ -2263,11 +2274,10 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
2263 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special 2274 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
2264 * standalone procedure for queueing an asynchronous RENEW. 2275 * standalone procedure for queueing an asynchronous RENEW.
2265 */ 2276 */
2266static void 2277static void nfs4_renew_done(struct rpc_task *task, void *data)
2267renew_done(struct rpc_task *task)
2268{ 2278{
2269 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; 2279 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
2270 unsigned long timestamp = (unsigned long)task->tk_calldata; 2280 unsigned long timestamp = (unsigned long)data;
2271 2281
2272 if (task->tk_status < 0) { 2282 if (task->tk_status < 0) {
2273 switch (task->tk_status) { 2283 switch (task->tk_status) {
@@ -2284,6 +2294,10 @@ renew_done(struct rpc_task *task)
2284 spin_unlock(&clp->cl_lock); 2294 spin_unlock(&clp->cl_lock);
2285} 2295}
2286 2296
2297static const struct rpc_call_ops nfs4_renew_ops = {
2298 .rpc_call_done = nfs4_renew_done,
2299};
2300
2287int 2301int
2288nfs4_proc_async_renew(struct nfs4_client *clp) 2302nfs4_proc_async_renew(struct nfs4_client *clp)
2289{ 2303{
@@ -2294,7 +2308,7 @@ nfs4_proc_async_renew(struct nfs4_client *clp)
2294 }; 2308 };
2295 2309
2296 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, 2310 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
2297 renew_done, (void *)jiffies); 2311 &nfs4_renew_ops, (void *)jiffies);
2298} 2312}
2299 2313
2300int 2314int
@@ -2866,15 +2880,16 @@ static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata)
2866 } 2880 }
2867} 2881}
2868 2882
2869static void nfs4_locku_complete(struct nfs4_unlockdata *calldata) 2883static void nfs4_locku_complete(void *data)
2870{ 2884{
2885 struct nfs4_unlockdata *calldata = data;
2871 complete(&calldata->completion); 2886 complete(&calldata->completion);
2872 nfs4_locku_release_calldata(calldata); 2887 nfs4_locku_release_calldata(calldata);
2873} 2888}
2874 2889
2875static void nfs4_locku_done(struct rpc_task *task) 2890static void nfs4_locku_done(struct rpc_task *task, void *data)
2876{ 2891{
2877 struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata; 2892 struct nfs4_unlockdata *calldata = data;
2878 2893
2879 nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid); 2894 nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid);
2880 switch (task->tk_status) { 2895 switch (task->tk_status) {
@@ -2890,10 +2905,8 @@ static void nfs4_locku_done(struct rpc_task *task)
2890 default: 2905 default:
2891 if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) { 2906 if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) {
2892 rpc_restart_call(task); 2907 rpc_restart_call(task);
2893 return;
2894 } 2908 }
2895 } 2909 }
2896 nfs4_locku_complete(calldata);
2897} 2910}
2898 2911
2899static void nfs4_locku_begin(struct rpc_task *task) 2912static void nfs4_locku_begin(struct rpc_task *task)
@@ -2911,14 +2924,18 @@ static void nfs4_locku_begin(struct rpc_task *task)
2911 if (status != 0) 2924 if (status != 0)
2912 return; 2925 return;
2913 if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { 2926 if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) {
2914 nfs4_locku_complete(calldata); 2927 /* Note: exit _without_ running nfs4_locku_done */
2915 task->tk_exit = NULL; 2928 task->tk_action = NULL;
2916 rpc_exit(task, 0);
2917 return; 2929 return;
2918 } 2930 }
2919 rpc_call_setup(task, &msg, 0); 2931 rpc_call_setup(task, &msg, 0);
2920} 2932}
2921 2933
2934static const struct rpc_call_ops nfs4_locku_ops = {
2935 .rpc_call_done = nfs4_locku_done,
2936 .rpc_release = nfs4_locku_complete,
2937};
2938
2922static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) 2939static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
2923{ 2940{
2924 struct nfs4_unlockdata *calldata; 2941 struct nfs4_unlockdata *calldata;
@@ -2963,7 +2980,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
2963 init_completion(&calldata->completion); 2980 init_completion(&calldata->completion);
2964 2981
2965 status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin, 2982 status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin,
2966 nfs4_locku_done, calldata); 2983 &nfs4_locku_ops, calldata);
2967 if (status == 0) 2984 if (status == 0)
2968 wait_for_completion_interruptible(&calldata->completion); 2985 wait_for_completion_interruptible(&calldata->completion);
2969 do_vfs_lock(request->fl_file, request); 2986 do_vfs_lock(request->fl_file, request);
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index e1e3ca5d746b..6145e82b45e8 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -547,10 +547,9 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
547 547
548extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); 548extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
549 549
550static void 550static void nfs_read_done(struct rpc_task *task, void *calldata)
551nfs_read_done(struct rpc_task *task)
552{ 551{
553 struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; 552 struct nfs_read_data *data = calldata;
554 553
555 if (task->tk_status >= 0) { 554 if (task->tk_status >= 0) {
556 nfs_refresh_inode(data->inode, data->res.fattr); 555 nfs_refresh_inode(data->inode, data->res.fattr);
@@ -560,9 +559,14 @@ nfs_read_done(struct rpc_task *task)
560 if (data->args.offset + data->args.count >= data->res.fattr->size) 559 if (data->args.offset + data->args.count >= data->res.fattr->size)
561 data->res.eof = 1; 560 data->res.eof = 1;
562 } 561 }
563 nfs_readpage_result(task); 562 nfs_readpage_result(task, calldata);
564} 563}
565 564
565static const struct rpc_call_ops nfs_read_ops = {
566 .rpc_call_done = nfs_read_done,
567 .rpc_release = nfs_readdata_release,
568};
569
566static void 570static void
567nfs_proc_read_setup(struct nfs_read_data *data) 571nfs_proc_read_setup(struct nfs_read_data *data)
568{ 572{
@@ -580,20 +584,24 @@ nfs_proc_read_setup(struct nfs_read_data *data)
580 flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); 584 flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
581 585
582 /* Finalize the task. */ 586 /* Finalize the task. */
583 rpc_init_task(task, NFS_CLIENT(inode), nfs_read_done, flags); 587 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_read_ops, data);
584 rpc_call_setup(task, &msg, 0); 588 rpc_call_setup(task, &msg, 0);
585} 589}
586 590
587static void 591static void nfs_write_done(struct rpc_task *task, void *calldata)
588nfs_write_done(struct rpc_task *task)
589{ 592{
590 struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; 593 struct nfs_write_data *data = calldata;
591 594
592 if (task->tk_status >= 0) 595 if (task->tk_status >= 0)
593 nfs_post_op_update_inode(data->inode, data->res.fattr); 596 nfs_post_op_update_inode(data->inode, data->res.fattr);
594 nfs_writeback_done(task); 597 nfs_writeback_done(task, calldata);
595} 598}
596 599
600static const struct rpc_call_ops nfs_write_ops = {
601 .rpc_call_done = nfs_write_done,
602 .rpc_release = nfs_writedata_release,
603};
604
597static void 605static void
598nfs_proc_write_setup(struct nfs_write_data *data, int how) 606nfs_proc_write_setup(struct nfs_write_data *data, int how)
599{ 607{
@@ -614,7 +622,7 @@ nfs_proc_write_setup(struct nfs_write_data *data, int how)
614 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; 622 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
615 623
616 /* Finalize the task. */ 624 /* Finalize the task. */
617 rpc_init_task(task, NFS_CLIENT(inode), nfs_write_done, flags); 625 rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_write_ops, data);
618 rpc_call_setup(task, &msg, 0); 626 rpc_call_setup(task, &msg, 0);
619} 627}
620 628
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 5f20eafba8ec..21486242c3d3 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -42,9 +42,8 @@ mempool_t *nfs_rdata_mempool;
42 42
43#define MIN_POOL_READ (32) 43#define MIN_POOL_READ (32)
44 44
45void nfs_readdata_release(struct rpc_task *task) 45void nfs_readdata_release(void *data)
46{ 46{
47 struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
48 nfs_readdata_free(data); 47 nfs_readdata_free(data);
49} 48}
50 49
@@ -220,9 +219,6 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
220 NFS_PROTO(inode)->read_setup(data); 219 NFS_PROTO(inode)->read_setup(data);
221 220
222 data->task.tk_cookie = (unsigned long)inode; 221 data->task.tk_cookie = (unsigned long)inode;
223 data->task.tk_calldata = data;
224 /* Release requests */
225 data->task.tk_release = nfs_readdata_release;
226 222
227 dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n", 223 dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
228 data->task.tk_pid, 224 data->task.tk_pid,
@@ -452,9 +448,9 @@ static void nfs_readpage_result_full(struct nfs_read_data *data, int status)
452 * This is the callback from RPC telling us whether a reply was 448 * This is the callback from RPC telling us whether a reply was
453 * received or some error occurred (timeout or socket shutdown). 449 * received or some error occurred (timeout or socket shutdown).
454 */ 450 */
455void nfs_readpage_result(struct rpc_task *task) 451void nfs_readpage_result(struct rpc_task *task, void *calldata)
456{ 452{
457 struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata; 453 struct nfs_read_data *data = calldata;
458 struct nfs_readargs *argp = &data->args; 454 struct nfs_readargs *argp = &data->args;
459 struct nfs_readres *resp = &data->res; 455 struct nfs_readres *resp = &data->res;
460 int status = task->tk_status; 456 int status = task->tk_status;
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index d639d172d568..1494484ba86d 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -116,10 +116,9 @@ nfs_async_unlink_init(struct rpc_task *task)
116 * 116 *
117 * Do the directory attribute update. 117 * Do the directory attribute update.
118 */ 118 */
119static void 119static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
120nfs_async_unlink_done(struct rpc_task *task)
121{ 120{
122 struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata; 121 struct nfs_unlinkdata *data = calldata;
123 struct dentry *dir = data->dir; 122 struct dentry *dir = data->dir;
124 struct inode *dir_i; 123 struct inode *dir_i;
125 124
@@ -141,13 +140,17 @@ nfs_async_unlink_done(struct rpc_task *task)
141 * We need to call nfs_put_unlinkdata as a 'tk_release' task since the 140 * We need to call nfs_put_unlinkdata as a 'tk_release' task since the
142 * rpc_task would be freed too. 141 * rpc_task would be freed too.
143 */ 142 */
144static void 143static void nfs_async_unlink_release(void *calldata)
145nfs_async_unlink_release(struct rpc_task *task)
146{ 144{
147 struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata; 145 struct nfs_unlinkdata *data = calldata;
148 nfs_put_unlinkdata(data); 146 nfs_put_unlinkdata(data);
149} 147}
150 148
149static const struct rpc_call_ops nfs_unlink_ops = {
150 .rpc_call_done = nfs_async_unlink_done,
151 .rpc_release = nfs_async_unlink_release,
152};
153
151/** 154/**
152 * nfs_async_unlink - asynchronous unlinking of a file 155 * nfs_async_unlink - asynchronous unlinking of a file
153 * @dentry: dentry to unlink 156 * @dentry: dentry to unlink
@@ -179,10 +182,8 @@ nfs_async_unlink(struct dentry *dentry)
179 data->count = 1; 182 data->count = 1;
180 183
181 task = &data->task; 184 task = &data->task;
182 rpc_init_task(task, clnt, nfs_async_unlink_done , RPC_TASK_ASYNC); 185 rpc_init_task(task, clnt, RPC_TASK_ASYNC, &nfs_unlink_ops, data);
183 task->tk_calldata = data;
184 task->tk_action = nfs_async_unlink_init; 186 task->tk_action = nfs_async_unlink_init;
185 task->tk_release = nfs_async_unlink_release;
186 187
187 spin_lock(&dentry->d_lock); 188 spin_lock(&dentry->d_lock);
188 dentry->d_flags |= DCACHE_NFSFS_RENAMED; 189 dentry->d_flags |= DCACHE_NFSFS_RENAMED;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 95d00f9132d0..80bc4ea1b824 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -104,9 +104,8 @@ static inline void nfs_commit_free(struct nfs_write_data *p)
104 mempool_free(p, nfs_commit_mempool); 104 mempool_free(p, nfs_commit_mempool);
105} 105}
106 106
107static void nfs_writedata_release(struct rpc_task *task) 107void nfs_writedata_release(void *wdata)
108{ 108{
109 struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata;
110 nfs_writedata_free(wdata); 109 nfs_writedata_free(wdata);
111} 110}
112 111
@@ -871,9 +870,6 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
871 870
872 data->task.tk_priority = flush_task_priority(how); 871 data->task.tk_priority = flush_task_priority(how);
873 data->task.tk_cookie = (unsigned long)inode; 872 data->task.tk_cookie = (unsigned long)inode;
874 data->task.tk_calldata = data;
875 /* Release requests */
876 data->task.tk_release = nfs_writedata_release;
877 873
878 dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n", 874 dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n",
879 data->task.tk_pid, 875 data->task.tk_pid,
@@ -1131,9 +1127,9 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
1131/* 1127/*
1132 * This function is called when the WRITE call is complete. 1128 * This function is called when the WRITE call is complete.
1133 */ 1129 */
1134void nfs_writeback_done(struct rpc_task *task) 1130void nfs_writeback_done(struct rpc_task *task, void *calldata)
1135{ 1131{
1136 struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; 1132 struct nfs_write_data *data = calldata;
1137 struct nfs_writeargs *argp = &data->args; 1133 struct nfs_writeargs *argp = &data->args;
1138 struct nfs_writeres *resp = &data->res; 1134 struct nfs_writeres *resp = &data->res;
1139 1135
@@ -1200,9 +1196,8 @@ void nfs_writeback_done(struct rpc_task *task)
1200 1196
1201 1197
1202#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1198#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
1203static void nfs_commit_release(struct rpc_task *task) 1199void nfs_commit_release(void *wdata)
1204{ 1200{
1205 struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata;
1206 nfs_commit_free(wdata); 1201 nfs_commit_free(wdata);
1207} 1202}
1208 1203
@@ -1238,9 +1233,6 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1238 1233
1239 data->task.tk_priority = flush_task_priority(how); 1234 data->task.tk_priority = flush_task_priority(how);
1240 data->task.tk_cookie = (unsigned long)inode; 1235 data->task.tk_cookie = (unsigned long)inode;
1241 data->task.tk_calldata = data;
1242 /* Release requests */
1243 data->task.tk_release = nfs_commit_release;
1244 1236
1245 dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid); 1237 dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid);
1246} 1238}
@@ -1277,10 +1269,9 @@ nfs_commit_list(struct list_head *head, int how)
1277/* 1269/*
1278 * COMMIT call returned 1270 * COMMIT call returned
1279 */ 1271 */
1280void 1272void nfs_commit_done(struct rpc_task *task, void *calldata)
1281nfs_commit_done(struct rpc_task *task)
1282{ 1273{
1283 struct nfs_write_data *data = (struct nfs_write_data *)task->tk_calldata; 1274 struct nfs_write_data *data = calldata;
1284 struct nfs_page *req; 1275 struct nfs_page *req;
1285 int res = 0; 1276 int res = 0;
1286 1277
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 583c0710e45e..cf92008f219a 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -53,7 +53,7 @@
53#define NFSPROC4_CB_COMPOUND 1 53#define NFSPROC4_CB_COMPOUND 1
54 54
55/* declarations */ 55/* declarations */
56static void nfs4_cb_null(struct rpc_task *task); 56static const struct rpc_call_ops nfs4_cb_null_ops;
57 57
58/* Index of predefined Linux callback client operations */ 58/* Index of predefined Linux callback client operations */
59 59
@@ -447,7 +447,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
447 msg.rpc_cred = nfsd4_lookupcred(clp,0); 447 msg.rpc_cred = nfsd4_lookupcred(clp,0);
448 if (IS_ERR(msg.rpc_cred)) 448 if (IS_ERR(msg.rpc_cred))
449 goto out_rpciod; 449 goto out_rpciod;
450 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL); 450 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
451 put_rpccred(msg.rpc_cred); 451 put_rpccred(msg.rpc_cred);
452 452
453 if (status != 0) { 453 if (status != 0) {
@@ -469,7 +469,7 @@ out_err:
469} 469}
470 470
471static void 471static void
472nfs4_cb_null(struct rpc_task *task) 472nfs4_cb_null(struct rpc_task *task, void *dummy)
473{ 473{
474 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; 474 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
475 struct nfs4_callback *cb = &clp->cl_callback; 475 struct nfs4_callback *cb = &clp->cl_callback;
@@ -488,6 +488,10 @@ out:
488 put_nfs4_client(clp); 488 put_nfs4_client(clp);
489} 489}
490 490
491static const struct rpc_call_ops nfs4_cb_null_ops = {
492 .rpc_call_done = nfs4_cb_null,
493};
494
491/* 495/*
492 * called with dp->dl_count inc'ed. 496 * called with dp->dl_count inc'ed.
493 * nfs4_lock_state() may or may not have been called. 497 * nfs4_lock_state() may or may not have been called.
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 16d4e5a08e1d..95c8fea293ba 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -172,7 +172,7 @@ extern struct nlm_host *nlm_find_client(void);
172/* 172/*
173 * Server-side lock handling 173 * Server-side lock handling
174 */ 174 */
175int nlmsvc_async_call(struct nlm_rqst *, u32, rpc_action); 175int nlmsvc_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *);
176u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, 176u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
177 struct nlm_lock *, int, struct nlm_cookie *); 177 struct nlm_lock *, int, struct nlm_cookie *);
178u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); 178u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 2516adeccecf..4dff705d2ff2 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -406,10 +406,12 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
406extern int nfs_writepages(struct address_space *, struct writeback_control *); 406extern int nfs_writepages(struct address_space *, struct writeback_control *);
407extern int nfs_flush_incompatible(struct file *file, struct page *page); 407extern int nfs_flush_incompatible(struct file *file, struct page *page);
408extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); 408extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
409extern void nfs_writeback_done(struct rpc_task *task); 409extern void nfs_writeback_done(struct rpc_task *task, void *data);
410extern void nfs_writedata_release(void *data);
410 411
411#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 412#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
412extern void nfs_commit_done(struct rpc_task *); 413extern void nfs_commit_done(struct rpc_task *, void *data);
414extern void nfs_commit_release(void *data);
413#endif 415#endif
414 416
415/* 417/*
@@ -481,7 +483,9 @@ static inline void nfs_writedata_free(struct nfs_write_data *p)
481extern int nfs_readpage(struct file *, struct page *); 483extern int nfs_readpage(struct file *, struct page *);
482extern int nfs_readpages(struct file *, struct address_space *, 484extern int nfs_readpages(struct file *, struct address_space *,
483 struct list_head *, unsigned); 485 struct list_head *, unsigned);
484extern void nfs_readpage_result(struct rpc_task *); 486extern void nfs_readpage_result(struct rpc_task *, void *);
487extern void nfs_readdata_release(void *data);
488
485 489
486/* 490/*
487 * Allocate and free nfs_read_data structures 491 * Allocate and free nfs_read_data structures
@@ -501,8 +505,6 @@ static inline void nfs_readdata_free(struct nfs_read_data *p)
501 mempool_free(p, nfs_rdata_mempool); 505 mempool_free(p, nfs_rdata_mempool);
502} 506}
503 507
504extern void nfs_readdata_release(struct rpc_task *task);
505
506/* 508/*
507 * linux/fs/nfs3proc.c 509 * linux/fs/nfs3proc.c
508 */ 510 */
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index ab151bbb66df..b0ab959eca65 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -126,7 +126,8 @@ int rpc_register(u32, u32, int, unsigned short, int *);
126void rpc_call_setup(struct rpc_task *, struct rpc_message *, int); 126void rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
127 127
128int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, 128int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
129 int flags, rpc_action callback, void *clntdata); 129 int flags, const struct rpc_call_ops *tk_ops,
130 void *calldata);
130int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, 131int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
131 int flags); 132 int flags);
132void rpc_restart_call(struct rpc_task *); 133void rpc_restart_call(struct rpc_task *);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 4c4b2dc8aca5..581d8cdc3b86 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -27,6 +27,7 @@ struct rpc_message {
27 struct rpc_cred * rpc_cred; /* Credentials */ 27 struct rpc_cred * rpc_cred; /* Credentials */
28}; 28};
29 29
30struct rpc_call_ops;
30struct rpc_wait_queue; 31struct rpc_wait_queue;
31struct rpc_wait { 32struct rpc_wait {
32 struct list_head list; /* wait queue links */ 33 struct list_head list; /* wait queue links */
@@ -61,13 +62,12 @@ struct rpc_task {
61 * timeout_fn to be executed by timer bottom half 62 * timeout_fn to be executed by timer bottom half
62 * callback to be executed after waking up 63 * callback to be executed after waking up
63 * action next procedure for async tasks 64 * action next procedure for async tasks
64 * exit exit async task and report to caller 65 * tk_ops caller callbacks
65 */ 66 */
66 void (*tk_timeout_fn)(struct rpc_task *); 67 void (*tk_timeout_fn)(struct rpc_task *);
67 void (*tk_callback)(struct rpc_task *); 68 void (*tk_callback)(struct rpc_task *);
68 void (*tk_action)(struct rpc_task *); 69 void (*tk_action)(struct rpc_task *);
69 void (*tk_exit)(struct rpc_task *); 70 const struct rpc_call_ops *tk_ops;
70 void (*tk_release)(struct rpc_task *);
71 void * tk_calldata; 71 void * tk_calldata;
72 72
73 /* 73 /*
@@ -111,6 +111,12 @@ struct rpc_task {
111 111
112typedef void (*rpc_action)(struct rpc_task *); 112typedef void (*rpc_action)(struct rpc_task *);
113 113
114struct rpc_call_ops {
115 void (*rpc_call_done)(struct rpc_task *, void *);
116 void (*rpc_release)(void *);
117};
118
119
114/* 120/*
115 * RPC task flags 121 * RPC task flags
116 */ 122 */
@@ -228,10 +234,12 @@ struct rpc_wait_queue {
228/* 234/*
229 * Function prototypes 235 * Function prototypes
230 */ 236 */
231struct rpc_task *rpc_new_task(struct rpc_clnt *, rpc_action, int flags); 237struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags,
238 const struct rpc_call_ops *ops, void *data);
232struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); 239struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent);
233void rpc_init_task(struct rpc_task *, struct rpc_clnt *, 240void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt,
234 rpc_action exitfunc, int flags); 241 int flags, const struct rpc_call_ops *ops,
242 void *data);
235void rpc_release_task(struct rpc_task *); 243void rpc_release_task(struct rpc_task *);
236void rpc_exit_task(struct rpc_task *); 244void rpc_exit_task(struct rpc_task *);
237void rpc_killall_tasks(struct rpc_clnt *); 245void rpc_killall_tasks(struct rpc_clnt *);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 6ab4cbd8a901..8b2f75bc006d 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -374,10 +374,14 @@ out:
374 * Default callback for async RPC calls 374 * Default callback for async RPC calls
375 */ 375 */
376static void 376static void
377rpc_default_callback(struct rpc_task *task) 377rpc_default_callback(struct rpc_task *task, void *data)
378{ 378{
379} 379}
380 380
381static const struct rpc_call_ops rpc_default_ops = {
382 .rpc_call_done = rpc_default_callback,
383};
384
381/* 385/*
382 * Export the signal mask handling for synchronous code that 386 * Export the signal mask handling for synchronous code that
383 * sleeps on RPC calls 387 * sleeps on RPC calls
@@ -432,7 +436,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
432 BUG_ON(flags & RPC_TASK_ASYNC); 436 BUG_ON(flags & RPC_TASK_ASYNC);
433 437
434 status = -ENOMEM; 438 status = -ENOMEM;
435 task = rpc_new_task(clnt, NULL, flags); 439 task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
436 if (task == NULL) 440 if (task == NULL)
437 goto out; 441 goto out;
438 442
@@ -459,7 +463,7 @@ out:
459 */ 463 */
460int 464int
461rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, 465rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
462 rpc_action callback, void *data) 466 const struct rpc_call_ops *tk_ops, void *data)
463{ 467{
464 struct rpc_task *task; 468 struct rpc_task *task;
465 sigset_t oldset; 469 sigset_t oldset;
@@ -472,12 +476,9 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
472 flags |= RPC_TASK_ASYNC; 476 flags |= RPC_TASK_ASYNC;
473 477
474 /* Create/initialize a new RPC task */ 478 /* Create/initialize a new RPC task */
475 if (!callback)
476 callback = rpc_default_callback;
477 status = -ENOMEM; 479 status = -ENOMEM;
478 if (!(task = rpc_new_task(clnt, callback, flags))) 480 if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
479 goto out; 481 goto out;
480 task->tk_calldata = data;
481 482
482 /* Mask signals on GSS_AUTH upcalls */ 483 /* Mask signals on GSS_AUTH upcalls */
483 rpc_task_sigmask(task, &oldset); 484 rpc_task_sigmask(task, &oldset);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 3fcf7b0e1f6c..8d6233d3248b 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -555,13 +555,13 @@ __rpc_atrun(struct rpc_task *task)
555} 555}
556 556
557/* 557/*
558 * Helper that calls task->tk_exit if it exists 558 * Helper that calls task->tk_ops->rpc_call_done if it exists
559 */ 559 */
560void rpc_exit_task(struct rpc_task *task) 560void rpc_exit_task(struct rpc_task *task)
561{ 561{
562 task->tk_action = NULL; 562 task->tk_action = NULL;
563 if (task->tk_exit != NULL) { 563 if (task->tk_ops->rpc_call_done != NULL) {
564 task->tk_exit(task); 564 task->tk_ops->rpc_call_done(task, task->tk_calldata);
565 if (task->tk_action != NULL) { 565 if (task->tk_action != NULL) {
566 WARN_ON(RPC_ASSASSINATED(task)); 566 WARN_ON(RPC_ASSASSINATED(task));
567 /* Always release the RPC slot and buffer memory */ 567 /* Always release the RPC slot and buffer memory */
@@ -747,7 +747,7 @@ rpc_free(struct rpc_task *task)
747/* 747/*
748 * Creation and deletion of RPC task structures 748 * Creation and deletion of RPC task structures
749 */ 749 */
750void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action callback, int flags) 750void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
751{ 751{
752 memset(task, 0, sizeof(*task)); 752 memset(task, 0, sizeof(*task));
753 init_timer(&task->tk_timer); 753 init_timer(&task->tk_timer);
@@ -755,7 +755,8 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call
755 task->tk_timer.function = (void (*)(unsigned long)) rpc_run_timer; 755 task->tk_timer.function = (void (*)(unsigned long)) rpc_run_timer;
756 task->tk_client = clnt; 756 task->tk_client = clnt;
757 task->tk_flags = flags; 757 task->tk_flags = flags;
758 task->tk_exit = callback; 758 task->tk_ops = tk_ops;
759 task->tk_calldata = calldata;
759 760
760 /* Initialize retry counters */ 761 /* Initialize retry counters */
761 task->tk_garb_retry = 2; 762 task->tk_garb_retry = 2;
@@ -784,6 +785,8 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call
784 list_add_tail(&task->tk_task, &all_tasks); 785 list_add_tail(&task->tk_task, &all_tasks);
785 spin_unlock(&rpc_sched_lock); 786 spin_unlock(&rpc_sched_lock);
786 787
788 BUG_ON(task->tk_ops == NULL);
789
787 dprintk("RPC: %4d new task procpid %d\n", task->tk_pid, 790 dprintk("RPC: %4d new task procpid %d\n", task->tk_pid,
788 current->pid); 791 current->pid);
789} 792}
@@ -794,8 +797,7 @@ rpc_alloc_task(void)
794 return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS); 797 return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
795} 798}
796 799
797static void 800static void rpc_free_task(struct rpc_task *task)
798rpc_default_free_task(struct rpc_task *task)
799{ 801{
800 dprintk("RPC: %4d freeing task\n", task->tk_pid); 802 dprintk("RPC: %4d freeing task\n", task->tk_pid);
801 mempool_free(task, rpc_task_mempool); 803 mempool_free(task, rpc_task_mempool);
@@ -806,8 +808,7 @@ rpc_default_free_task(struct rpc_task *task)
806 * clean up after an allocation failure, as the client may 808 * clean up after an allocation failure, as the client may
807 * have specified "oneshot". 809 * have specified "oneshot".
808 */ 810 */
809struct rpc_task * 811struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
810rpc_new_task(struct rpc_clnt *clnt, rpc_action callback, int flags)
811{ 812{
812 struct rpc_task *task; 813 struct rpc_task *task;
813 814
@@ -815,10 +816,7 @@ rpc_new_task(struct rpc_clnt *clnt, rpc_action callback, int flags)
815 if (!task) 816 if (!task)
816 goto cleanup; 817 goto cleanup;
817 818
818 rpc_init_task(task, clnt, callback, flags); 819 rpc_init_task(task, clnt, flags, tk_ops, calldata);
819
820 /* Replace tk_release */
821 task->tk_release = rpc_default_free_task;
822 820
823 dprintk("RPC: %4d allocated task\n", task->tk_pid); 821 dprintk("RPC: %4d allocated task\n", task->tk_pid);
824 task->tk_flags |= RPC_TASK_DYNAMIC; 822 task->tk_flags |= RPC_TASK_DYNAMIC;
@@ -838,6 +836,8 @@ cleanup:
838 836
839void rpc_release_task(struct rpc_task *task) 837void rpc_release_task(struct rpc_task *task)
840{ 838{
839 const struct rpc_call_ops *tk_ops = task->tk_ops;
840 void *calldata = task->tk_calldata;
841 dprintk("RPC: %4d release task\n", task->tk_pid); 841 dprintk("RPC: %4d release task\n", task->tk_pid);
842 842
843#ifdef RPC_DEBUG 843#ifdef RPC_DEBUG
@@ -869,8 +869,10 @@ void rpc_release_task(struct rpc_task *task)
869#ifdef RPC_DEBUG 869#ifdef RPC_DEBUG
870 task->tk_magic = 0; 870 task->tk_magic = 0;
871#endif 871#endif
872 if (task->tk_release) 872 if (task->tk_flags & RPC_TASK_DYNAMIC)
873 task->tk_release(task); 873 rpc_free_task(task);
874 if (tk_ops->rpc_release)
875 tk_ops->rpc_release(calldata);
874} 876}
875 877
876/** 878/**
@@ -883,12 +885,11 @@ void rpc_release_task(struct rpc_task *task)
883 * 885 *
884 * Caller must hold childq.lock 886 * Caller must hold childq.lock
885 */ 887 */
886static inline struct rpc_task *rpc_find_parent(struct rpc_task *child) 888static inline struct rpc_task *rpc_find_parent(struct rpc_task *child, struct rpc_task *parent)
887{ 889{
888 struct rpc_task *task, *parent; 890 struct rpc_task *task;
889 struct list_head *le; 891 struct list_head *le;
890 892
891 parent = (struct rpc_task *) child->tk_calldata;
892 task_for_each(task, le, &childq.tasks[0]) 893 task_for_each(task, le, &childq.tasks[0])
893 if (task == parent) 894 if (task == parent)
894 return parent; 895 return parent;
@@ -896,18 +897,22 @@ static inline struct rpc_task *rpc_find_parent(struct rpc_task *child)
896 return NULL; 897 return NULL;
897} 898}
898 899
899static void rpc_child_exit(struct rpc_task *child) 900static void rpc_child_exit(struct rpc_task *child, void *calldata)
900{ 901{
901 struct rpc_task *parent; 902 struct rpc_task *parent;
902 903
903 spin_lock_bh(&childq.lock); 904 spin_lock_bh(&childq.lock);
904 if ((parent = rpc_find_parent(child)) != NULL) { 905 if ((parent = rpc_find_parent(child, calldata)) != NULL) {
905 parent->tk_status = child->tk_status; 906 parent->tk_status = child->tk_status;
906 __rpc_wake_up_task(parent); 907 __rpc_wake_up_task(parent);
907 } 908 }
908 spin_unlock_bh(&childq.lock); 909 spin_unlock_bh(&childq.lock);
909} 910}
910 911
912static const struct rpc_call_ops rpc_child_ops = {
913 .rpc_call_done = rpc_child_exit,
914};
915
911/* 916/*
912 * Note: rpc_new_task releases the client after a failure. 917 * Note: rpc_new_task releases the client after a failure.
913 */ 918 */
@@ -916,11 +921,9 @@ rpc_new_child(struct rpc_clnt *clnt, struct rpc_task *parent)
916{ 921{
917 struct rpc_task *task; 922 struct rpc_task *task;
918 923
919 task = rpc_new_task(clnt, NULL, RPC_TASK_ASYNC | RPC_TASK_CHILD); 924 task = rpc_new_task(clnt, RPC_TASK_ASYNC | RPC_TASK_CHILD, &rpc_child_ops, parent);
920 if (!task) 925 if (!task)
921 goto fail; 926 goto fail;
922 task->tk_exit = rpc_child_exit;
923 task->tk_calldata = parent;
924 return task; 927 return task;
925 928
926fail: 929fail:
@@ -1056,7 +1059,7 @@ void rpc_show_tasks(void)
1056 return; 1059 return;
1057 } 1060 }
1058 printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " 1061 printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
1059 "-rpcwait -action- --exit--\n"); 1062 "-rpcwait -action- ---ops--\n");
1060 alltask_for_each(t, le, &all_tasks) { 1063 alltask_for_each(t, le, &all_tasks) {
1061 const char *rpc_waitq = "none"; 1064 const char *rpc_waitq = "none";
1062 1065
@@ -1071,7 +1074,7 @@ void rpc_show_tasks(void)
1071 (t->tk_client ? t->tk_client->cl_prog : 0), 1074 (t->tk_client ? t->tk_client->cl_prog : 0),
1072 t->tk_rqstp, t->tk_timeout, 1075 t->tk_rqstp, t->tk_timeout,
1073 rpc_waitq, 1076 rpc_waitq,
1074 t->tk_action, t->tk_exit); 1077 t->tk_action, t->tk_ops);
1075 } 1078 }
1076 spin_unlock(&rpc_sched_lock); 1079 spin_unlock(&rpc_sched_lock);
1077} 1080}