diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-11-14 10:21:46 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-11-15 07:40:47 -0500 |
commit | 20e9e2bc98b907efe82621797c561f6169d63d96 (patch) | |
tree | d3325479970ab864d03df647fe2e1e447563d46a | |
parent | 9b5311374057e5c87017ea3756e566047c9b61e7 (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.h | 4 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 27 |
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 | |||
32 | struct cld_net; | 35 | struct cld_net; |
33 | 36 | ||
34 | struct nfsd_net { | 37 | struct 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 | ||
66 | extern int nfsd_net_id; | 70 | extern 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 | ||
3869 | static inline u64 | 3867 | static 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 | ||
3896 | static 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 | ||
3961 | static struct nfs4_lockowner * | 3957 | static struct nfs4_lockowner * |
3962 | find_lockowner_str(struct inode *inode, clientid_t *clid, | 3958 | find_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 | ||
4788 | err_lockowner_ino: | ||
4789 | kfree(nn->ownerstr_hashtbl); | ||
4786 | err_ownerstr: | 4790 | err_ownerstr: |
4787 | kfree(nn->unconf_id_hashtbl); | 4791 | kfree(nn->unconf_id_hashtbl); |
4788 | err_unconf_id: | 4792 | err_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); |