aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Eshel <eshel@almaden.ibm.com>2009-04-03 01:27:52 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-04-03 20:41:14 -0400
commit5282fd724b667b7d65f2e41e405a825e58a78813 (patch)
tree6603d2895c789db0e2244e9966f3a2246a6addb9
parentc4bf7868064ce8b9c75d8049d077e593c20602b3 (diff)
nfsd41: sessionid hashing
Simple sessionid hashing using its monotonically increasing sequence number. Locking considerations: sessionid_hashtbl access is controlled by the sessionid_lock spin lock. It must be taken for insert, delete, and lookup. nfsd4_sequence looks up the session id and if the session is found, it calls nfsd4_get_session (still under the sessionid_lock). nfsd4_destroy_session calls nfsd4_put_session after unhashing it, so when the session's kref reaches zero it's going to get freed. Signed-off-by: Benny Halevy <bhalevy@panasas.com> [we don't use a prime for sessionid hash table size] [use sessionid_lock spin lock] Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--fs/nfsd/nfs4state.c55
-rw-r--r--include/linux/nfsd/state.h7
2 files changed, 61 insertions, 1 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f23385b13065..fc20e1f38d75 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -382,11 +382,62 @@ static void release_openowner(struct nfs4_stateowner *sop)
382 nfs4_put_stateowner(sop); 382 nfs4_put_stateowner(sop);
383} 383}
384 384
385static DEFINE_SPINLOCK(sessionid_lock);
386#define SESSION_HASH_SIZE 512
387static struct list_head sessionid_hashtbl[SESSION_HASH_SIZE];
388
389static inline int
390hash_sessionid(struct nfs4_sessionid *sessionid)
391{
392 struct nfsd4_sessionid *sid = (struct nfsd4_sessionid *)sessionid;
393
394 return sid->sequence % SESSION_HASH_SIZE;
395}
396
397static inline void
398dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
399{
400 u32 *ptr = (u32 *)(&sessionid->data[0]);
401 dprintk("%s: %u:%u:%u:%u\n", fn, ptr[0], ptr[1], ptr[2], ptr[3]);
402}
403
404/* caller must hold sessionid_lock */
405static struct nfsd4_session *
406find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)
407{
408 struct nfsd4_session *elem;
409 int idx;
410
411 dump_sessionid(__func__, sessionid);
412 idx = hash_sessionid(sessionid);
413 dprintk("%s: idx is %d\n", __func__, idx);
414 /* Search in the appropriate list */
415 list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) {
416 dump_sessionid("list traversal", &elem->se_sessionid);
417 if (!memcmp(elem->se_sessionid.data, sessionid->data,
418 NFS4_MAX_SESSIONID_LEN)) {
419 return elem;
420 }
421 }
422
423 dprintk("%s: session not found\n", __func__);
424 return NULL;
425}
426
427/* caller must hold sessionid_lock */
385static void 428static void
386release_session(struct nfsd4_session *ses) 429unhash_session(struct nfsd4_session *ses)
387{ 430{
388 list_del(&ses->se_hash); 431 list_del(&ses->se_hash);
389 list_del(&ses->se_perclnt); 432 list_del(&ses->se_perclnt);
433}
434
435static void
436release_session(struct nfsd4_session *ses)
437{
438 spin_lock(&sessionid_lock);
439 unhash_session(ses);
440 spin_unlock(&sessionid_lock);
390 nfsd4_put_session(ses); 441 nfsd4_put_session(ses);
391} 442}
392 443
@@ -3205,6 +3256,8 @@ nfs4_state_init(void)
3205 INIT_LIST_HEAD(&unconf_str_hashtbl[i]); 3256 INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
3206 INIT_LIST_HEAD(&unconf_id_hashtbl[i]); 3257 INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
3207 } 3258 }
3259 for (i = 0; i < SESSION_HASH_SIZE; i++)
3260 INIT_LIST_HEAD(&sessionid_hashtbl[i]);
3208 for (i = 0; i < FILE_HASH_SIZE; i++) { 3261 for (i = 0; i < FILE_HASH_SIZE; i++) {
3209 INIT_LIST_HEAD(&file_hashtbl[i]); 3262 INIT_LIST_HEAD(&file_hashtbl[i]);
3210 } 3263 }
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 7faefc7c9d9a..5b3a6660f3af 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -132,6 +132,13 @@ nfsd4_get_session(struct nfsd4_session *ses)
132 kref_get(&ses->se_ref); 132 kref_get(&ses->se_ref);
133} 133}
134 134
135/* formatted contents of nfs4_sessionid */
136struct nfsd4_sessionid {
137 clientid_t clientid;
138 u32 sequence;
139 u32 reserved;
140};
141
135#define HEXDIR_LEN 33 /* hex version of 16 byte md5 of cl_name plus '\0' */ 142#define HEXDIR_LEN 33 /* hex version of 16 byte md5 of cl_name plus '\0' */
136 143
137/* 144/*