aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-11-14 10:21:51 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-11-15 07:40:47 -0500
commit1872de0e8171904612ee85de218fa045bc473cad (patch)
tree807822b296dab38e1fad9ffacefe40b2757c3f1e /fs/nfsd/nfs4state.c
parent20e9e2bc98b907efe82621797c561f6169d63d96 (diff)
nfsd: make sessionid_hashtbl allocated per net
This hash holds established sessions state and closely associated with nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace too. Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1e76d55a3e9a..248f217a00bc 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -632,9 +632,6 @@ static void release_openowner(struct nfs4_openowner *oo)
632 nfs4_free_openowner(oo); 632 nfs4_free_openowner(oo);
633} 633}
634 634
635#define SESSION_HASH_SIZE 512
636static struct list_head sessionid_hashtbl[SESSION_HASH_SIZE];
637
638static inline int 635static inline int
639hash_sessionid(struct nfs4_sessionid *sessionid) 636hash_sessionid(struct nfs4_sessionid *sessionid)
640{ 637{
@@ -928,6 +925,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
928static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses) 925static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
929{ 926{
930 int idx; 927 int idx;
928 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
931 929
932 new->se_client = clp; 930 new->se_client = clp;
933 gen_sessionid(new); 931 gen_sessionid(new);
@@ -941,7 +939,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
941 kref_init(&new->se_ref); 939 kref_init(&new->se_ref);
942 idx = hash_sessionid(&new->se_sessionid); 940 idx = hash_sessionid(&new->se_sessionid);
943 spin_lock(&client_lock); 941 spin_lock(&client_lock);
944 list_add(&new->se_hash, &sessionid_hashtbl[idx]); 942 list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
945 spin_lock(&clp->cl_lock); 943 spin_lock(&clp->cl_lock);
946 list_add(&new->se_perclnt, &clp->cl_sessions); 944 list_add(&new->se_perclnt, &clp->cl_sessions);
947 spin_unlock(&clp->cl_lock); 945 spin_unlock(&clp->cl_lock);
@@ -963,15 +961,16 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
963 961
964/* caller must hold client_lock */ 962/* caller must hold client_lock */
965static struct nfsd4_session * 963static struct nfsd4_session *
966find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid) 964find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid, struct net *net)
967{ 965{
968 struct nfsd4_session *elem; 966 struct nfsd4_session *elem;
969 int idx; 967 int idx;
968 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
970 969
971 dump_sessionid(__func__, sessionid); 970 dump_sessionid(__func__, sessionid);
972 idx = hash_sessionid(sessionid); 971 idx = hash_sessionid(sessionid);
973 /* Search in the appropriate list */ 972 /* Search in the appropriate list */
974 list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) { 973 list_for_each_entry(elem, &nn->sessionid_hashtbl[idx], se_hash) {
975 if (!memcmp(elem->se_sessionid.data, sessionid->data, 974 if (!memcmp(elem->se_sessionid.data, sessionid->data,
976 NFS4_MAX_SESSIONID_LEN)) { 975 NFS4_MAX_SESSIONID_LEN)) {
977 return elem; 976 return elem;
@@ -1905,7 +1904,7 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
1905 if (!nfsd4_last_compound_op(rqstp)) 1904 if (!nfsd4_last_compound_op(rqstp))
1906 return nfserr_not_only_op; 1905 return nfserr_not_only_op;
1907 spin_lock(&client_lock); 1906 spin_lock(&client_lock);
1908 cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid); 1907 cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid, SVC_NET(rqstp));
1909 /* Sorta weird: we only need the refcnt'ing because new_conn acquires 1908 /* Sorta weird: we only need the refcnt'ing because new_conn acquires
1910 * client_lock iself: */ 1909 * client_lock iself: */
1911 if (cstate->session) { 1910 if (cstate->session) {
@@ -1954,7 +1953,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
1954 } 1953 }
1955 dump_sessionid(__func__, &sessionid->sessionid); 1954 dump_sessionid(__func__, &sessionid->sessionid);
1956 spin_lock(&client_lock); 1955 spin_lock(&client_lock);
1957 ses = find_in_sessionid_hashtbl(&sessionid->sessionid); 1956 ses = find_in_sessionid_hashtbl(&sessionid->sessionid, SVC_NET(r));
1958 if (!ses) { 1957 if (!ses) {
1959 spin_unlock(&client_lock); 1958 spin_unlock(&client_lock);
1960 goto out; 1959 goto out;
@@ -2050,7 +2049,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
2050 2049
2051 spin_lock(&client_lock); 2050 spin_lock(&client_lock);
2052 status = nfserr_badsession; 2051 status = nfserr_badsession;
2053 session = find_in_sessionid_hashtbl(&seq->sessionid); 2052 session = find_in_sessionid_hashtbl(&seq->sessionid, SVC_NET(rqstp));
2054 if (!session) 2053 if (!session)
2055 goto out; 2054 goto out;
2056 2055
@@ -4719,8 +4718,6 @@ nfs4_state_init(void)
4719{ 4718{
4720 int i; 4719 int i;
4721 4720
4722 for (i = 0; i < SESSION_HASH_SIZE; i++)
4723 INIT_LIST_HEAD(&sessionid_hashtbl[i]);
4724 for (i = 0; i < FILE_HASH_SIZE; i++) { 4721 for (i = 0; i < FILE_HASH_SIZE; i++) {
4725 INIT_LIST_HEAD(&file_hashtbl[i]); 4722 INIT_LIST_HEAD(&file_hashtbl[i]);
4726 } 4723 }
@@ -4771,6 +4768,10 @@ static int nfs4_state_start_net(struct net *net)
4771 LOCKOWNER_INO_HASH_SIZE, GFP_KERNEL); 4768 LOCKOWNER_INO_HASH_SIZE, GFP_KERNEL);
4772 if (!nn->lockowner_ino_hashtbl) 4769 if (!nn->lockowner_ino_hashtbl)
4773 goto err_lockowner_ino; 4770 goto err_lockowner_ino;
4771 nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) *
4772 SESSION_HASH_SIZE, GFP_KERNEL);
4773 if (!nn->sessionid_hashtbl)
4774 goto err_sessionid;
4774 4775
4775 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 4776 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
4776 INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]); 4777 INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
@@ -4780,11 +4781,15 @@ static int nfs4_state_start_net(struct net *net)
4780 INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]); 4781 INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]);
4781 for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++) 4782 for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
4782 INIT_LIST_HEAD(&nn->lockowner_ino_hashtbl[i]); 4783 INIT_LIST_HEAD(&nn->lockowner_ino_hashtbl[i]);
4784 for (i = 0; i < SESSION_HASH_SIZE; i++)
4785 INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
4783 nn->conf_name_tree = RB_ROOT; 4786 nn->conf_name_tree = RB_ROOT;
4784 nn->unconf_name_tree = RB_ROOT; 4787 nn->unconf_name_tree = RB_ROOT;
4785 4788
4786 return 0; 4789 return 0;
4787 4790
4791err_sessionid:
4792 kfree(nn->lockowner_ino_hashtbl);
4788err_lockowner_ino: 4793err_lockowner_ino:
4789 kfree(nn->ownerstr_hashtbl); 4794 kfree(nn->ownerstr_hashtbl);
4790err_ownerstr: 4795err_ownerstr:
@@ -4819,6 +4824,7 @@ __nfs4_state_shutdown_net(struct net *net)
4819 destroy_client(clp); 4824 destroy_client(clp);
4820 } 4825 }
4821 4826
4827 kfree(nn->sessionid_hashtbl);
4822 kfree(nn->lockowner_ino_hashtbl); 4828 kfree(nn->lockowner_ino_hashtbl);
4823 kfree(nn->ownerstr_hashtbl); 4829 kfree(nn->ownerstr_hashtbl);
4824 kfree(nn->unconf_id_hashtbl); 4830 kfree(nn->unconf_id_hashtbl);