diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2010-06-06 18:12:14 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-10-01 19:29:44 -0400 |
commit | c7662518c781edc8059cd9737d18168154bf7510 (patch) | |
tree | c622e315c4df927a915f2a7992eb946ae168b3b4 /fs/nfsd | |
parent | 5b6feee9608dce7afd2646f457c93e612526d1d8 (diff) |
nfsd4: keep per-session list of connections
The spec requires us in various places to keep track of the connections
associated with each session.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 69 | ||||
-rw-r--r-- | fs/nfsd/state.h | 8 |
2 files changed, 62 insertions, 15 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index f86476c23b2f..c7c1a7afa197 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -625,11 +625,58 @@ static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4 | |||
625 | new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND); | 625 | new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND); |
626 | } | 626 | } |
627 | 627 | ||
628 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) | ||
629 | { | ||
630 | struct nfs4_client *clp = ses->se_client; | ||
631 | struct nfsd4_conn *conn; | ||
632 | |||
633 | conn = kmalloc(sizeof(struct nfsd4_conn), GFP_KERNEL); | ||
634 | if (!conn) | ||
635 | return nfserr_jukebox; | ||
636 | conn->cn_flags = NFS4_CDFC4_FORE; | ||
637 | svc_xprt_get(rqstp->rq_xprt); | ||
638 | conn->cn_xprt = rqstp->rq_xprt; | ||
639 | |||
640 | spin_lock(&clp->cl_lock); | ||
641 | list_add(&conn->cn_persession, &ses->se_conns); | ||
642 | spin_unlock(&clp->cl_lock); | ||
643 | |||
644 | return nfs_ok; | ||
645 | } | ||
646 | |||
647 | static void free_conn(struct nfsd4_conn *c) | ||
648 | { | ||
649 | svc_xprt_put(c->cn_xprt); | ||
650 | kfree(c); | ||
651 | } | ||
652 | |||
653 | void free_session(struct kref *kref) | ||
654 | { | ||
655 | struct nfsd4_session *ses; | ||
656 | int mem; | ||
657 | |||
658 | ses = container_of(kref, struct nfsd4_session, se_ref); | ||
659 | while (!list_empty(&ses->se_conns)) { | ||
660 | struct nfsd4_conn *c; | ||
661 | c = list_first_entry(&ses->se_conns, struct nfsd4_conn, cn_persession); | ||
662 | list_del(&c->cn_persession); | ||
663 | free_conn(c); | ||
664 | } | ||
665 | spin_lock(&nfsd_drc_lock); | ||
666 | mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel); | ||
667 | nfsd_drc_mem_used -= mem; | ||
668 | spin_unlock(&nfsd_drc_lock); | ||
669 | free_session_slots(ses); | ||
670 | kfree(ses); | ||
671 | } | ||
672 | |||
673 | |||
628 | static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) | 674 | static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) |
629 | { | 675 | { |
630 | struct nfsd4_session *new; | 676 | struct nfsd4_session *new; |
631 | struct nfsd4_channel_attrs *fchan = &cses->fore_channel; | 677 | struct nfsd4_channel_attrs *fchan = &cses->fore_channel; |
632 | int numslots, slotsize; | 678 | int numslots, slotsize; |
679 | int status; | ||
633 | int idx; | 680 | int idx; |
634 | 681 | ||
635 | /* | 682 | /* |
@@ -654,6 +701,8 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp | |||
654 | memcpy(clp->cl_sessionid.data, new->se_sessionid.data, | 701 | memcpy(clp->cl_sessionid.data, new->se_sessionid.data, |
655 | NFS4_MAX_SESSIONID_LEN); | 702 | NFS4_MAX_SESSIONID_LEN); |
656 | 703 | ||
704 | INIT_LIST_HEAD(&new->se_conns); | ||
705 | |||
657 | new->se_flags = cses->flags; | 706 | new->se_flags = cses->flags; |
658 | kref_init(&new->se_ref); | 707 | kref_init(&new->se_ref); |
659 | idx = hash_sessionid(&new->se_sessionid); | 708 | idx = hash_sessionid(&new->se_sessionid); |
@@ -662,6 +711,11 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp | |||
662 | list_add(&new->se_perclnt, &clp->cl_sessions); | 711 | list_add(&new->se_perclnt, &clp->cl_sessions); |
663 | spin_unlock(&client_lock); | 712 | spin_unlock(&client_lock); |
664 | 713 | ||
714 | status = nfsd4_new_conn(rqstp, new); | ||
715 | if (status) { | ||
716 | free_session(&new->se_ref); | ||
717 | return nfserr_jukebox; | ||
718 | } | ||
665 | return nfs_ok; | 719 | return nfs_ok; |
666 | } | 720 | } |
667 | 721 | ||
@@ -694,21 +748,6 @@ unhash_session(struct nfsd4_session *ses) | |||
694 | list_del(&ses->se_perclnt); | 748 | list_del(&ses->se_perclnt); |
695 | } | 749 | } |
696 | 750 | ||
697 | void | ||
698 | free_session(struct kref *kref) | ||
699 | { | ||
700 | struct nfsd4_session *ses; | ||
701 | int mem; | ||
702 | |||
703 | ses = container_of(kref, struct nfsd4_session, se_ref); | ||
704 | spin_lock(&nfsd_drc_lock); | ||
705 | mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel); | ||
706 | nfsd_drc_mem_used -= mem; | ||
707 | spin_unlock(&nfsd_drc_lock); | ||
708 | free_session_slots(ses); | ||
709 | kfree(ses); | ||
710 | } | ||
711 | |||
712 | /* must be called under the client_lock */ | 751 | /* must be called under the client_lock */ |
713 | static inline void | 752 | static inline void |
714 | renew_client_locked(struct nfs4_client *clp) | 753 | renew_client_locked(struct nfs4_client *clp) |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 58bc2a63ca14..29413c2ed270 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -152,6 +152,13 @@ struct nfsd4_clid_slot { | |||
152 | struct nfsd4_create_session sl_cr_ses; | 152 | struct nfsd4_create_session sl_cr_ses; |
153 | }; | 153 | }; |
154 | 154 | ||
155 | struct nfsd4_conn { | ||
156 | struct list_head cn_persession; | ||
157 | struct svc_xprt *cn_xprt; | ||
158 | /* CDFC4_FORE, CDFC4_BACK: */ | ||
159 | unsigned char cn_flags; | ||
160 | }; | ||
161 | |||
155 | struct nfsd4_session { | 162 | struct nfsd4_session { |
156 | struct kref se_ref; | 163 | struct kref se_ref; |
157 | struct list_head se_hash; /* hash by sessionid */ | 164 | struct list_head se_hash; /* hash by sessionid */ |
@@ -161,6 +168,7 @@ struct nfsd4_session { | |||
161 | struct nfs4_sessionid se_sessionid; | 168 | struct nfs4_sessionid se_sessionid; |
162 | struct nfsd4_channel_attrs se_fchannel; | 169 | struct nfsd4_channel_attrs se_fchannel; |
163 | struct nfsd4_channel_attrs se_bchannel; | 170 | struct nfsd4_channel_attrs se_bchannel; |
171 | struct list_head se_conns; | ||
164 | struct nfsd4_slot *se_slots[]; /* forward channel slots */ | 172 | struct nfsd4_slot *se_slots[]; /* forward channel slots */ |
165 | }; | 173 | }; |
166 | 174 | ||