diff options
-rw-r--r-- | fs/lockd/clntproc.c | 38 | ||||
-rw-r--r-- | fs/lockd/svc4proc.c | 15 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 14 | ||||
-rw-r--r-- | fs/lockd/svcproc.c | 14 | ||||
-rw-r--r-- | fs/nfs/direct.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 44 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 107 | ||||
-rw-r--r-- | fs/nfs/proc.c | 28 | ||||
-rw-r--r-- | fs/nfs/read.c | 10 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 19 | ||||
-rw-r--r-- | fs/nfs/write.c | 21 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 10 | ||||
-rw-r--r-- | include/linux/lockd/lockd.h | 2 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 12 | ||||
-rw-r--r-- | include/linux/sunrpc/clnt.h | 3 | ||||
-rw-r--r-- | include/linux/sunrpc/sched.h | 20 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 15 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 53 |
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 @@ | |||
26 | static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); | 26 | static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); |
27 | static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); | 27 | static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); |
28 | static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); | 28 | static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); |
29 | static void nlmclnt_unlock_callback(struct rpc_task *); | ||
30 | static void nlmclnt_cancel_callback(struct rpc_task *); | ||
31 | static int nlm_stat_to_errno(u32 stat); | 29 | static int nlm_stat_to_errno(u32 stat); |
32 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); | 30 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); |
33 | 31 | ||
32 | static const struct rpc_call_ops nlmclnt_unlock_ops; | ||
33 | static 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 | */ |
402 | int | 403 | int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) |
403 | nlmsvc_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 | ||
427 | static int | 427 | static int nlmclnt_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) |
428 | nlmclnt_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 | ||
695 | static void | 694 | static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) |
696 | nlmclnt_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 | ||
723 | static 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 | ||
768 | static void | 769 | static void nlmclnt_cancel_callback(struct rpc_task *task, void *data) |
769 | nlmclnt_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 | ||
810 | static 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 | ||
24 | static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *); | 24 | static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *); |
25 | static void nlm4svc_callback_exit(struct rpc_task *); | 25 | |
26 | static 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 | ||
507 | static void | 507 | static void nlm4svc_callback_exit(struct rpc_task *task, void *data) |
508 | nlm4svc_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 | ||
519 | static 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 | ||
42 | static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); | 42 | static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); |
43 | static int nlmsvc_remove_block(struct nlm_block *block); | 43 | static int nlmsvc_remove_block(struct nlm_block *block); |
44 | static void nlmsvc_grant_callback(struct rpc_task *task); | 44 | |
45 | static 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 | */ |
578 | static void | 579 | static void nlmsvc_grant_callback(struct rpc_task *task, void *data) |
579 | nlmsvc_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 | ||
617 | static 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 | ||
25 | static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *); | 25 | static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *); |
26 | static void nlmsvc_callback_exit(struct rpc_task *); | 26 | |
27 | static const struct rpc_call_ops nlmsvc_callback_ops; | ||
27 | 28 | ||
28 | #ifdef CONFIG_LOCKD_V4 | 29 | #ifdef CONFIG_LOCKD_V4 |
29 | static u32 | 30 | static 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 | ||
531 | static void | 532 | static void nlmsvc_callback_exit(struct rpc_task *task, void *data) |
532 | nlmsvc_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 | ||
544 | static 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 | ||
733 | extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); | 733 | extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); |
734 | 734 | ||
735 | static void | 735 | static void nfs3_read_done(struct rpc_task *task, void *calldata) |
736 | nfs3_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 | ||
747 | static const struct rpc_call_ops nfs3_read_ops = { | ||
748 | .rpc_call_done = nfs3_read_done, | ||
749 | .rpc_release = nfs_readdata_release, | ||
750 | }; | ||
751 | |||
748 | static void | 752 | static void |
749 | nfs3_proc_read_setup(struct nfs_read_data *data) | 753 | nfs3_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 | ||
769 | static void | 773 | static void nfs3_write_done(struct rpc_task *task, void *calldata) |
770 | nfs3_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 | ||
784 | static const struct rpc_call_ops nfs3_write_ops = { | ||
785 | .rpc_call_done = nfs3_write_done, | ||
786 | .rpc_release = nfs_writedata_release, | ||
787 | }; | ||
788 | |||
782 | static void | 789 | static void |
783 | nfs3_proc_write_setup(struct nfs_write_data *data, int how) | 790 | nfs3_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 | ||
813 | static void | 820 | static void nfs3_commit_done(struct rpc_task *task, void *calldata) |
814 | nfs3_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 | ||
831 | static const struct rpc_call_ops nfs3_commit_ops = { | ||
832 | .rpc_call_done = nfs3_commit_done, | ||
833 | .rpc_release = nfs_commit_release, | ||
834 | }; | ||
835 | |||
826 | static void | 836 | static void |
827 | nfs3_proc_commit_setup(struct nfs_write_data *data, int how) | 837 | nfs3_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 */ |
198 | static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin, | 198 | static 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 | ||
870 | static void nfs4_free_closedata(struct nfs4_closedata *calldata) | 868 | static 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 | ||
881 | static void nfs4_close_done(struct rpc_task *task) | 879 | static 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 | ||
910 | static void nfs4_close_begin(struct rpc_task *task) | 907 | static 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 | ||
946 | static 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 | ||
2128 | static void | 2127 | static void nfs4_read_done(struct rpc_task *task, void *calldata) |
2129 | nfs4_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 | ||
2142 | static const struct rpc_call_ops nfs4_read_ops = { | ||
2143 | .rpc_call_done = nfs4_read_done, | ||
2144 | .rpc_release = nfs_readdata_release, | ||
2145 | }; | ||
2146 | |||
2144 | static void | 2147 | static void |
2145 | nfs4_proc_read_setup(struct nfs_read_data *data) | 2148 | nfs4_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 | ||
2167 | static void | 2170 | static void nfs4_write_done(struct rpc_task *task, void *calldata) |
2168 | nfs4_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 | ||
2187 | static const struct rpc_call_ops nfs4_write_ops = { | ||
2188 | .rpc_call_done = nfs4_write_done, | ||
2189 | .rpc_release = nfs_writedata_release, | ||
2190 | }; | ||
2191 | |||
2185 | static void | 2192 | static void |
2186 | nfs4_proc_write_setup(struct nfs_write_data *data, int how) | 2193 | nfs4_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 | ||
2221 | static void | 2228 | static void nfs4_commit_done(struct rpc_task *task, void *calldata) |
2222 | nfs4_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 | ||
2243 | static const struct rpc_call_ops nfs4_commit_ops = { | ||
2244 | .rpc_call_done = nfs4_commit_done, | ||
2245 | .rpc_release = nfs_commit_release, | ||
2246 | }; | ||
2247 | |||
2237 | static void | 2248 | static void |
2238 | nfs4_proc_commit_setup(struct nfs_write_data *data, int how) | 2249 | nfs4_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 | */ |
2266 | static void | 2277 | static void nfs4_renew_done(struct rpc_task *task, void *data) |
2267 | renew_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 | ||
2297 | static const struct rpc_call_ops nfs4_renew_ops = { | ||
2298 | .rpc_call_done = nfs4_renew_done, | ||
2299 | }; | ||
2300 | |||
2287 | int | 2301 | int |
2288 | nfs4_proc_async_renew(struct nfs4_client *clp) | 2302 | nfs4_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 | ||
2300 | int | 2314 | int |
@@ -2866,15 +2880,16 @@ static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata) | |||
2866 | } | 2880 | } |
2867 | } | 2881 | } |
2868 | 2882 | ||
2869 | static void nfs4_locku_complete(struct nfs4_unlockdata *calldata) | 2883 | static 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 | ||
2875 | static void nfs4_locku_done(struct rpc_task *task) | 2890 | static 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 | ||
2899 | static void nfs4_locku_begin(struct rpc_task *task) | 2912 | static 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 | ||
2934 | static const struct rpc_call_ops nfs4_locku_ops = { | ||
2935 | .rpc_call_done = nfs4_locku_done, | ||
2936 | .rpc_release = nfs4_locku_complete, | ||
2937 | }; | ||
2938 | |||
2922 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | 2939 | static 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 | ||
548 | extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); | 548 | extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); |
549 | 549 | ||
550 | static void | 550 | static void nfs_read_done(struct rpc_task *task, void *calldata) |
551 | nfs_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 | ||
565 | static const struct rpc_call_ops nfs_read_ops = { | ||
566 | .rpc_call_done = nfs_read_done, | ||
567 | .rpc_release = nfs_readdata_release, | ||
568 | }; | ||
569 | |||
566 | static void | 570 | static void |
567 | nfs_proc_read_setup(struct nfs_read_data *data) | 571 | nfs_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 | ||
587 | static void | 591 | static void nfs_write_done(struct rpc_task *task, void *calldata) |
588 | nfs_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 | ||
600 | static const struct rpc_call_ops nfs_write_ops = { | ||
601 | .rpc_call_done = nfs_write_done, | ||
602 | .rpc_release = nfs_writedata_release, | ||
603 | }; | ||
604 | |||
597 | static void | 605 | static void |
598 | nfs_proc_write_setup(struct nfs_write_data *data, int how) | 606 | nfs_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 | ||
45 | void nfs_readdata_release(struct rpc_task *task) | 45 | void 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 | */ |
455 | void nfs_readpage_result(struct rpc_task *task) | 451 | void 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 | */ |
119 | static void | 119 | static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) |
120 | nfs_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 | */ |
144 | static void | 143 | static void nfs_async_unlink_release(void *calldata) |
145 | nfs_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 | ||
149 | static 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 | ||
107 | static void nfs_writedata_release(struct rpc_task *task) | 107 | void 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 | */ |
1134 | void nfs_writeback_done(struct rpc_task *task) | 1130 | void 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) |
1203 | static void nfs_commit_release(struct rpc_task *task) | 1199 | void 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 | */ |
1280 | void | 1272 | void nfs_commit_done(struct rpc_task *task, void *calldata) |
1281 | nfs_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 */ |
56 | static void nfs4_cb_null(struct rpc_task *task); | 56 | static 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 | ||
471 | static void | 471 | static void |
472 | nfs4_cb_null(struct rpc_task *task) | 472 | nfs4_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 | ||
491 | static 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 | */ |
175 | int nlmsvc_async_call(struct nlm_rqst *, u32, rpc_action); | 175 | int nlmsvc_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *); |
176 | u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, | 176 | u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, |
177 | struct nlm_lock *, int, struct nlm_cookie *); | 177 | struct nlm_lock *, int, struct nlm_cookie *); |
178 | u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); | 178 | u32 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); | |||
406 | extern int nfs_writepages(struct address_space *, struct writeback_control *); | 406 | extern int nfs_writepages(struct address_space *, struct writeback_control *); |
407 | extern int nfs_flush_incompatible(struct file *file, struct page *page); | 407 | extern int nfs_flush_incompatible(struct file *file, struct page *page); |
408 | extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); | 408 | extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); |
409 | extern void nfs_writeback_done(struct rpc_task *task); | 409 | extern void nfs_writeback_done(struct rpc_task *task, void *data); |
410 | extern 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) |
412 | extern void nfs_commit_done(struct rpc_task *); | 413 | extern void nfs_commit_done(struct rpc_task *, void *data); |
414 | extern 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) | |||
481 | extern int nfs_readpage(struct file *, struct page *); | 483 | extern int nfs_readpage(struct file *, struct page *); |
482 | extern int nfs_readpages(struct file *, struct address_space *, | 484 | extern int nfs_readpages(struct file *, struct address_space *, |
483 | struct list_head *, unsigned); | 485 | struct list_head *, unsigned); |
484 | extern void nfs_readpage_result(struct rpc_task *); | 486 | extern void nfs_readpage_result(struct rpc_task *, void *); |
487 | extern 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 | ||
504 | extern 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 *); | |||
126 | void rpc_call_setup(struct rpc_task *, struct rpc_message *, int); | 126 | void rpc_call_setup(struct rpc_task *, struct rpc_message *, int); |
127 | 127 | ||
128 | int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, | 128 | int 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); | ||
130 | int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, | 131 | int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, |
131 | int flags); | 132 | int flags); |
132 | void rpc_restart_call(struct rpc_task *); | 133 | void 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 | ||
30 | struct rpc_call_ops; | ||
30 | struct rpc_wait_queue; | 31 | struct rpc_wait_queue; |
31 | struct rpc_wait { | 32 | struct 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 | ||
112 | typedef void (*rpc_action)(struct rpc_task *); | 112 | typedef void (*rpc_action)(struct rpc_task *); |
113 | 113 | ||
114 | struct 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 | */ |
231 | struct rpc_task *rpc_new_task(struct rpc_clnt *, rpc_action, int flags); | 237 | struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags, |
238 | const struct rpc_call_ops *ops, void *data); | ||
232 | struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); | 239 | struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); |
233 | void rpc_init_task(struct rpc_task *, struct rpc_clnt *, | 240 | void 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); | ||
235 | void rpc_release_task(struct rpc_task *); | 243 | void rpc_release_task(struct rpc_task *); |
236 | void rpc_exit_task(struct rpc_task *); | 244 | void rpc_exit_task(struct rpc_task *); |
237 | void rpc_killall_tasks(struct rpc_clnt *); | 245 | void 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 | */ |
376 | static void | 376 | static void |
377 | rpc_default_callback(struct rpc_task *task) | 377 | rpc_default_callback(struct rpc_task *task, void *data) |
378 | { | 378 | { |
379 | } | 379 | } |
380 | 380 | ||
381 | static 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 | */ |
460 | int | 464 | int |
461 | rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | 465 | rpc_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 | */ |
560 | void rpc_exit_task(struct rpc_task *task) | 560 | void 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 | */ |
750 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action callback, int flags) | 750 | void 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 | ||
797 | static void | 800 | static void rpc_free_task(struct rpc_task *task) |
798 | rpc_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 | */ |
809 | struct rpc_task * | 811 | struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) |
810 | rpc_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 | ||
839 | void rpc_release_task(struct rpc_task *task) | 837 | void 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 | */ |
886 | static inline struct rpc_task *rpc_find_parent(struct rpc_task *child) | 888 | static 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 | ||
899 | static void rpc_child_exit(struct rpc_task *child) | 900 | static 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 | ||
912 | static 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 | ||
926 | fail: | 929 | fail: |
@@ -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 | } |