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>
This commit is contained in:
Родитель
c4bf786806
Коммит
5282fd724b
|
@ -382,11 +382,62 @@ static void release_openowner(struct nfs4_stateowner *sop)
|
|||
nfs4_put_stateowner(sop);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(sessionid_lock);
|
||||
#define SESSION_HASH_SIZE 512
|
||||
static struct list_head sessionid_hashtbl[SESSION_HASH_SIZE];
|
||||
|
||||
static inline int
|
||||
hash_sessionid(struct nfs4_sessionid *sessionid)
|
||||
{
|
||||
struct nfsd4_sessionid *sid = (struct nfsd4_sessionid *)sessionid;
|
||||
|
||||
return sid->sequence % SESSION_HASH_SIZE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
|
||||
{
|
||||
u32 *ptr = (u32 *)(&sessionid->data[0]);
|
||||
dprintk("%s: %u:%u:%u:%u\n", fn, ptr[0], ptr[1], ptr[2], ptr[3]);
|
||||
}
|
||||
|
||||
/* caller must hold sessionid_lock */
|
||||
static struct nfsd4_session *
|
||||
find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)
|
||||
{
|
||||
struct nfsd4_session *elem;
|
||||
int idx;
|
||||
|
||||
dump_sessionid(__func__, sessionid);
|
||||
idx = hash_sessionid(sessionid);
|
||||
dprintk("%s: idx is %d\n", __func__, idx);
|
||||
/* Search in the appropriate list */
|
||||
list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) {
|
||||
dump_sessionid("list traversal", &elem->se_sessionid);
|
||||
if (!memcmp(elem->se_sessionid.data, sessionid->data,
|
||||
NFS4_MAX_SESSIONID_LEN)) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
||||
dprintk("%s: session not found\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* caller must hold sessionid_lock */
|
||||
static void
|
||||
release_session(struct nfsd4_session *ses)
|
||||
unhash_session(struct nfsd4_session *ses)
|
||||
{
|
||||
list_del(&ses->se_hash);
|
||||
list_del(&ses->se_perclnt);
|
||||
}
|
||||
|
||||
static void
|
||||
release_session(struct nfsd4_session *ses)
|
||||
{
|
||||
spin_lock(&sessionid_lock);
|
||||
unhash_session(ses);
|
||||
spin_unlock(&sessionid_lock);
|
||||
nfsd4_put_session(ses);
|
||||
}
|
||||
|
||||
|
@ -3205,6 +3256,8 @@ nfs4_state_init(void)
|
|||
INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
|
||||
INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
|
||||
}
|
||||
for (i = 0; i < SESSION_HASH_SIZE; i++)
|
||||
INIT_LIST_HEAD(&sessionid_hashtbl[i]);
|
||||
for (i = 0; i < FILE_HASH_SIZE; i++) {
|
||||
INIT_LIST_HEAD(&file_hashtbl[i]);
|
||||
}
|
||||
|
|
|
@ -132,6 +132,13 @@ nfsd4_get_session(struct nfsd4_session *ses)
|
|||
kref_get(&ses->se_ref);
|
||||
}
|
||||
|
||||
/* formatted contents of nfs4_sessionid */
|
||||
struct nfsd4_sessionid {
|
||||
clientid_t clientid;
|
||||
u32 sequence;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
#define HEXDIR_LEN 33 /* hex version of 16 byte md5 of cl_name plus '\0' */
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче