aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-11-14 10:21:41 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-11-15 07:40:46 -0500
commit9b5311374057e5c87017ea3756e566047c9b61e7 (patch)
tree3cde40f55baf51b9cc29ac60a8a28bff3d94a7ef /fs/nfsd/nfs4state.c
parenta99454aa4ff1241a19dcb486fa302d3e8cc09e5b (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/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b35329199e3..f68514d8210 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
179static 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
2429static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) 2427static 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
2488static struct nfs4_openowner * 2488static struct nfs4_openowner *
2489find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions) 2489find_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
4616static int nfsd_release_n_owners(u64 num, bool is_open_owner, 4618static 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,
4634void nfsd_forget_locks(u64 num) 4637void 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)
4645void nfsd_forget_openowners(u64 num) 4649void 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
4786err_ownerstr:
4787 kfree(nn->unconf_id_hashtbl);
4778err_unconf_id: 4788err_unconf_id:
4779 kfree(nn->conf_id_hashtbl); 4789 kfree(nn->conf_id_hashtbl);
4780err: 4790err:
@@ -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}