diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-11-07 17:23:30 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-11-08 11:28:45 -0500 |
commit | 16bfdaafa2c66d8cc81422a97a105a849ca65b3e (patch) | |
tree | 122c457da33077af885dbfea1d2c7745325f80ec /fs/nfsd | |
parent | 06f1f864d4ae5804e83785308d41f14a08e4b980 (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.c | 71 |
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 | ||
141 | static unsigned int open_ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername) | 141 | static 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 | ||
150 | static struct list_head open_ownerstr_hashtbl[OPEN_OWNER_HASH_SIZE]; | 150 | static 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 | ||
2374 | static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) | 2374 | static 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 | ||
3729 | static inline u64 | 3725 | static inline u64 |
3730 | end_offset(u64 start, u64 len) | 3726 | end_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 | ||
3749 | static 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 * | |||
3815 | find_lockowner_str(struct inode *inode, clientid_t *clid, | 3809 | find_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 | ||
3830 | static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp) | 3826 | static 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 | ||
3844 | static struct nfs4_lockowner * | 3840 | static 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 | ||
4447 | static int nfsd_release_n_owners(u64 num, | 4445 | static 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); |