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 | |
| 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>
| -rw-r--r-- | fs/nfsd/nfs4state.c | 69 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 8 | ||||
| -rw-r--r-- | include/linux/nfs4.h | 3 |
3 files changed, 65 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 | ||
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 07e40c625972..79b15fb2f304 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
| @@ -61,6 +61,9 @@ | |||
| 61 | #define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000 | 61 | #define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000 |
| 62 | #define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED 0x20000 | 62 | #define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED 0x20000 |
| 63 | 63 | ||
| 64 | #define NFS4_CDFC4_FORE 0x1 | ||
| 65 | #define NFS4_CDFC4_BACK 0x2 | ||
| 66 | |||
| 64 | #define NFS4_SET_TO_SERVER_TIME 0 | 67 | #define NFS4_SET_TO_SERVER_TIME 0 |
| 65 | #define NFS4_SET_TO_CLIENT_TIME 1 | 68 | #define NFS4_SET_TO_CLIENT_TIME 1 |
| 66 | 69 | ||
