diff options
Diffstat (limited to 'fs/nfsd/nfs4idmap.c')
-rw-r--r-- | fs/nfsd/nfs4idmap.c | 146 |
1 files changed, 109 insertions, 37 deletions
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 13369650cdf9..4b6aa60dfceb 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
@@ -76,21 +76,18 @@ struct ent { | |||
76 | char authname[IDMAP_NAMESZ]; | 76 | char authname[IDMAP_NAMESZ]; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | #define DefineSimpleCacheLookupMap(STRUCT, FUNC) \ | ||
80 | DefineCacheLookup(struct STRUCT, h, FUNC##_lookup, \ | ||
81 | (struct STRUCT *item, int set), /*no setup */, \ | ||
82 | & FUNC##_cache, FUNC##_hash(item), FUNC##_match(item, tmp), \ | ||
83 | STRUCT##_init(new, item), STRUCT##_update(tmp, item), 0) | ||
84 | |||
85 | /* Common entry handling */ | 79 | /* Common entry handling */ |
86 | 80 | ||
87 | #define ENT_HASHBITS 8 | 81 | #define ENT_HASHBITS 8 |
88 | #define ENT_HASHMAX (1 << ENT_HASHBITS) | 82 | #define ENT_HASHMAX (1 << ENT_HASHBITS) |
89 | #define ENT_HASHMASK (ENT_HASHMAX - 1) | 83 | #define ENT_HASHMASK (ENT_HASHMAX - 1) |
90 | 84 | ||
91 | static inline void | 85 | static void |
92 | ent_init(struct ent *new, struct ent *itm) | 86 | ent_init(struct cache_head *cnew, struct cache_head *citm) |
93 | { | 87 | { |
88 | struct ent *new = container_of(cnew, struct ent, h); | ||
89 | struct ent *itm = container_of(citm, struct ent, h); | ||
90 | |||
94 | new->id = itm->id; | 91 | new->id = itm->id; |
95 | new->type = itm->type; | 92 | new->type = itm->type; |
96 | 93 | ||
@@ -98,19 +95,21 @@ ent_init(struct ent *new, struct ent *itm) | |||
98 | strlcpy(new->authname, itm->authname, sizeof(new->name)); | 95 | strlcpy(new->authname, itm->authname, sizeof(new->name)); |
99 | } | 96 | } |
100 | 97 | ||
101 | static inline void | 98 | static void |
102 | ent_update(struct ent *new, struct ent *itm) | 99 | ent_put(struct kref *ref) |
103 | { | 100 | { |
104 | ent_init(new, itm); | 101 | struct ent *map = container_of(ref, struct ent, h.ref); |
102 | kfree(map); | ||
105 | } | 103 | } |
106 | 104 | ||
107 | static void | 105 | static struct cache_head * |
108 | ent_put(struct cache_head *ch, struct cache_detail *cd) | 106 | ent_alloc(void) |
109 | { | 107 | { |
110 | if (cache_put(ch, cd)) { | 108 | struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL); |
111 | struct ent *map = container_of(ch, struct ent, h); | 109 | if (e) |
112 | kfree(map); | 110 | return &e->h; |
113 | } | 111 | else |
112 | return NULL; | ||
114 | } | 113 | } |
115 | 114 | ||
116 | /* | 115 | /* |
@@ -149,9 +148,12 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, | |||
149 | (*bpp)[-1] = '\n'; | 148 | (*bpp)[-1] = '\n'; |
150 | } | 149 | } |
151 | 150 | ||
152 | static inline int | 151 | static int |
153 | idtoname_match(struct ent *a, struct ent *b) | 152 | idtoname_match(struct cache_head *ca, struct cache_head *cb) |
154 | { | 153 | { |
154 | struct ent *a = container_of(ca, struct ent, h); | ||
155 | struct ent *b = container_of(cb, struct ent, h); | ||
156 | |||
155 | return (a->id == b->id && a->type == b->type && | 157 | return (a->id == b->id && a->type == b->type && |
156 | strcmp(a->authname, b->authname) == 0); | 158 | strcmp(a->authname, b->authname) == 0); |
157 | } | 159 | } |
@@ -184,7 +186,8 @@ warn_no_idmapd(struct cache_detail *detail) | |||
184 | 186 | ||
185 | 187 | ||
186 | static int idtoname_parse(struct cache_detail *, char *, int); | 188 | static int idtoname_parse(struct cache_detail *, char *, int); |
187 | static struct ent *idtoname_lookup(struct ent *, int); | 189 | static struct ent *idtoname_lookup(struct ent *); |
190 | static struct ent *idtoname_update(struct ent *, struct ent *); | ||
188 | 191 | ||
189 | static struct cache_detail idtoname_cache = { | 192 | static struct cache_detail idtoname_cache = { |
190 | .owner = THIS_MODULE, | 193 | .owner = THIS_MODULE, |
@@ -196,6 +199,10 @@ static struct cache_detail idtoname_cache = { | |||
196 | .cache_parse = idtoname_parse, | 199 | .cache_parse = idtoname_parse, |
197 | .cache_show = idtoname_show, | 200 | .cache_show = idtoname_show, |
198 | .warn_no_listener = warn_no_idmapd, | 201 | .warn_no_listener = warn_no_idmapd, |
202 | .match = idtoname_match, | ||
203 | .init = ent_init, | ||
204 | .update = ent_init, | ||
205 | .alloc = ent_alloc, | ||
199 | }; | 206 | }; |
200 | 207 | ||
201 | int | 208 | int |
@@ -238,6 +245,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
238 | if (ent.h.expiry_time == 0) | 245 | if (ent.h.expiry_time == 0) |
239 | goto out; | 246 | goto out; |
240 | 247 | ||
248 | error = -ENOMEM; | ||
249 | res = idtoname_lookup(&ent); | ||
250 | if (!res) | ||
251 | goto out; | ||
252 | |||
241 | /* Name */ | 253 | /* Name */ |
242 | error = qword_get(&buf, buf1, PAGE_SIZE); | 254 | error = qword_get(&buf, buf1, PAGE_SIZE); |
243 | if (error == -EINVAL) | 255 | if (error == -EINVAL) |
@@ -252,10 +264,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
252 | memcpy(ent.name, buf1, sizeof(ent.name)); | 264 | memcpy(ent.name, buf1, sizeof(ent.name)); |
253 | } | 265 | } |
254 | error = -ENOMEM; | 266 | error = -ENOMEM; |
255 | if ((res = idtoname_lookup(&ent, 1)) == NULL) | 267 | res = idtoname_update(&ent, res); |
268 | if (res == NULL) | ||
256 | goto out; | 269 | goto out; |
257 | 270 | ||
258 | ent_put(&res->h, &idtoname_cache); | 271 | cache_put(&res->h, &idtoname_cache); |
259 | 272 | ||
260 | error = 0; | 273 | error = 0; |
261 | out: | 274 | out: |
@@ -264,7 +277,31 @@ out: | |||
264 | return error; | 277 | return error; |
265 | } | 278 | } |
266 | 279 | ||
267 | static DefineSimpleCacheLookupMap(ent, idtoname); | 280 | |
281 | static struct ent * | ||
282 | idtoname_lookup(struct ent *item) | ||
283 | { | ||
284 | struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache, | ||
285 | &item->h, | ||
286 | idtoname_hash(item)); | ||
287 | if (ch) | ||
288 | return container_of(ch, struct ent, h); | ||
289 | else | ||
290 | return NULL; | ||
291 | } | ||
292 | |||
293 | static struct ent * | ||
294 | idtoname_update(struct ent *new, struct ent *old) | ||
295 | { | ||
296 | struct cache_head *ch = sunrpc_cache_update(&idtoname_cache, | ||
297 | &new->h, &old->h, | ||
298 | idtoname_hash(new)); | ||
299 | if (ch) | ||
300 | return container_of(ch, struct ent, h); | ||
301 | else | ||
302 | return NULL; | ||
303 | } | ||
304 | |||
268 | 305 | ||
269 | /* | 306 | /* |
270 | * Name -> ID cache | 307 | * Name -> ID cache |
@@ -291,9 +328,12 @@ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, | |||
291 | (*bpp)[-1] = '\n'; | 328 | (*bpp)[-1] = '\n'; |
292 | } | 329 | } |
293 | 330 | ||
294 | static inline int | 331 | static int |
295 | nametoid_match(struct ent *a, struct ent *b) | 332 | nametoid_match(struct cache_head *ca, struct cache_head *cb) |
296 | { | 333 | { |
334 | struct ent *a = container_of(ca, struct ent, h); | ||
335 | struct ent *b = container_of(cb, struct ent, h); | ||
336 | |||
297 | return (a->type == b->type && strcmp(a->name, b->name) == 0 && | 337 | return (a->type == b->type && strcmp(a->name, b->name) == 0 && |
298 | strcmp(a->authname, b->authname) == 0); | 338 | strcmp(a->authname, b->authname) == 0); |
299 | } | 339 | } |
@@ -317,7 +357,8 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) | |||
317 | return 0; | 357 | return 0; |
318 | } | 358 | } |
319 | 359 | ||
320 | static struct ent *nametoid_lookup(struct ent *, int); | 360 | static struct ent *nametoid_lookup(struct ent *); |
361 | static struct ent *nametoid_update(struct ent *, struct ent *); | ||
321 | static int nametoid_parse(struct cache_detail *, char *, int); | 362 | static int nametoid_parse(struct cache_detail *, char *, int); |
322 | 363 | ||
323 | static struct cache_detail nametoid_cache = { | 364 | static struct cache_detail nametoid_cache = { |
@@ -330,6 +371,10 @@ static struct cache_detail nametoid_cache = { | |||
330 | .cache_parse = nametoid_parse, | 371 | .cache_parse = nametoid_parse, |
331 | .cache_show = nametoid_show, | 372 | .cache_show = nametoid_show, |
332 | .warn_no_listener = warn_no_idmapd, | 373 | .warn_no_listener = warn_no_idmapd, |
374 | .match = nametoid_match, | ||
375 | .init = ent_init, | ||
376 | .update = ent_init, | ||
377 | .alloc = ent_alloc, | ||
333 | }; | 378 | }; |
334 | 379 | ||
335 | static int | 380 | static int |
@@ -379,10 +424,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen) | |||
379 | set_bit(CACHE_NEGATIVE, &ent.h.flags); | 424 | set_bit(CACHE_NEGATIVE, &ent.h.flags); |
380 | 425 | ||
381 | error = -ENOMEM; | 426 | error = -ENOMEM; |
382 | if ((res = nametoid_lookup(&ent, 1)) == NULL) | 427 | res = nametoid_lookup(&ent); |
428 | if (res == NULL) | ||
429 | goto out; | ||
430 | res = nametoid_update(&ent, res); | ||
431 | if (res == NULL) | ||
383 | goto out; | 432 | goto out; |
384 | 433 | ||
385 | ent_put(&res->h, &nametoid_cache); | 434 | cache_put(&res->h, &nametoid_cache); |
386 | error = 0; | 435 | error = 0; |
387 | out: | 436 | out: |
388 | kfree(buf1); | 437 | kfree(buf1); |
@@ -390,7 +439,30 @@ out: | |||
390 | return (error); | 439 | return (error); |
391 | } | 440 | } |
392 | 441 | ||
393 | static DefineSimpleCacheLookupMap(ent, nametoid); | 442 | |
443 | static struct ent * | ||
444 | nametoid_lookup(struct ent *item) | ||
445 | { | ||
446 | struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache, | ||
447 | &item->h, | ||
448 | nametoid_hash(item)); | ||
449 | if (ch) | ||
450 | return container_of(ch, struct ent, h); | ||
451 | else | ||
452 | return NULL; | ||
453 | } | ||
454 | |||
455 | static struct ent * | ||
456 | nametoid_update(struct ent *new, struct ent *old) | ||
457 | { | ||
458 | struct cache_head *ch = sunrpc_cache_update(&nametoid_cache, | ||
459 | &new->h, &old->h, | ||
460 | nametoid_hash(new)); | ||
461 | if (ch) | ||
462 | return container_of(ch, struct ent, h); | ||
463 | else | ||
464 | return NULL; | ||
465 | } | ||
394 | 466 | ||
395 | /* | 467 | /* |
396 | * Exported API | 468 | * Exported API |
@@ -458,24 +530,24 @@ idmap_defer(struct cache_req *req) | |||
458 | } | 530 | } |
459 | 531 | ||
460 | static inline int | 532 | static inline int |
461 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key, | 533 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
462 | struct cache_detail *detail, struct ent **item, | 534 | struct cache_detail *detail, struct ent **item, |
463 | struct idmap_defer_req *mdr) | 535 | struct idmap_defer_req *mdr) |
464 | { | 536 | { |
465 | *item = lookup_fn(key, 0); | 537 | *item = lookup_fn(key); |
466 | if (!*item) | 538 | if (!*item) |
467 | return -ENOMEM; | 539 | return -ENOMEM; |
468 | return cache_check(detail, &(*item)->h, &mdr->req); | 540 | return cache_check(detail, &(*item)->h, &mdr->req); |
469 | } | 541 | } |
470 | 542 | ||
471 | static inline int | 543 | static inline int |
472 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int), | 544 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *), |
473 | struct ent *key, struct cache_detail *detail, | 545 | struct ent *key, struct cache_detail *detail, |
474 | struct ent **item) | 546 | struct ent **item) |
475 | { | 547 | { |
476 | int ret = -ENOMEM; | 548 | int ret = -ENOMEM; |
477 | 549 | ||
478 | *item = lookup_fn(key, 0); | 550 | *item = lookup_fn(key); |
479 | if (!*item) | 551 | if (!*item) |
480 | goto out_err; | 552 | goto out_err; |
481 | ret = -ETIMEDOUT; | 553 | ret = -ETIMEDOUT; |
@@ -488,7 +560,7 @@ do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int), | |||
488 | goto out_put; | 560 | goto out_put; |
489 | return 0; | 561 | return 0; |
490 | out_put: | 562 | out_put: |
491 | ent_put(&(*item)->h, detail); | 563 | cache_put(&(*item)->h, detail); |
492 | out_err: | 564 | out_err: |
493 | *item = NULL; | 565 | *item = NULL; |
494 | return ret; | 566 | return ret; |
@@ -496,7 +568,7 @@ out_err: | |||
496 | 568 | ||
497 | static int | 569 | static int |
498 | idmap_lookup(struct svc_rqst *rqstp, | 570 | idmap_lookup(struct svc_rqst *rqstp, |
499 | struct ent *(*lookup_fn)(struct ent *, int), struct ent *key, | 571 | struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
500 | struct cache_detail *detail, struct ent **item) | 572 | struct cache_detail *detail, struct ent **item) |
501 | { | 573 | { |
502 | struct idmap_defer_req *mdr; | 574 | struct idmap_defer_req *mdr; |
@@ -539,7 +611,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen | |||
539 | if (ret) | 611 | if (ret) |
540 | return ret; | 612 | return ret; |
541 | *id = item->id; | 613 | *id = item->id; |
542 | ent_put(&item->h, &nametoid_cache); | 614 | cache_put(&item->h, &nametoid_cache); |
543 | return 0; | 615 | return 0; |
544 | } | 616 | } |
545 | 617 | ||
@@ -561,7 +633,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) | |||
561 | ret = strlen(item->name); | 633 | ret = strlen(item->name); |
562 | BUG_ON(ret > IDMAP_NAMESZ); | 634 | BUG_ON(ret > IDMAP_NAMESZ); |
563 | memcpy(name, item->name, ret); | 635 | memcpy(name, item->name, ret); |
564 | ent_put(&item->h, &idtoname_cache); | 636 | cache_put(&item->h, &idtoname_cache); |
565 | return ret; | 637 | return ret; |
566 | } | 638 | } |
567 | 639 | ||