diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2010-05-26 17:52:14 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-10-01 19:29:43 -0400 |
commit | cee277d92495a9ea49a6137fe7005d7c76b31b5b (patch) | |
tree | c7e80e31d64038d17761472d9a349330426d8c12 | |
parent | 5878453dbde627a8e1b5a4693087e36cb88d45b1 (diff) |
nfsd4: use generic callback code in null case
This will eventually allow us, for example, to kick off null callback
from contexts where we can't sleep.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r-- | fs/nfsd/nfs4callback.c | 33 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 1 | ||||
-rw-r--r-- | fs/nfsd/state.h | 1 |
3 files changed, 20 insertions, 15 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index a037f26252ee..26fa878005cc 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -519,7 +519,7 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason) | |||
519 | 519 | ||
520 | static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) | 520 | static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) |
521 | { | 521 | { |
522 | struct nfs4_client *clp = calldata; | 522 | struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); |
523 | 523 | ||
524 | if (task->tk_status) | 524 | if (task->tk_status) |
525 | warn_no_callback_path(clp, task->tk_status); | 525 | warn_no_callback_path(clp, task->tk_status); |
@@ -528,6 +528,8 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) | |||
528 | } | 528 | } |
529 | 529 | ||
530 | static const struct rpc_call_ops nfsd4_cb_probe_ops = { | 530 | static const struct rpc_call_ops nfsd4_cb_probe_ops = { |
531 | /* XXX: release method to ensure we set the cb channel down if | ||
532 | * necessary on early failure? */ | ||
531 | .rpc_call_done = nfsd4_cb_probe_done, | 533 | .rpc_call_done = nfsd4_cb_probe_done, |
532 | }; | 534 | }; |
533 | 535 | ||
@@ -543,21 +545,23 @@ int set_callback_cred(void) | |||
543 | return 0; | 545 | return 0; |
544 | } | 546 | } |
545 | 547 | ||
548 | static struct workqueue_struct *callback_wq; | ||
546 | 549 | ||
547 | void do_probe_callback(struct nfs4_client *clp) | 550 | void do_probe_callback(struct nfs4_client *clp) |
548 | { | 551 | { |
549 | struct rpc_message msg = { | 552 | struct nfsd4_callback *cb = &clp->cl_cb_null; |
550 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], | ||
551 | .rpc_argp = clp, | ||
552 | .rpc_cred = callback_cred | ||
553 | }; | ||
554 | int status; | ||
555 | 553 | ||
556 | status = rpc_call_async(clp->cl_cb_client, &msg, | 554 | cb->cb_args.args_op = NULL; |
557 | RPC_TASK_SOFT | RPC_TASK_SOFTCONN, | 555 | cb->cb_args.args_clp = clp; |
558 | &nfsd4_cb_probe_ops, (void *)clp); | 556 | |
559 | if (status) | 557 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL]; |
560 | warn_no_callback_path(clp, status); | 558 | cb->cb_msg.rpc_argp = NULL; |
559 | cb->cb_msg.rpc_resp = NULL; | ||
560 | cb->cb_msg.rpc_cred = callback_cred; | ||
561 | |||
562 | cb->cb_ops = &nfsd4_cb_probe_ops; | ||
563 | |||
564 | queue_work(callback_wq, &cb->cb_work); | ||
561 | } | 565 | } |
562 | 566 | ||
563 | /* | 567 | /* |
@@ -713,8 +717,6 @@ static const struct rpc_call_ops nfsd4_cb_recall_ops = { | |||
713 | .rpc_release = nfsd4_cb_recall_release, | 717 | .rpc_release = nfsd4_cb_recall_release, |
714 | }; | 718 | }; |
715 | 719 | ||
716 | static struct workqueue_struct *callback_wq; | ||
717 | |||
718 | int nfsd4_create_callback_queue(void) | 720 | int nfsd4_create_callback_queue(void) |
719 | { | 721 | { |
720 | callback_wq = create_singlethread_workqueue("nfsd4_callbacks"); | 722 | callback_wq = create_singlethread_workqueue("nfsd4_callbacks"); |
@@ -760,7 +762,8 @@ void nfsd4_do_callback_rpc(struct work_struct *w) | |||
760 | nfsd4_release_cb(cb); | 762 | nfsd4_release_cb(cb); |
761 | return; /* Client is shutting down; give up. */ | 763 | return; /* Client is shutting down; give up. */ |
762 | } | 764 | } |
763 | rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT, cb->cb_ops, cb); | 765 | rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN, |
766 | cb->cb_ops, cb); | ||
764 | } | 767 | } |
765 | 768 | ||
766 | void nfsd4_cb_recall(struct nfs4_delegation *dp) | 769 | void nfsd4_cb_recall(struct nfs4_delegation *dp) |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index d347180ce55a..2f464fb26afc 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -978,6 +978,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, | |||
978 | INIT_LIST_HEAD(&clp->cl_delegations); | 978 | INIT_LIST_HEAD(&clp->cl_delegations); |
979 | INIT_LIST_HEAD(&clp->cl_sessions); | 979 | INIT_LIST_HEAD(&clp->cl_sessions); |
980 | INIT_LIST_HEAD(&clp->cl_lru); | 980 | INIT_LIST_HEAD(&clp->cl_lru); |
981 | INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc); | ||
981 | clp->cl_time = get_seconds(); | 982 | clp->cl_time = get_seconds(); |
982 | clear_bit(0, &clp->cl_cb_slot_busy); | 983 | clear_bit(0, &clp->cl_cb_slot_busy); |
983 | rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); | 984 | rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 6e592148ad80..19732d531cda 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -223,6 +223,7 @@ struct nfs4_client { | |||
223 | struct nfs4_cb_conn cl_cb_conn; | 223 | struct nfs4_cb_conn cl_cb_conn; |
224 | struct rpc_clnt *cl_cb_client; | 224 | struct rpc_clnt *cl_cb_client; |
225 | atomic_t cl_cb_set; | 225 | atomic_t cl_cb_set; |
226 | struct nfsd4_callback cl_cb_null; | ||
226 | 227 | ||
227 | /* for nfs41 */ | 228 | /* for nfs41 */ |
228 | struct list_head cl_sessions; | 229 | struct list_head cl_sessions; |