aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/export.c')
-rw-r--r--fs/nfsd/export.c136
1 files changed, 99 insertions, 37 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 2ebd77d758bc..abd68965822f 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -57,17 +57,6 @@ static int exp_verify_string(char *cp, int max);
57#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) 57#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
58static struct cache_head *expkey_table[EXPKEY_HASHMAX]; 58static struct cache_head *expkey_table[EXPKEY_HASHMAX];
59 59
60static inline int svc_expkey_hash(struct svc_expkey *item)
61{
62 int hash = item->ek_fsidtype;
63 char * cp = (char*)item->ek_fsid;
64 int len = key_len(item->ek_fsidtype);
65
66 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
67 hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
68 return hash & EXPKEY_HASHMASK;
69}
70
71void expkey_put(struct cache_head *item, struct cache_detail *cd) 60void expkey_put(struct cache_head *item, struct cache_detail *cd)
72{ 61{
73 if (cache_put(item, cd)) { 62 if (cache_put(item, cd)) {
@@ -97,7 +86,8 @@ static void expkey_request(struct cache_detail *cd,
97 (*bpp)[-1] = '\n'; 86 (*bpp)[-1] = '\n';
98} 87}
99 88
100static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int); 89static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old);
90static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *);
101static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) 91static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
102{ 92{
103 /* client fsidtype fsid [path] */ 93 /* client fsidtype fsid [path] */
@@ -108,6 +98,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
108 int fsidtype; 98 int fsidtype;
109 char *ep; 99 char *ep;
110 struct svc_expkey key; 100 struct svc_expkey key;
101 struct svc_expkey *ek;
111 102
112 if (mesg[mlen-1] != '\n') 103 if (mesg[mlen-1] != '\n')
113 return -EINVAL; 104 return -EINVAL;
@@ -152,20 +143,25 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
152 key.ek_fsidtype = fsidtype; 143 key.ek_fsidtype = fsidtype;
153 memcpy(key.ek_fsid, buf, len); 144 memcpy(key.ek_fsid, buf, len);
154 145
146 ek = svc_expkey_lookup(&key);
147 err = -ENOMEM;
148 if (!ek)
149 goto out;
150
155 /* now we want a pathname, or empty meaning NEGATIVE */ 151 /* now we want a pathname, or empty meaning NEGATIVE */
152 err = -EINVAL;
156 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) 153 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
157 goto out; 154 goto out;
158 dprintk("Path seems to be <%s>\n", buf); 155 dprintk("Path seems to be <%s>\n", buf);
159 err = 0; 156 err = 0;
160 if (len == 0) { 157 if (len == 0) {
161 struct svc_expkey *ek;
162 set_bit(CACHE_NEGATIVE, &key.h.flags); 158 set_bit(CACHE_NEGATIVE, &key.h.flags);
163 ek = svc_expkey_lookup(&key, 1); 159 ek = svc_expkey_update(&key, ek);
164 if (ek) 160 if (ek)
165 expkey_put(&ek->h, &svc_expkey_cache); 161 expkey_put(&ek->h, &svc_expkey_cache);
162 else err = -ENOMEM;
166 } else { 163 } else {
167 struct nameidata nd; 164 struct nameidata nd;
168 struct svc_expkey *ek;
169 err = path_lookup(buf, 0, &nd); 165 err = path_lookup(buf, 0, &nd);
170 if (err) 166 if (err)
171 goto out; 167 goto out;
@@ -174,10 +170,11 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
174 key.ek_mnt = nd.mnt; 170 key.ek_mnt = nd.mnt;
175 key.ek_dentry = nd.dentry; 171 key.ek_dentry = nd.dentry;
176 172
177 ek = svc_expkey_lookup(&key, 1); 173 ek = svc_expkey_update(&key, ek);
178 if (ek) 174 if (ek)
179 expkey_put(&ek->h, &svc_expkey_cache); 175 expkey_put(&ek->h, &svc_expkey_cache);
180 err = 0; 176 else
177 err = -ENOMEM;
181 path_release(&nd); 178 path_release(&nd);
182 } 179 }
183 cache_flush(); 180 cache_flush();
@@ -213,29 +210,25 @@ static int expkey_show(struct seq_file *m,
213 seq_printf(m, "\n"); 210 seq_printf(m, "\n");
214 return 0; 211 return 0;
215} 212}
216
217struct cache_detail svc_expkey_cache = {
218 .owner = THIS_MODULE,
219 .hash_size = EXPKEY_HASHMAX,
220 .hash_table = expkey_table,
221 .name = "nfsd.fh",
222 .cache_put = expkey_put,
223 .cache_request = expkey_request,
224 .cache_parse = expkey_parse,
225 .cache_show = expkey_show,
226};
227 213
228static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b) 214static inline int expkey_match (struct cache_head *a, struct cache_head *b)
229{ 215{
230 if (a->ek_fsidtype != b->ek_fsidtype || 216 struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
231 a->ek_client != b->ek_client || 217 struct svc_expkey *new = container_of(b, struct svc_expkey, h);
232 memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0) 218
219 if (orig->ek_fsidtype != new->ek_fsidtype ||
220 orig->ek_client != new->ek_client ||
221 memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0)
233 return 0; 222 return 0;
234 return 1; 223 return 1;
235} 224}
236 225
237static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item) 226static inline void expkey_init(struct cache_head *cnew,
227 struct cache_head *citem)
238{ 228{
229 struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
230 struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
231
239 kref_get(&item->ek_client->ref); 232 kref_get(&item->ek_client->ref);
240 new->ek_client = item->ek_client; 233 new->ek_client = item->ek_client;
241 new->ek_fsidtype = item->ek_fsidtype; 234 new->ek_fsidtype = item->ek_fsidtype;
@@ -244,13 +237,80 @@ static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *it
244 new->ek_fsid[2] = item->ek_fsid[2]; 237 new->ek_fsid[2] = item->ek_fsid[2];
245} 238}
246 239
247static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item) 240static inline void expkey_update(struct cache_head *cnew,
241 struct cache_head *citem)
248{ 242{
243 struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
244 struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
245
249 new->ek_mnt = mntget(item->ek_mnt); 246 new->ek_mnt = mntget(item->ek_mnt);
250 new->ek_dentry = dget(item->ek_dentry); 247 new->ek_dentry = dget(item->ek_dentry);
251} 248}
252 249
253static DefineSimpleCacheLookup(svc_expkey, svc_expkey) 250static struct cache_head *expkey_alloc(void)
251{
252 struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
253 if (i)
254 return &i->h;
255 else
256 return NULL;
257}
258
259struct cache_detail svc_expkey_cache = {
260 .owner = THIS_MODULE,
261 .hash_size = EXPKEY_HASHMAX,
262 .hash_table = expkey_table,
263 .name = "nfsd.fh",
264 .cache_put = expkey_put,
265 .cache_request = expkey_request,
266 .cache_parse = expkey_parse,
267 .cache_show = expkey_show,
268 .match = expkey_match,
269 .init = expkey_init,
270 .update = expkey_update,
271 .alloc = expkey_alloc,
272};
273
274static struct svc_expkey *
275svc_expkey_lookup(struct svc_expkey *item)
276{
277 struct cache_head *ch;
278 int hash = item->ek_fsidtype;
279 char * cp = (char*)item->ek_fsid;
280 int len = key_len(item->ek_fsidtype);
281
282 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
283 hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
284 hash &= EXPKEY_HASHMASK;
285
286 ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h,
287 hash);
288 if (ch)
289 return container_of(ch, struct svc_expkey, h);
290 else
291 return NULL;
292}
293
294static struct svc_expkey *
295svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
296{
297 struct cache_head *ch;
298 int hash = new->ek_fsidtype;
299 char * cp = (char*)new->ek_fsid;
300 int len = key_len(new->ek_fsidtype);
301
302 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
303 hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS);
304 hash &= EXPKEY_HASHMASK;
305
306 ch = sunrpc_cache_update(&svc_expkey_cache, &new->h,
307 &old->h, hash);
308 if (ch)
309 return container_of(ch, struct svc_expkey, h);
310 else
311 return NULL;
312}
313
254 314
255#define EXPORT_HASHBITS 8 315#define EXPORT_HASHBITS 8
256#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) 316#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
@@ -549,7 +609,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
549 key.ek_fsidtype = fsid_type; 609 key.ek_fsidtype = fsid_type;
550 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 610 memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
551 611
552 ek = svc_expkey_lookup(&key, 0); 612 ek = svc_expkey_lookup(&key);
553 if (ek != NULL) 613 if (ek != NULL)
554 if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) 614 if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
555 ek = ERR_PTR(err); 615 ek = ERR_PTR(err);
@@ -569,7 +629,9 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
569 key.h.expiry_time = NEVER; 629 key.h.expiry_time = NEVER;
570 key.h.flags = 0; 630 key.h.flags = 0;
571 631
572 ek = svc_expkey_lookup(&key, 1); 632 ek = svc_expkey_lookup(&key);
633 if (ek)
634 ek = svc_expkey_update(&key,ek);
573 if (ek) { 635 if (ek) {
574 expkey_put(&ek->h, &svc_expkey_cache); 636 expkey_put(&ek->h, &svc_expkey_cache);
575 return 0; 637 return 0;