diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-11-14 10:21:41 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-11-15 07:40:46 -0500 |
commit | 9b5311374057e5c87017ea3756e566047c9b61e7 (patch) | |
tree | 3cde40f55baf51b9cc29ac60a8a28bff3d94a7ef /fs | |
parent | a99454aa4ff1241a19dcb486fa302d3e8cc09e5b (diff) |
nfsd: make ownerstr_hashtbl allocated per net
This hash holds open owner state and closely associated with nfs4_clients
info, which are network namespace aware. So let's make it allocated per
network namespace too.
Note: this hash can be allocated in per-net operations. But it looks
better to allocate it on nfsd state start and thus don't waste resources
if server is not running.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/netns.h | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 41 |
2 files changed, 27 insertions, 15 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 1e76030e1d16..46cca9494c7a 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h | |||
@@ -60,6 +60,7 @@ struct nfsd_net { | |||
60 | struct rb_root conf_name_tree; | 60 | struct rb_root conf_name_tree; |
61 | struct list_head *unconf_id_hashtbl; | 61 | struct list_head *unconf_id_hashtbl; |
62 | struct rb_root unconf_name_tree; | 62 | struct rb_root unconf_name_tree; |
63 | struct list_head *ownerstr_hashtbl; | ||
63 | }; | 64 | }; |
64 | 65 | ||
65 | extern int nfsd_net_id; | 66 | extern int nfsd_net_id; |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index b35329199e35..f68514d8210e 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -176,8 +176,6 @@ static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername) | |||
176 | return ret & OWNER_HASH_MASK; | 176 | return ret & OWNER_HASH_MASK; |
177 | } | 177 | } |
178 | 178 | ||
179 | static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; | ||
180 | |||
181 | /* hash table for nfs4_file */ | 179 | /* hash table for nfs4_file */ |
182 | #define FILE_HASH_BITS 8 | 180 | #define FILE_HASH_BITS 8 |
183 | #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) | 181 | #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) |
@@ -2428,7 +2426,9 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj | |||
2428 | 2426 | ||
2429 | static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) | 2427 | static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) |
2430 | { | 2428 | { |
2431 | list_add(&oo->oo_owner.so_strhash, &ownerstr_hashtbl[strhashval]); | 2429 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); |
2430 | |||
2431 | list_add(&oo->oo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]); | ||
2432 | list_add(&oo->oo_perclient, &clp->cl_openowners); | 2432 | list_add(&oo->oo_perclient, &clp->cl_openowners); |
2433 | } | 2433 | } |
2434 | 2434 | ||
@@ -2486,13 +2486,14 @@ same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, | |||
2486 | } | 2486 | } |
2487 | 2487 | ||
2488 | static struct nfs4_openowner * | 2488 | static struct nfs4_openowner * |
2489 | find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions) | 2489 | find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, |
2490 | bool sessions, struct nfsd_net *nn) | ||
2490 | { | 2491 | { |
2491 | struct nfs4_stateowner *so; | 2492 | struct nfs4_stateowner *so; |
2492 | struct nfs4_openowner *oo; | 2493 | struct nfs4_openowner *oo; |
2493 | struct nfs4_client *clp; | 2494 | struct nfs4_client *clp; |
2494 | 2495 | ||
2495 | list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { | 2496 | list_for_each_entry(so, &nn->ownerstr_hashtbl[hashval], so_strhash) { |
2496 | if (!so->so_is_open_owner) | 2497 | if (!so->so_is_open_owner) |
2497 | continue; | 2498 | continue; |
2498 | if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { | 2499 | if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { |
@@ -2648,7 +2649,7 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate, | |||
2648 | return nfserr_jukebox; | 2649 | return nfserr_jukebox; |
2649 | 2650 | ||
2650 | strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); | 2651 | strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); |
2651 | oo = find_openstateowner_str(strhashval, open, cstate->minorversion); | 2652 | oo = find_openstateowner_str(strhashval, open, cstate->minorversion, nn); |
2652 | open->op_openowner = oo; | 2653 | open->op_openowner = oo; |
2653 | if (!oo) { | 2654 | if (!oo) { |
2654 | clp = find_confirmed_client(clientid, cstate->minorversion, | 2655 | clp = find_confirmed_client(clientid, cstate->minorversion, |
@@ -3976,8 +3977,9 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s | |||
3976 | struct inode *inode = open_stp->st_file->fi_inode; | 3977 | struct inode *inode = open_stp->st_file->fi_inode; |
3977 | unsigned int inohash = lockowner_ino_hashval(inode, | 3978 | unsigned int inohash = lockowner_ino_hashval(inode, |
3978 | clp->cl_clientid.cl_id, &lo->lo_owner.so_owner); | 3979 | clp->cl_clientid.cl_id, &lo->lo_owner.so_owner); |
3980 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); | ||
3979 | 3981 | ||
3980 | list_add(&lo->lo_owner.so_strhash, &ownerstr_hashtbl[strhashval]); | 3982 | list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]); |
3981 | list_add(&lo->lo_owner_ino_hash, &lockowner_ino_hashtbl[inohash]); | 3983 | list_add(&lo->lo_owner_ino_hash, &lockowner_ino_hashtbl[inohash]); |
3982 | list_add(&lo->lo_perstateid, &open_stp->st_lockowners); | 3984 | list_add(&lo->lo_perstateid, &open_stp->st_lockowners); |
3983 | } | 3985 | } |
@@ -4458,7 +4460,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
4458 | status = nfserr_locks_held; | 4460 | status = nfserr_locks_held; |
4459 | INIT_LIST_HEAD(&matches); | 4461 | INIT_LIST_HEAD(&matches); |
4460 | 4462 | ||
4461 | list_for_each_entry(sop, &ownerstr_hashtbl[hashval], so_strhash) { | 4463 | list_for_each_entry(sop, &nn->ownerstr_hashtbl[hashval], so_strhash) { |
4462 | if (sop->so_is_open_owner) | 4464 | if (sop->so_is_open_owner) |
4463 | continue; | 4465 | continue; |
4464 | if (!same_owner_str(sop, owner, clid)) | 4466 | if (!same_owner_str(sop, owner, clid)) |
@@ -4614,13 +4616,14 @@ static void release_openowner_sop(struct nfs4_stateowner *sop) | |||
4614 | } | 4616 | } |
4615 | 4617 | ||
4616 | static int nfsd_release_n_owners(u64 num, bool is_open_owner, | 4618 | static int nfsd_release_n_owners(u64 num, bool is_open_owner, |
4617 | void (*release_sop)(struct nfs4_stateowner *)) | 4619 | void (*release_sop)(struct nfs4_stateowner *), |
4620 | struct nfsd_net *nn) | ||
4618 | { | 4621 | { |
4619 | int i, count = 0; | 4622 | int i, count = 0; |
4620 | struct nfs4_stateowner *sop, *next; | 4623 | struct nfs4_stateowner *sop, *next; |
4621 | 4624 | ||
4622 | for (i = 0; i < OWNER_HASH_SIZE; i++) { | 4625 | for (i = 0; i < OWNER_HASH_SIZE; i++) { |
4623 | list_for_each_entry_safe(sop, next, &ownerstr_hashtbl[i], so_strhash) { | 4626 | list_for_each_entry_safe(sop, next, &nn->ownerstr_hashtbl[i], so_strhash) { |
4624 | if (sop->so_is_open_owner != is_open_owner) | 4627 | if (sop->so_is_open_owner != is_open_owner) |
4625 | continue; | 4628 | continue; |
4626 | release_sop(sop); | 4629 | release_sop(sop); |
@@ -4634,9 +4637,10 @@ static int nfsd_release_n_owners(u64 num, bool is_open_owner, | |||
4634 | void nfsd_forget_locks(u64 num) | 4637 | void nfsd_forget_locks(u64 num) |
4635 | { | 4638 | { |
4636 | int count; | 4639 | int count; |
4640 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
4637 | 4641 | ||
4638 | nfs4_lock_state(); | 4642 | nfs4_lock_state(); |
4639 | count = nfsd_release_n_owners(num, false, release_lockowner_sop); | 4643 | count = nfsd_release_n_owners(num, false, release_lockowner_sop, nn); |
4640 | nfs4_unlock_state(); | 4644 | nfs4_unlock_state(); |
4641 | 4645 | ||
4642 | printk(KERN_INFO "NFSD: Forgot %d locks", count); | 4646 | printk(KERN_INFO "NFSD: Forgot %d locks", count); |
@@ -4645,9 +4649,10 @@ void nfsd_forget_locks(u64 num) | |||
4645 | void nfsd_forget_openowners(u64 num) | 4649 | void nfsd_forget_openowners(u64 num) |
4646 | { | 4650 | { |
4647 | int count; | 4651 | int count; |
4652 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
4648 | 4653 | ||
4649 | nfs4_lock_state(); | 4654 | nfs4_lock_state(); |
4650 | count = nfsd_release_n_owners(num, true, release_openowner_sop); | 4655 | count = nfsd_release_n_owners(num, true, release_openowner_sop, nn); |
4651 | nfs4_unlock_state(); | 4656 | nfs4_unlock_state(); |
4652 | 4657 | ||
4653 | printk(KERN_INFO "NFSD: Forgot %d open owners", count); | 4658 | printk(KERN_INFO "NFSD: Forgot %d open owners", count); |
@@ -4721,9 +4726,6 @@ nfs4_state_init(void) | |||
4721 | for (i = 0; i < FILE_HASH_SIZE; i++) { | 4726 | for (i = 0; i < FILE_HASH_SIZE; i++) { |
4722 | INIT_LIST_HEAD(&file_hashtbl[i]); | 4727 | INIT_LIST_HEAD(&file_hashtbl[i]); |
4723 | } | 4728 | } |
4724 | for (i = 0; i < OWNER_HASH_SIZE; i++) { | ||
4725 | INIT_LIST_HEAD(&ownerstr_hashtbl[i]); | ||
4726 | } | ||
4727 | for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++) | 4729 | for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++) |
4728 | INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]); | 4730 | INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]); |
4729 | INIT_LIST_HEAD(&close_lru); | 4731 | INIT_LIST_HEAD(&close_lru); |
@@ -4765,16 +4767,24 @@ static int nfs4_state_start_net(struct net *net) | |||
4765 | CLIENT_HASH_SIZE, GFP_KERNEL); | 4767 | CLIENT_HASH_SIZE, GFP_KERNEL); |
4766 | if (!nn->unconf_id_hashtbl) | 4768 | if (!nn->unconf_id_hashtbl) |
4767 | goto err_unconf_id; | 4769 | goto err_unconf_id; |
4770 | nn->ownerstr_hashtbl = kmalloc(sizeof(struct list_head) * | ||
4771 | OWNER_HASH_SIZE, GFP_KERNEL); | ||
4772 | if (!nn->ownerstr_hashtbl) | ||
4773 | goto err_ownerstr; | ||
4768 | 4774 | ||
4769 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { | 4775 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { |
4770 | INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]); | 4776 | INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]); |
4771 | INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]); | 4777 | INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]); |
4772 | } | 4778 | } |
4779 | for (i = 0; i < OWNER_HASH_SIZE; i++) | ||
4780 | INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]); | ||
4773 | nn->conf_name_tree = RB_ROOT; | 4781 | nn->conf_name_tree = RB_ROOT; |
4774 | nn->unconf_name_tree = RB_ROOT; | 4782 | nn->unconf_name_tree = RB_ROOT; |
4775 | 4783 | ||
4776 | return 0; | 4784 | return 0; |
4777 | 4785 | ||
4786 | err_ownerstr: | ||
4787 | kfree(nn->unconf_id_hashtbl); | ||
4778 | err_unconf_id: | 4788 | err_unconf_id: |
4779 | kfree(nn->conf_id_hashtbl); | 4789 | kfree(nn->conf_id_hashtbl); |
4780 | err: | 4790 | err: |
@@ -4805,6 +4815,7 @@ __nfs4_state_shutdown_net(struct net *net) | |||
4805 | destroy_client(clp); | 4815 | destroy_client(clp); |
4806 | } | 4816 | } |
4807 | 4817 | ||
4818 | kfree(nn->ownerstr_hashtbl); | ||
4808 | kfree(nn->unconf_id_hashtbl); | 4819 | kfree(nn->unconf_id_hashtbl); |
4809 | kfree(nn->conf_id_hashtbl); | 4820 | kfree(nn->conf_id_hashtbl); |
4810 | } | 4821 | } |