diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-11-07 16:58:18 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-11-07 21:10:48 -0500 |
commit | 06f1f864d4ae5804e83785308d41f14a08e4b980 (patch) | |
tree | 44b3f33201d9f7a6b13cc1e3b276ccd9e6743996 /fs/nfsd | |
parent | c7e8472cf8ae877b232eb506284a5b15cf7efb2c (diff) |
nfsd4: hash lockowners to simplify RELEASE_LOCKOWNER
Hash lockowners on just the owner string rather than on (owner, inode).
This makes the owner-string lookup needed for RELEASE_LOCKOWNER simpler
(currently it's doing at a linear search through the entire hash
table!). That may come at the expense of making (owner, inode) lookups
more expensive if a client reuses the same lockowner across multiple
files. We might add a separate lookup for that.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 42 |
1 files changed, 14 insertions, 28 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1d6812db5099..eec990022ad3 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -3746,15 +3746,6 @@ last_byte_offset(u64 start, u64 len) | |||
3746 | return end > start ? end - 1: NFS4_MAX_UINT64; | 3746 | return end > start ? end - 1: NFS4_MAX_UINT64; |
3747 | } | 3747 | } |
3748 | 3748 | ||
3749 | static inline unsigned int | ||
3750 | lock_ownerstr_hashval(struct inode *inode, u32 cl_id, | ||
3751 | struct xdr_netobj *ownername) | ||
3752 | { | ||
3753 | return (file_hashval(inode) + cl_id | ||
3754 | + opaque_hashval(ownername->data, ownername->len)) | ||
3755 | & LOCK_HASH_MASK; | ||
3756 | } | ||
3757 | |||
3758 | static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; | 3749 | static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; |
3759 | 3750 | ||
3760 | /* | 3751 | /* |
@@ -3824,7 +3815,7 @@ static struct nfs4_lockowner * | |||
3824 | find_lockowner_str(struct inode *inode, clientid_t *clid, | 3815 | find_lockowner_str(struct inode *inode, clientid_t *clid, |
3825 | struct xdr_netobj *owner) | 3816 | struct xdr_netobj *owner) |
3826 | { | 3817 | { |
3827 | unsigned int hashval = lock_ownerstr_hashval(inode, clid->cl_id, owner); | 3818 | unsigned int hashval = open_ownerstr_hashval(clid->cl_id, owner); |
3828 | struct nfs4_lockowner *lo; | 3819 | struct nfs4_lockowner *lo; |
3829 | struct nfs4_stateowner *op; | 3820 | struct nfs4_stateowner *op; |
3830 | 3821 | ||
@@ -3847,7 +3838,7 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s | |||
3847 | * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has | 3838 | * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has |
3848 | * occurred. | 3839 | * occurred. |
3849 | * | 3840 | * |
3850 | * strhashval = lock_ownerstr_hashval | 3841 | * strhashval = open_ownerstr_hashval |
3851 | */ | 3842 | */ |
3852 | 3843 | ||
3853 | static struct nfs4_lockowner * | 3844 | static struct nfs4_lockowner * |
@@ -3922,7 +3913,7 @@ __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct n | |||
3922 | struct nfs4_ol_stateid, st_perstateowner); | 3913 | struct nfs4_ol_stateid, st_perstateowner); |
3923 | return nfs_ok; | 3914 | return nfs_ok; |
3924 | } | 3915 | } |
3925 | strhashval = lock_ownerstr_hashval(fi->fi_inode, cl->cl_clientid.cl_id, | 3916 | strhashval = open_ownerstr_hashval(cl->cl_clientid.cl_id, |
3926 | &lock->v.new.owner); | 3917 | &lock->v.new.owner); |
3927 | lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); | 3918 | lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); |
3928 | if (lo == NULL) | 3919 | if (lo == NULL) |
@@ -4286,7 +4277,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
4286 | struct nfs4_ol_stateid *stp; | 4277 | struct nfs4_ol_stateid *stp; |
4287 | struct xdr_netobj *owner = &rlockowner->rl_owner; | 4278 | struct xdr_netobj *owner = &rlockowner->rl_owner; |
4288 | struct list_head matches; | 4279 | struct list_head matches; |
4289 | int i; | 4280 | unsigned int hashval = open_ownerstr_hashval(clid->cl_id, owner); |
4290 | __be32 status; | 4281 | __be32 status; |
4291 | 4282 | ||
4292 | dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", | 4283 | dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", |
@@ -4301,22 +4292,17 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
4301 | nfs4_lock_state(); | 4292 | nfs4_lock_state(); |
4302 | 4293 | ||
4303 | status = nfserr_locks_held; | 4294 | status = nfserr_locks_held; |
4304 | /* XXX: we're doing a linear search through all the lockowners. | ||
4305 | * Yipes! For now we'll just hope clients aren't really using | ||
4306 | * release_lockowner much, but eventually we have to fix these | ||
4307 | * data structures. */ | ||
4308 | INIT_LIST_HEAD(&matches); | 4295 | INIT_LIST_HEAD(&matches); |
4309 | for (i = 0; i < LOCK_HASH_SIZE; i++) { | 4296 | |
4310 | list_for_each_entry(sop, &lock_ownerstr_hashtbl[i], so_strhash) { | 4297 | list_for_each_entry(sop, &lock_ownerstr_hashtbl[hashval], so_strhash) { |
4311 | if (!same_owner_str(sop, owner, clid)) | 4298 | if (!same_owner_str(sop, owner, clid)) |
4312 | continue; | 4299 | continue; |
4313 | list_for_each_entry(stp, &sop->so_stateids, | 4300 | list_for_each_entry(stp, &sop->so_stateids, |
4314 | st_perstateowner) { | 4301 | st_perstateowner) { |
4315 | lo = lockowner(sop); | 4302 | lo = lockowner(sop); |
4316 | if (check_for_locks(stp->st_file, lo)) | 4303 | if (check_for_locks(stp->st_file, lo)) |
4317 | goto out; | 4304 | goto out; |
4318 | list_add(&lo->lo_list, &matches); | 4305 | list_add(&lo->lo_list, &matches); |
4319 | } | ||
4320 | } | 4306 | } |
4321 | } | 4307 | } |
4322 | /* Clients probably won't expect us to return with some (but not all) | 4308 | /* Clients probably won't expect us to return with some (but not all) |