aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-11-07 16:58:18 -0500
committerJ. Bruce Fields <bfields@redhat.com>2011-11-07 21:10:48 -0500
commit06f1f864d4ae5804e83785308d41f14a08e4b980 (patch)
tree44b3f33201d9f7a6b13cc1e3b276ccd9e6743996 /fs/nfsd
parentc7e8472cf8ae877b232eb506284a5b15cf7efb2c (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.c42
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
3749static inline unsigned int
3750lock_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
3758static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; 3749static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
3759 3750
3760/* 3751/*
@@ -3824,7 +3815,7 @@ static struct nfs4_lockowner *
3824find_lockowner_str(struct inode *inode, clientid_t *clid, 3815find_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
3853static struct nfs4_lockowner * 3844static 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)