Skip to content

Commit 43d1d00

Browse files
chuckleversmb49
authored andcommitted
NFSD: Set up an rhashtable for the filecache
BugLink: https://bugs.launchpad.net/bugs/2065435 [ Upstream commit fc22945 ] Add code to initialize and tear down an rhashtable. The rhashtable is not used yet. Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Manuel Diewald <[email protected]> Signed-off-by: Roxana Nicolescu <[email protected]>
1 parent a37f08b commit 43d1d00

File tree

2 files changed

+140
-21
lines changed

2 files changed

+140
-21
lines changed

fs/nfsd/filecache.c

Lines changed: 139 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/fsnotify_backend.h>
1313
#include <linux/fsnotify.h>
1414
#include <linux/seq_file.h>
15+
#include <linux/rhashtable.h>
1516

1617
#include "vfs.h"
1718
#include "nfsd.h"
@@ -62,6 +63,136 @@ static unsigned long nfsd_file_flags;
6263
static struct fsnotify_group *nfsd_file_fsnotify_group;
6364
static atomic_long_t nfsd_filecache_count;
6465
static struct delayed_work nfsd_filecache_laundrette;
66+
static struct rhashtable nfsd_file_rhash_tbl
67+
____cacheline_aligned_in_smp;
68+
69+
enum nfsd_file_lookup_type {
70+
NFSD_FILE_KEY_INODE,
71+
NFSD_FILE_KEY_FULL,
72+
};
73+
74+
struct nfsd_file_lookup_key {
75+
struct inode *inode;
76+
struct net *net;
77+
const struct cred *cred;
78+
unsigned char need;
79+
enum nfsd_file_lookup_type type;
80+
};
81+
82+
/*
83+
* The returned hash value is based solely on the address of an in-code
84+
* inode, a pointer to a slab-allocated object. The entropy in such a
85+
* pointer is concentrated in its middle bits.
86+
*/
87+
static u32 nfsd_file_inode_hash(const struct inode *inode, u32 seed)
88+
{
89+
unsigned long ptr = (unsigned long)inode;
90+
u32 k;
91+
92+
k = ptr >> L1_CACHE_SHIFT;
93+
k &= 0x00ffffff;
94+
return jhash2(&k, 1, seed);
95+
}
96+
97+
/**
98+
* nfsd_file_key_hashfn - Compute the hash value of a lookup key
99+
* @data: key on which to compute the hash value
100+
* @len: rhash table's key_len parameter (unused)
101+
* @seed: rhash table's random seed of the day
102+
*
103+
* Return value:
104+
* Computed 32-bit hash value
105+
*/
106+
static u32 nfsd_file_key_hashfn(const void *data, u32 len, u32 seed)
107+
{
108+
const struct nfsd_file_lookup_key *key = data;
109+
110+
return nfsd_file_inode_hash(key->inode, seed);
111+
}
112+
113+
/**
114+
* nfsd_file_obj_hashfn - Compute the hash value of an nfsd_file
115+
* @data: object on which to compute the hash value
116+
* @len: rhash table's key_len parameter (unused)
117+
* @seed: rhash table's random seed of the day
118+
*
119+
* Return value:
120+
* Computed 32-bit hash value
121+
*/
122+
static u32 nfsd_file_obj_hashfn(const void *data, u32 len, u32 seed)
123+
{
124+
const struct nfsd_file *nf = data;
125+
126+
return nfsd_file_inode_hash(nf->nf_inode, seed);
127+
}
128+
129+
static bool
130+
nfsd_match_cred(const struct cred *c1, const struct cred *c2)
131+
{
132+
int i;
133+
134+
if (!uid_eq(c1->fsuid, c2->fsuid))
135+
return false;
136+
if (!gid_eq(c1->fsgid, c2->fsgid))
137+
return false;
138+
if (c1->group_info == NULL || c2->group_info == NULL)
139+
return c1->group_info == c2->group_info;
140+
if (c1->group_info->ngroups != c2->group_info->ngroups)
141+
return false;
142+
for (i = 0; i < c1->group_info->ngroups; i++) {
143+
if (!gid_eq(c1->group_info->gid[i], c2->group_info->gid[i]))
144+
return false;
145+
}
146+
return true;
147+
}
148+
149+
/**
150+
* nfsd_file_obj_cmpfn - Match a cache item against search criteria
151+
* @arg: search criteria
152+
* @ptr: cache item to check
153+
*
154+
* Return values:
155+
* %0 - Item matches search criteria
156+
* %1 - Item does not match search criteria
157+
*/
158+
static int nfsd_file_obj_cmpfn(struct rhashtable_compare_arg *arg,
159+
const void *ptr)
160+
{
161+
const struct nfsd_file_lookup_key *key = arg->key;
162+
const struct nfsd_file *nf = ptr;
163+
164+
switch (key->type) {
165+
case NFSD_FILE_KEY_INODE:
166+
if (nf->nf_inode != key->inode)
167+
return 1;
168+
break;
169+
case NFSD_FILE_KEY_FULL:
170+
if (nf->nf_inode != key->inode)
171+
return 1;
172+
if (nf->nf_may != key->need)
173+
return 1;
174+
if (nf->nf_net != key->net)
175+
return 1;
176+
if (!nfsd_match_cred(nf->nf_cred, key->cred))
177+
return 1;
178+
if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags) == 0)
179+
return 1;
180+
break;
181+
}
182+
return 0;
183+
}
184+
185+
static const struct rhashtable_params nfsd_file_rhash_params = {
186+
.key_len = sizeof_field(struct nfsd_file, nf_inode),
187+
.key_offset = offsetof(struct nfsd_file, nf_inode),
188+
.head_offset = offsetof(struct nfsd_file, nf_rhash),
189+
.hashfn = nfsd_file_key_hashfn,
190+
.obj_hashfn = nfsd_file_obj_hashfn,
191+
.obj_cmpfn = nfsd_file_obj_cmpfn,
192+
/* Reduce resizing churn on light workloads */
193+
.min_size = 512, /* buckets */
194+
.automatic_shrinking = true,
195+
};
65196

