aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4callback.c62
-rw-r--r--fs/nfsd/nfs4state.c1
-rw-r--r--include/linux/nfsd/state.h1
3 files changed, 64 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index f31175717c1a..25a09069e458 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -501,6 +501,67 @@ nfsd4_probe_callback(struct nfs4_client *clp)
501 do_probe_callback(clp); 501 do_probe_callback(clp);
502} 502}
503 503
504/*
505 * There's currently a single callback channel slot.
506 * If the slot is available, then mark it busy. Otherwise, set the
507 * thread for sleeping on the callback RPC wait queue.
508 */
509static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
510 struct rpc_task *task)
511{
512 struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
513 u32 *ptr = (u32 *)clp->cl_sessionid.data;
514 int status = 0;
515
516 dprintk("%s: %u:%u:%u:%u\n", __func__,
517 ptr[0], ptr[1], ptr[2], ptr[3]);
518
519 if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
520 rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
521 dprintk("%s slot is busy\n", __func__);
522 status = -EAGAIN;
523 goto out;
524 }
525
526 /*
527 * We'll need the clp during XDR encoding and decoding,
528 * and the sequence during decoding to verify the reply
529 */
530 args->args_seq.cbs_clp = clp;
531 task->tk_msg.rpc_resp = &args->args_seq;
532
533out:
534 dprintk("%s status=%d\n", __func__, status);
535 return status;
536}
537
538/*
539 * TODO: cb_sequence should support referring call lists, cachethis, multiple
540 * slots, and mark callback channel down on communication errors.
541 */
542static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
543{
544 struct nfs4_delegation *dp = calldata;
545 struct nfs4_client *clp = dp->dl_client;
546 struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
547 u32 minorversion = clp->cl_cb_conn.cb_minorversion;
548 int status = 0;
549
550 args->args_seq.cbs_minorversion = minorversion;
551 if (minorversion) {
552 status = nfsd41_cb_setup_sequence(clp, task);
553 if (status) {
554 if (status != -EAGAIN) {
555 /* terminate rpc task */
556 task->tk_status = status;
557 task->tk_action = NULL;
558 }
559 return;
560 }
561 }
562 rpc_call_start(task);
563}
564
504static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) 565static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
505{ 566{
506 struct nfs4_delegation *dp = calldata; 567 struct nfs4_delegation *dp = calldata;
@@ -540,6 +601,7 @@ static void nfsd4_cb_recall_release(void *calldata)
540} 601}
541 602
542static const struct rpc_call_ops nfsd4_cb_recall_ops = { 603static const struct rpc_call_ops nfsd4_cb_recall_ops = {
604 .rpc_call_prepare = nfsd4_cb_prepare,
543 .rpc_call_done = nfsd4_cb_recall_done, 605 .rpc_call_done = nfsd4_cb_recall_done,
544 .rpc_release = nfsd4_cb_recall_release, 606 .rpc_release = nfsd4_cb_recall_release,
545}; 607};
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f4cebd9016bc..76b7bcbb3f20 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1331,6 +1331,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1331 unconf->cl_cb_conn.cb_minorversion = 1331 unconf->cl_cb_conn.cb_minorversion =
1332 cstate->minorversion; 1332 cstate->minorversion;
1333 unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog; 1333 unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
1334 unconf->cl_cb_seq_nr = 1;
1334 nfsd4_probe_callback(unconf); 1335 nfsd4_probe_callback(unconf);
1335 } 1336 }
1336 conf = unconf; 1337 conf = unconf;
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 9cc40a137c34..b38d11324189 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -221,6 +221,7 @@ struct nfs4_client {
221 /* for nfs41 callbacks */ 221 /* for nfs41 callbacks */
222 /* We currently support a single back channel with a single slot */ 222 /* We currently support a single back channel with a single slot */
223 unsigned long cl_cb_slot_busy; 223 unsigned long cl_cb_slot_busy;
224 u32 cl_cb_seq_nr;
224 struct svc_xprt *cl_cb_xprt; /* 4.1 callback transport */ 225 struct svc_xprt *cl_cb_xprt; /* 4.1 callback transport */
225 struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */ 226 struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */
226 /* wait here for slots */ 227 /* wait here for slots */