summaryrefslogtreecommitdiff
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2010-09-30 00:11:06 +0400
committerJ. Bruce Fields <bfields@redhat.com>2010-10-02 03:29:45 +0400
commit328ead287220711c3ad4490b1f3f691855df4039 (patch)
tree5b8d5de0d2a922af7e3e300e9b521ba058d4f8f3 /fs/nfsd
parentdb90681d6eff89efc1eee523e1cb77eb632a6cf7 (diff)
downloadlinux-328ead287220711c3ad4490b1f3f691855df4039.tar.xz
nfsd4: add new connections to session
As long as we're not implementing any session security, we should just automatically add any new connections that come along to the list of sessions associated with the session. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 3b4d74cbb6c8..596702e157c9 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -658,13 +658,18 @@ static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp)
return conn;
}
+static void __nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
+{
+ conn->cn_session = ses;
+ list_add(&conn->cn_persession, &ses->se_conns);
+}
+
static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
{
struct nfs4_client *clp = ses->se_client;
spin_lock(&clp->cl_lock);
- conn->cn_session = ses;
- list_add(&conn->cn_persession, &ses->se_conns);
+ __nfsd4_hash_conn(conn, ses);
spin_unlock(&clp->cl_lock);
}
@@ -1612,6 +1617,44 @@ out:
return status;
}
+static struct nfsd4_conn *__nfsd4_find_conn(struct svc_rqst *r, struct nfsd4_session *s)
+{
+ struct nfsd4_conn *c;
+
+ list_for_each_entry(c, &s->se_conns, cn_persession) {
+ if (c->cn_xprt == r->rq_xprt) {
+ return c;
+ }
+ }
+ return NULL;
+}
+
+static void nfsd4_sequence_check_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
+{
+ struct nfs4_client *clp = ses->se_client;
+ struct nfsd4_conn *c, *new = NULL;
+
+ spin_lock(&clp->cl_lock);
+ c = __nfsd4_find_conn(rqstp, ses);
+ spin_unlock(&clp->cl_lock);
+ if (c)
+ return;
+
+ new = alloc_conn(rqstp);
+
+ spin_lock(&clp->cl_lock);
+ c = __nfsd4_find_conn(rqstp, ses);
+ if (c) {
+ spin_unlock(&clp->cl_lock);
+ free_conn(new);
+ return;
+ }
+ __nfsd4_hash_conn(new, ses);
+ spin_unlock(&clp->cl_lock);
+ nfsd4_register_conn(new);
+ return;
+}
+
__be32
nfsd4_sequence(struct svc_rqst *rqstp,
struct nfsd4_compound_state *cstate,
@@ -1656,6 +1699,8 @@ nfsd4_sequence(struct svc_rqst *rqstp,
if (status)
goto out;
+ nfsd4_sequence_check_conn(rqstp, session);
+
/* Success! bump slot seqid */
slot->sl_inuse = true;
slot->sl_seqid = seq->seqid;