aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-11-14 10:21:46 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-11-15 07:40:47 -0500
commit20e9e2bc98b907efe82621797c561f6169d63d96 (patch)
treed3325479970ab864d03df647fe2e1e447563d46a
parent9b5311374057e5c87017ea3756e566047c9b61e7 (diff)
nfsd: make lockowner_ino_hashtbl allocated per net
This hash holds file lock owners 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>
-rw-r--r--fs/nfsd/netns.h4
-rw-r--r--fs/nfsd/nfs4state.c27
2 files changed, 20 insertions, 11 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 46cca9494c7a..2281f6df5573 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -29,6 +29,9 @@
29#define CLIENT_HASH_SIZE (1 << CLIENT_HASH_BITS) 29#define CLIENT_HASH_SIZE (1 << CLIENT_HASH_BITS)
30#define CLIENT_HASH_MASK (CLIENT_HASH_SIZE - 1) 30#define CLIENT_HASH_MASK (CLIENT_HASH_SIZE - 1)
31 31
32#define LOCKOWNER_INO_HASH_BITS 8
33#define LOCKOWNER_INO_HASH_SIZE (1 << LOCKOWNER_INO_HASH_BITS)
34
32struct cld_net; 35struct cld_net;
33 36
34struct nfsd_net { 37struct nfsd_net {
@@ -61,6 +64,7 @@ struct nfsd_net {
61 struct list_head *unconf_id_hashtbl; 64 struct list_head *unconf_id_hashtbl;
62 struct rb_root unconf_name_tree; 65 struct rb_root unconf_name_tree;
63 struct list_head *ownerstr_hashtbl; 66 struct list_head *ownerstr_hashtbl;
67 struct list_head *lockowner_ino_hashtbl;
64}; 68};
65 69
66extern int nfsd_net_id; 70extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f68514d8210e..1e76d55a3e9a 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3862,8 +3862,6 @@ out:
3862 3862
3863#define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start)) 3863#define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start))
3864 3864
3865#define LOCKOWNER_INO_HASH_BITS 8
3866#define LOCKOWNER_INO_HASH_SIZE (1 << LOCKOWNER_INO_HASH_BITS)
3867#define LOCKOWNER_INO_HASH_MASK (LOCKOWNER_INO_HASH_SIZE - 1) 3865#define LOCKOWNER_INO_HASH_MASK (LOCKOWNER_INO_HASH_SIZE - 1)
3868 3866
3869static inline u64 3867static inline u64
@@ -3893,8 +3891,6 @@ static unsigned int lockowner_ino_hashval(struct inode *inode, u32 cl_id, struct
3893 & LOCKOWNER_INO_HASH_MASK; 3891 & LOCKOWNER_INO_HASH_MASK;
3894} 3892}
3895 3893
3896static struct list_head lockowner_ino_hashtbl[LOCKOWNER_INO_HASH_SIZE];
3897
3898/* 3894/*
3899 * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that 3895 * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
3900 * we can't properly handle lock requests that go beyond the (2^63 - 1)-th 3896 * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
@@ -3960,12 +3956,12 @@ static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, c
3960 3956
3961static struct nfs4_lockowner * 3957static struct nfs4_lockowner *
3962find_lockowner_str(struct inode *inode, clientid_t *clid, 3958find_lockowner_str(struct inode *inode, clientid_t *clid,
3963 struct xdr_netobj *owner) 3959 struct xdr_netobj *owner, struct nfsd_net *nn)
3964{ 3960{
3965 unsigned int hashval = lockowner_ino_hashval(inode, clid->cl_id, owner); 3961 unsigned int hashval = lockowner_ino_hashval(inode, clid->cl_id, owner);
3966 struct nfs4_lockowner *lo; 3962 struct nfs4_lockowner *lo;
3967 3963
3968 list_for_each_entry(lo, &lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) { 3964 list_for_each_entry(lo, &nn->lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) {
3969 if (same_lockowner_ino(lo, inode, clid, owner)) 3965 if (same_lockowner_ino(lo, inode, clid, owner))
3970 return lo; 3966 return lo;
3971 } 3967 }
@@ -3980,7 +3976,7 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s
3980 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 3976 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
3981 3977
3982 list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]); 3978 list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
3983 list_add(&lo->lo_owner_ino_hash, &lockowner_ino_hashtbl[inohash]); 3979 list_add(&lo->lo_owner_ino_hash, &nn->lockowner_ino_hashtbl[inohash]);
3984 list_add(&lo->lo_perstateid, &open_stp->st_lockowners); 3980 list_add(&lo->lo_perstateid, &open_stp->st_lockowners);
3985} 3981}
3986 3982
@@ -4054,8 +4050,10 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s
4054 struct nfs4_client *cl = oo->oo_owner.so_client; 4050 struct nfs4_client *cl = oo->oo_owner.so_client;
4055 struct nfs4_lockowner *lo; 4051 struct nfs4_lockowner *lo;
4056 unsigned int strhashval; 4052 unsigned int strhashval;
4053 struct nfsd_net *nn = net_generic(cl->net, nfsd_net_id);
4057 4054
4058 lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid, &lock->v.new.owner); 4055 lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid,
4056 &lock->v.new.owner, nn);
4059 if (lo) { 4057 if (lo) {
4060 if (!cstate->minorversion) 4058 if (!cstate->minorversion)
4061 return nfserr_bad_seqid; 4059 return nfserr_bad_seqid;
@@ -4308,7 +4306,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4308 goto out; 4306 goto out;
4309 } 4307 }
4310 4308
4311 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner); 4309 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner, nn);
4312 if (lo) 4310 if (lo)
4313 file_lock->fl_owner = (fl_owner_t)lo; 4311 file_lock->fl_owner = (fl_owner_t)lo;
4314 file_lock->fl_pid = current->tgid; 4312 file_lock->fl_pid = current->tgid;
@@ -4726,8 +4724,6 @@ nfs4_state_init(void)
4726 for (i = 0; i < FILE_HASH_SIZE; i++) { 4724 for (i = 0; i < FILE_HASH_SIZE; i++) {
4727 INIT_LIST_HEAD(&file_hashtbl[i]); 4725 INIT_LIST_HEAD(&file_hashtbl[i]);
4728 } 4726 }
4729 for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
4730 INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]);
4731 INIT_LIST_HEAD(&close_lru); 4727 INIT_LIST_HEAD(&close_lru);
4732 INIT_LIST_HEAD(&client_lru); 4728 INIT_LIST_HEAD(&client_lru);
4733 INIT_LIST_HEAD(&del_recall_lru); 4729 INIT_LIST_HEAD(&del_recall_lru);
@@ -4771,6 +4767,10 @@ static int nfs4_state_start_net(struct net *net)
4771 OWNER_HASH_SIZE, GFP_KERNEL); 4767 OWNER_HASH_SIZE, GFP_KERNEL);
4772 if (!nn->ownerstr_hashtbl) 4768 if (!nn->ownerstr_hashtbl)
4773 goto err_ownerstr; 4769 goto err_ownerstr;
4770 nn->lockowner_ino_hashtbl = kmalloc(sizeof(struct list_head) *
4771 LOCKOWNER_INO_HASH_SIZE, GFP_KERNEL);
4772 if (!nn->lockowner_ino_hashtbl)
4773 goto err_lockowner_ino;
4774 4774
4775 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 4775 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
4776 INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]); 4776 INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
@@ -4778,11 +4778,15 @@ static int nfs4_state_start_net(struct net *net)
4778 } 4778 }
4779 for (i = 0; i < OWNER_HASH_SIZE; i++) 4779 for (i = 0; i < OWNER_HASH_SIZE; i++)
4780 INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]); 4780 INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]);
4781 for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
4782 INIT_LIST_HEAD(&nn->lockowner_ino_hashtbl[i]);
4781 nn->conf_name_tree = RB_ROOT; 4783 nn->conf_name_tree = RB_ROOT;
4782 nn->unconf_name_tree = RB_ROOT; 4784 nn->unconf_name_tree = RB_ROOT;
4783 4785
4784 return 0; 4786 return 0;
4785 4787
4788err_lockowner_ino:
4789 kfree(nn->ownerstr_hashtbl);
4786err_ownerstr: 4790err_ownerstr:
4787 kfree(nn->unconf_id_hashtbl); 4791 kfree(nn->unconf_id_hashtbl);
4788err_unconf_id: 4792err_unconf_id:
@@ -4815,6 +4819,7 @@ __nfs4_state_shutdown_net(struct net *net)
4815 destroy_client(clp); 4819 destroy_client(clp);
4816 } 4820 }
4817 4821
4822 kfree(nn->lockowner_ino_hashtbl);
4818 kfree(nn->ownerstr_hashtbl); 4823 kfree(nn->ownerstr_hashtbl);
4819 kfree(nn->unconf_id_hashtbl); 4824 kfree(nn->unconf_id_hashtbl);
4820 kfree(nn->conf_id_hashtbl); 4825 kfree(nn->conf_id_hashtbl);