66197
static void
67198
nfsd_file_schedule_laundrette(void)
@@ -693,13 +824,18 @@ static const struct fsnotify_ops nfsd_file_fsnotify_ops = {
693824
int
694825
nfsd_file_cache_init(void)
695826
{
696-
int ret = -ENOMEM;
827+
int ret;
697828
unsigned int i;
698829

699830
lockdep_assert_held(&nfsd_mutex);
700831
if (test_and_set_bit(NFSD_FILE_CACHE_UP, &nfsd_file_flags) == 1)
701832
return 0;
702833

834+
ret = rhashtable_init(&nfsd_file_rhash_tbl, &nfsd_file_rhash_params);
835+
if (ret)
836+
return ret;
837+
838+
ret = -ENOMEM;
703839
nfsd_filecache_wq = alloc_workqueue("nfsd_filecache", 0, 0);
704840
if (!nfsd_filecache_wq)
705841
goto out;
@@ -777,6 +913,7 @@ nfsd_file_cache_init(void)
777913
nfsd_file_hashtbl = NULL;
778914
destroy_workqueue(nfsd_filecache_wq);
779915
nfsd_filecache_wq = NULL;
916+
rhashtable_destroy(&nfsd_file_rhash_tbl);
780917
goto out;
781918
}
782919

@@ -902,6 +1039,7 @@ nfsd_file_cache_shutdown(void)
9021039
nfsd_file_hashtbl = NULL;
9031040
destroy_workqueue(nfsd_filecache_wq);
9041041
nfsd_filecache_wq = NULL;
1042+
rhashtable_destroy(&nfsd_file_rhash_tbl);
9051043

9061044
for_each_possible_cpu(i) {
9071045
per_cpu(nfsd_file_cache_hits, i) = 0;
@@ -913,26 +1051,6 @@ nfsd_file_cache_shutdown(void)
9131051
}
9141052
}
9151053

916-
static bool
917-
nfsd_match_cred(const struct cred *c1, const struct cred *c2)
918-
{
919-
int i;
920-
921-
if (!uid_eq(c1->fsuid, c2->fsuid))
922-
return false;
923-
if (!gid_eq(c1->fsgid, c2->fsgid))
924-
return false;
925-
if (c1->group_info == NULL || c2->group_info == NULL)
926-
return c1->group_info == c2->group_info;
927-
if (c1->group_info->ngroups != c2->group_info->ngroups)
928-
return false;
929-
for (i = 0; i < c1->group_info->ngroups; i++) {
930-
if (!gid_eq(c1->group_info->gid[i], c2->group_info->gid[i]))
931-
return false;
932-
}
933-
return true;
934-
}
935-
9361054
static struct nfsd_file *
9371055
nfsd_file_find_locked(struct inode *inode, unsigned int may_flags,
9381056
unsigned int hashval, struct net *net)

fs/nfsd/filecache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct nfsd_file_mark {
2929
* never be dereferenced, only used for comparison.
3030
*/
3131
struct nfsd_file {
32+
struct rhash_head nf_rhash;
3233
struct hlist_node nf_node;
3334
struct list_head nf_lru;
3435
struct rcu_head nf_rcu;

0 commit comments

Comments
 (0)