aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-11-07 17:23:30 -0500
committerJ. Bruce Fields <bfields@redhat.com>2011-11-08 11:28:45 -0500
commit16bfdaafa2c66d8cc81422a97a105a849ca65b3e (patch)
tree122c457da33077af885dbfea1d2c7745325f80ec /fs/nfsd
parent06f1f864d4ae5804e83785308d41f14a08e4b980 (diff)
nfsd4: share open and lock owner hash tables
Now that they're used in the same way, it's a little simpler to put open and lock owners in the same hash table, and I can't see a reason not to. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c71
1 files changed, 32 insertions, 39 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index eec990022ad3..dcbe7f37759d 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -133,21 +133,21 @@ unsigned int max_delegations;
133 * Open owner state (share locks) 133 * Open owner state (share locks)
134 */ 134 */
135 135
136/* hash tables for open owners */ 136/* hash tables for lock and open owners */
137#define OPEN_OWNER_HASH_BITS 8 137#define OWNER_HASH_BITS 8
138#define OPEN_OWNER_HASH_SIZE (1 << OPEN_OWNER_HASH_BITS) 138#define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS)
139#define OPEN_OWNER_HASH_MASK (OPEN_OWNER_HASH_SIZE - 1) 139#define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1)
140 140
141static unsigned int open_ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername) 141static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername)
142{ 142{
143 unsigned int ret; 143 unsigned int ret;
144 144
145 ret = opaque_hashval(ownername->data, ownername->len); 145 ret = opaque_hashval(ownername->data, ownername->len);
146 ret += clientid; 146 ret += clientid;
147 return ret & OPEN_OWNER_HASH_MASK; 147 return ret & OWNER_HASH_MASK;
148} 148}
149 149
150static struct list_head open_ownerstr_hashtbl[OPEN_OWNER_HASH_SIZE]; 150static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
151 151
152/* hash table for nfs4_file */ 152/* hash table for nfs4_file */
153#define FILE_HASH_BITS 8 153#define FILE_HASH_BITS 8
@@ -2373,7 +2373,7 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj
2373 2373
2374static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) 2374static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval)
2375{ 2375{
2376 list_add(&oo->oo_owner.so_strhash, &open_ownerstr_hashtbl[strhashval]); 2376 list_add(&oo->oo_owner.so_strhash, &ownerstr_hashtbl[strhashval]);
2377 list_add(&oo->oo_perclient, &clp->cl_openowners); 2377 list_add(&oo->oo_perclient, &clp->cl_openowners);
2378} 2378}
2379 2379
@@ -2436,7 +2436,9 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open)
2436 struct nfs4_stateowner *so; 2436 struct nfs4_stateowner *so;
2437 struct nfs4_openowner *oo; 2437 struct nfs4_openowner *oo;
2438 2438
2439 list_for_each_entry(so, &open_ownerstr_hashtbl[hashval], so_strhash) { 2439 list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
2440 if (!so->so_is_open_owner)
2441 continue;
2440 if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { 2442 if (same_owner_str(so, &open->op_owner, &open->op_clientid)) {
2441 oo = openowner(so); 2443 oo = openowner(so);
2442 renew_client(oo->oo_owner.so_client); 2444 renew_client(oo->oo_owner.so_client);
@@ -2580,7 +2582,7 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
2580 if (open->op_file == NULL) 2582 if (open->op_file == NULL)
2581 return nfserr_jukebox; 2583 return nfserr_jukebox;
2582 2584
2583 strhashval = open_ownerstr_hashval(clientid->cl_id, &open->op_owner); 2585 strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner);
2584 oo = find_openstateowner_str(strhashval, open); 2586 oo = find_openstateowner_str(strhashval, open);
2585 open->op_openowner = oo; 2587 open->op_openowner = oo;
2586 if (!oo) { 2588 if (!oo) {
@@ -3718,13 +3720,7 @@ out:
3718} 3720}
3719 3721
3720 3722
3721/*
3722 * Lock owner state (byte-range locks)
3723 */
3724#define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start)) 3723#define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start))
3725#define LOCK_HASH_BITS 8
3726#define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS)
3727#define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1)
3728 3724
3729static inline u64 3725static inline u64
3730end_offset(u64 start, u64 len) 3726end_offset(u64 start, u64 len)
@@ -3746,8 +3742,6 @@ last_byte_offset(u64 start, u64 len)
3746 return end > start ? end - 1: NFS4_MAX_UINT64; 3742 return end > start ? end - 1: NFS4_MAX_UINT64;
3747} 3743}
3748 3744
3749static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
3750
3751/* 3745/*
3752 * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that 3746 * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
3753 * we can't properly handle lock requests that go beyond the (2^63 - 1)-th 3747 * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
@@ -3815,11 +3809,13 @@ static struct nfs4_lockowner *
3815find_lockowner_str(struct inode *inode, clientid_t *clid, 3809find_lockowner_str(struct inode *inode, clientid_t *clid,
3816 struct xdr_netobj *owner) 3810 struct xdr_netobj *owner)
3817{ 3811{
3818 unsigned int hashval = open_ownerstr_hashval(clid->cl_id, owner); 3812 unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
3819 struct nfs4_lockowner *lo; 3813 struct nfs4_lockowner *lo;
3820 struct nfs4_stateowner *op; 3814 struct nfs4_stateowner *op;
3821 3815
3822 list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) { 3816 list_for_each_entry(op, &ownerstr_hashtbl[hashval], so_strhash) {
3817 if (op->so_is_open_owner)
3818 continue;
3823 lo = lockowner(op); 3819 lo = lockowner(op);
3824 if (same_lockowner_ino(lo, inode, clid, owner)) 3820 if (same_lockowner_ino(lo, inode, clid, owner))
3825 return lo; 3821 return lo;
@@ -3829,7 +3825,7 @@ find_lockowner_str(struct inode *inode, clientid_t *clid,
3829 3825
3830static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp) 3826static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp)
3831{ 3827{
3832 list_add(&lo->lo_owner.so_strhash, &lock_ownerstr_hashtbl[strhashval]); 3828 list_add(&lo->lo_owner.so_strhash, &ownerstr_hashtbl[strhashval]);
3833 list_add(&lo->lo_perstateid, &open_stp->st_lockowners); 3829 list_add(&lo->lo_perstateid, &open_stp->st_lockowners);
3834} 3830}
3835 3831
@@ -3838,7 +3834,7 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s
3838 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has 3834 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has
3839 * occurred. 3835 * occurred.
3840 * 3836 *
3841 * strhashval = open_ownerstr_hashval 3837 * strhashval = ownerstr_hashval
3842 */ 3838 */
3843 3839
3844static struct nfs4_lockowner * 3840static struct nfs4_lockowner *
@@ -3913,7 +3909,7 @@ __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct n
3913 struct nfs4_ol_stateid, st_perstateowner); 3909 struct nfs4_ol_stateid, st_perstateowner);
3914 return nfs_ok; 3910 return nfs_ok;
3915 } 3911 }
3916 strhashval = open_ownerstr_hashval(cl->cl_clientid.cl_id, 3912 strhashval = ownerstr_hashval(cl->cl_clientid.cl_id,
3917 &lock->v.new.owner); 3913 &lock->v.new.owner);
3918 lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); 3914 lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock);
3919 if (lo == NULL) 3915 if (lo == NULL)
@@ -4277,7 +4273,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
4277 struct nfs4_ol_stateid *stp; 4273 struct nfs4_ol_stateid *stp;
4278 struct xdr_netobj *owner = &rlockowner->rl_owner; 4274 struct xdr_netobj *owner = &rlockowner->rl_owner;
4279 struct list_head matches; 4275 struct list_head matches;
4280 unsigned int hashval = open_ownerstr_hashval(clid->cl_id, owner); 4276 unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
4281 __be32 status; 4277 __be32 status;
4282 4278
4283 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", 4279 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
@@ -4294,7 +4290,9 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
4294 status = nfserr_locks_held; 4290 status = nfserr_locks_held;
4295 INIT_LIST_HEAD(&matches); 4291 INIT_LIST_HEAD(&matches);
4296 4292
4297 list_for_each_entry(sop, &lock_ownerstr_hashtbl[hashval], so_strhash) { 4293 list_for_each_entry(sop, &ownerstr_hashtbl[hashval], so_strhash) {
4294 if (sop->so_is_open_owner)
4295 continue;
4298 if (!same_owner_str(sop, owner, clid)) 4296 if (!same_owner_str(sop, owner, clid))
4299 continue; 4297 continue;
4300 list_for_each_entry(stp, &sop->so_stateids, 4298 list_for_each_entry(stp, &sop->so_stateids,
@@ -4444,16 +4442,16 @@ static void release_openowner_sop(struct nfs4_stateowner *sop)
4444 release_openowner(openowner(sop)); 4442 release_openowner(openowner(sop));
4445} 4443}
4446 4444
4447static int nfsd_release_n_owners(u64 num, 4445static int nfsd_release_n_owners(u64 num, bool is_open_owner
4448 struct list_head hashtbl[],
4449 unsigned int hashtbl_size,
4450 void (*release_sop)(struct nfs4_stateowner *)) 4446 void (*release_sop)(struct nfs4_stateowner *))
4451{ 4447{
4452 int i, count = 0; 4448 int i, count = 0;
4453 struct nfs4_stateowner *sop, *next; 4449 struct nfs4_stateowner *sop, *next;
4454 4450
4455 for (i = 0; i < hashtbl_size; i++) { 4451 for (i = 0; i < OWNER_HASH_SIZE; i++) {
4456 list_for_each_entry_safe(sop, next, &hashtbl[i], so_strhash) { 4452 list_for_each_entry_safe(sop, next, &ownerstr_hashtbl[i], so_strhash) {
4453 if (sop->so_is_open_owner != is_open_owner)
4454 continue;
4457 release_sop(sop); 4455 release_sop(sop);
4458 if (++count == num) 4456 if (++count == num)
4459 return count; 4457 return count;
@@ -4467,8 +4465,7 @@ void nfsd_forget_locks(u64 num)
4467 int count; 4465 int count;
4468 4466
4469 nfs4_lock_state(); 4467 nfs4_lock_state();
4470 count = nfsd_release_n_owners(num, lock_ownerstr_hashtbl, 4468 count = nfsd_release_n_owners(num, false, release_lockowner_sop);
4471 LOCK_HASH_SIZE, release_lockowner_sop);
4472 nfs4_unlock_state(); 4469 nfs4_unlock_state();
4473 4470
4474 printk(KERN_INFO "NFSD: Forgot %d locks", count); 4471 printk(KERN_INFO "NFSD: Forgot %d locks", count);
@@ -4479,8 +4476,7 @@ void nfsd_forget_openowners(u64 num)
4479 int count; 4476 int count;
4480 4477
4481 nfs4_lock_state(); 4478 nfs4_lock_state();
4482 count = nfsd_release_n_owners(num, open_ownerstr_hashtbl, 4479 count = nfsd_release_n_owners(num, true, release_openowner_sop);
4483 OPEN_OWNER_HASH_SIZE, release_openowner_sop);
4484 nfs4_unlock_state(); 4480 nfs4_unlock_state();
4485 4481
4486 printk(KERN_INFO "NFSD: Forgot %d open owners", count); 4482 printk(KERN_INFO "NFSD: Forgot %d open owners", count);
@@ -4549,11 +4545,8 @@ nfs4_state_init(void)
4549 for (i = 0; i < FILE_HASH_SIZE; i++) { 4545 for (i = 0; i < FILE_HASH_SIZE; i++) {
4550 INIT_LIST_HEAD(&file_hashtbl[i]); 4546 INIT_LIST_HEAD(&file_hashtbl[i]);
4551 } 4547 }
4552 for (i = 0; i < OPEN_OWNER_HASH_SIZE; i++) { 4548 for (i = 0; i < OWNER_HASH_SIZE; i++) {
4553 INIT_LIST_HEAD(&open_ownerstr_hashtbl[i]); 4549 INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
4554 }
4555 for (i = 0; i < LOCK_HASH_SIZE; i++) {
4556 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
4557 } 4550 }
4558 memset(&onestateid, ~0, sizeof(stateid_t)); 4551 memset(&onestateid, ~0, sizeof(stateid_t));
4559 INIT_LIST_HEAD(&close_lru); 4552 INIT_LIST_HEAD(&close_lru);