aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2010-06-14 19:01:57 -0400
committerJ. Bruce Fields <bfields@redhat.com>2010-10-21 10:11:51 -0400
commitac7c46f29a44f6d7f6d2e36dc874c0b7056acad2 (patch)
tree8349c56fbb67cb456fea62fee6ef29df20d6f87b /fs
parent90c8145bb6fe1d9e0a808de6a701748967588bbd (diff)
nfsd4: make backchannel sequence number per-session
Currently we don't deal well with a client that has multiple sessions associated with it (even simultaneously, or serially over the lifetime of the client). In particular, we don't attempt to keep the backchannel running after the original session diseappears. We will fix that soon. Once we do that, we need the slot sequence number to be per-session; otherwise, for example, we cannot correctly handle a case like this: - All session 1 connections are lost. - The client creates session 2. We use it for the backchannel (since it's the only working choice). - The client gives us a new connection to use with session 1. - The client destroys session 2. At this point our only choice is to go back to using session 1. When we do so we must use the sequence number that is next for session 1. We therefore need to maintain multiple sequence number streams. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/nfs4callback.c8
-rw-r--r--fs/nfsd/nfs4state.c22
-rw-r--r--fs/nfsd/state.h2
3 files changed, 17 insertions, 15 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 78ac779c09ff..5df9dda47bf4 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -260,7 +260,7 @@ encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
260 260
261 WRITE32(OP_CB_SEQUENCE); 261 WRITE32(OP_CB_SEQUENCE);
262 WRITEMEM(ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN); 262 WRITEMEM(ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN);
263 WRITE32(cb->cb_clp->cl_cb_seq_nr); 263 WRITE32(ses->se_cb_seq_nr);
264 WRITE32(0); /* slotid, always 0 */ 264 WRITE32(0); /* slotid, always 0 */
265 WRITE32(0); /* highest slotid always 0 */ 265 WRITE32(0); /* highest slotid always 0 */
266 WRITE32(0); /* cachethis always 0 */ 266 WRITE32(0); /* cachethis always 0 */
@@ -369,7 +369,7 @@ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
369 goto out; 369 goto out;
370 } 370 }
371 READ32(dummy); 371 READ32(dummy);
372 if (dummy != cb->cb_clp->cl_cb_seq_nr) { 372 if (dummy != ses->se_cb_seq_nr) {
373 dprintk("%s Invalid sequence number\n", __func__); 373 dprintk("%s Invalid sequence number\n", __func__);
374 goto out; 374 goto out;
375 } 375 }
@@ -643,11 +643,11 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
643 643
644 if (clp->cl_cb_conn.cb_minorversion) { 644 if (clp->cl_cb_conn.cb_minorversion) {
645 /* No need for lock, access serialized in nfsd4_cb_prepare */ 645 /* No need for lock, access serialized in nfsd4_cb_prepare */
646 ++clp->cl_cb_seq_nr; 646 ++clp->cl_cb_session->se_cb_seq_nr;
647 clear_bit(0, &clp->cl_cb_slot_busy); 647 clear_bit(0, &clp->cl_cb_slot_busy);
648 rpc_wake_up_next(&clp->cl_cb_waitq); 648 rpc_wake_up_next(&clp->cl_cb_waitq);
649 dprintk("%s: freed slot, new seqid=%d\n", __func__, 649 dprintk("%s: freed slot, new seqid=%d\n", __func__,
650 clp->cl_cb_seq_nr); 650 clp->cl_cb_session->se_cb_seq_nr);
651 651
652 /* We're done looking into the sequence information */ 652 /* We're done looking into the sequence information */
653 task->tk_msg.rpc_resp = NULL; 653 task->tk_msg.rpc_resp = NULL;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index c942511f73e6..6367c445d015 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -725,8 +725,7 @@ void free_session(struct kref *kref)
725 kfree(ses); 725 kfree(ses);
726} 726}
727 727
728 728static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
729static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
730{ 729{
731 struct nfsd4_session *new; 730 struct nfsd4_session *new;
732 struct nfsd4_channel_attrs *fchan = &cses->fore_channel; 731 struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
@@ -747,7 +746,7 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
747 new = alloc_session(slotsize, numslots); 746 new = alloc_session(slotsize, numslots);
748 if (!new) { 747 if (!new) {
749 nfsd4_put_drc_mem(slotsize, fchan->maxreqs); 748 nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
750 return nfserr_jukebox; 749 return NULL;
751 } 750 }
752 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize); 751 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
753 752
@@ -756,6 +755,7 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
756 755
757 INIT_LIST_HEAD(&new->se_conns); 756 INIT_LIST_HEAD(&new->se_conns);
758 757
758 new->se_cb_seq_nr = 1;
759 new->se_flags = cses->flags; 759 new->se_flags = cses->flags;
760 kref_init(&new->se_ref); 760 kref_init(&new->se_ref);
761 idx = hash_sessionid(&new->se_sessionid); 761 idx = hash_sessionid(&new->se_sessionid);
@@ -765,9 +765,10 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
765 spin_unlock(&client_lock); 765 spin_unlock(&client_lock);
766 766
767 status = nfsd4_new_conn(rqstp, new); 767 status = nfsd4_new_conn(rqstp, new);
768 /* whoops: benny points out, status is ignored! (err, or bogus) */
768 if (status) { 769 if (status) {
769 free_session(&new->se_ref); 770 free_session(&new->se_ref);
770 return nfserr_jukebox; 771 return NULL;
771 } 772 }
772 if (!clp->cl_cb_session && (cses->flags & SESSION4_BACK_CHAN)) { 773 if (!clp->cl_cb_session && (cses->flags & SESSION4_BACK_CHAN)) {
773 struct sockaddr *sa = svc_addr(rqstp); 774 struct sockaddr *sa = svc_addr(rqstp);
@@ -779,10 +780,9 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
779 clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); 780 clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
780 clp->cl_cb_conn.cb_minorversion = 1; 781 clp->cl_cb_conn.cb_minorversion = 1;
781 clp->cl_cb_conn.cb_prog = cses->callback_prog; 782 clp->cl_cb_conn.cb_prog = cses->callback_prog;
782 clp->cl_cb_seq_nr = 1;
783 nfsd4_probe_callback(clp, &clp->cl_cb_conn); 783 nfsd4_probe_callback(clp, &clp->cl_cb_conn);
784 } 784 }
785 return nfs_ok; 785 return new;
786} 786}
787 787
788/* caller must hold client_lock */ 788/* caller must hold client_lock */
@@ -1485,6 +1485,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1485{ 1485{
1486 struct sockaddr *sa = svc_addr(rqstp); 1486 struct sockaddr *sa = svc_addr(rqstp);
1487 struct nfs4_client *conf, *unconf; 1487 struct nfs4_client *conf, *unconf;
1488 struct nfsd4_session *new;
1488 struct nfsd4_clid_slot *cs_slot = NULL; 1489 struct nfsd4_clid_slot *cs_slot = NULL;
1489 int status = 0; 1490 int status = 0;
1490 1491
@@ -1538,11 +1539,12 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1538 cr_ses->flags &= ~SESSION4_PERSIST; 1539 cr_ses->flags &= ~SESSION4_PERSIST;
1539 cr_ses->flags &= ~SESSION4_RDMA; 1540 cr_ses->flags &= ~SESSION4_RDMA;
1540 1541
1541 status = alloc_init_session(rqstp, conf, cr_ses); 1542 status = nfserr_jukebox;
1542 if (status) 1543 new = alloc_init_session(rqstp, conf, cr_ses);
1544 if (!new)
1543 goto out; 1545 goto out;
1544 1546 status = nfs_ok;
1545 memcpy(cr_ses->sessionid.data, conf->cl_cb_session->se_sessionid.data, 1547 memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
1546 NFS4_MAX_SESSIONID_LEN); 1548 NFS4_MAX_SESSIONID_LEN);
1547 cr_ses->seqid = cs_slot->sl_seqid; 1549 cr_ses->seqid = cs_slot->sl_seqid;
1548 1550
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index cdce26ad50b5..7f5b2671ef18 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -172,6 +172,7 @@ struct nfsd4_session {
172 struct nfsd4_channel_attrs se_fchannel; 172 struct nfsd4_channel_attrs se_fchannel;
173 struct nfsd4_channel_attrs se_bchannel; 173 struct nfsd4_channel_attrs se_bchannel;
174 struct list_head se_conns; 174 struct list_head se_conns;
175 u32 se_cb_seq_nr;
175 struct nfsd4_slot *se_slots[]; /* forward channel slots */ 176 struct nfsd4_slot *se_slots[]; /* forward channel slots */
176}; 177};
177 178
@@ -249,7 +250,6 @@ struct nfs4_client {
249 /* for nfs41 callbacks */ 250 /* for nfs41 callbacks */
250 /* We currently support a single back channel with a single slot */ 251 /* We currently support a single back channel with a single slot */
251 unsigned long cl_cb_slot_busy; 252 unsigned long cl_cb_slot_busy;
252 u32 cl_cb_seq_nr;
253 struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */ 253 struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */
254 /* wait here for slots */ 254 /* wait here for slots */
255}; 255};