aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
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/nfsd/nfs4state.c
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/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c22
1 files changed, 12 insertions, 10 deletions
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