diff options
-rw-r--r-- | fs/nfsd/nfs4idmap.c | 126 |
1 files changed, 103 insertions, 23 deletions
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index dea690aa8bb5..75cfbb68b205 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
@@ -82,9 +82,12 @@ struct ent { | |||
82 | #define ENT_HASHMAX (1 << ENT_HASHBITS) | 82 | #define ENT_HASHMAX (1 << ENT_HASHBITS) |
83 | #define ENT_HASHMASK (ENT_HASHMAX - 1) | 83 | #define ENT_HASHMASK (ENT_HASHMAX - 1) |
84 | 84 | ||
85 | static inline void | 85 | static void |
86 | ent_init(struct ent *new, struct ent *itm) | 86 | ent_init(struct cache_head *cnew, struct cache_head *citm) |
87 | { | 87 | { |
88 | struct ent *new = container_of(cnew, struct ent, h); | ||
89 | struct ent *itm = container_of(citm, struct ent, h); | ||
90 | |||
88 | new->id = itm->id; | 91 | new->id = itm->id; |
89 | new->type = itm->type; | 92 | new->type = itm->type; |
90 | 93 | ||
@@ -92,12 +95,6 @@ ent_init(struct ent *new, struct ent *itm) | |||
92 | strlcpy(new->authname, itm->authname, sizeof(new->name)); | 95 | strlcpy(new->authname, itm->authname, sizeof(new->name)); |
93 | } | 96 | } |
94 | 97 | ||
95 | static inline void | ||
96 | ent_update(struct ent *new, struct ent *itm) | ||
97 | { | ||
98 | ent_init(new, itm); | ||
99 | } | ||
100 | |||
101 | static void | 98 | static void |
102 | ent_put(struct cache_head *ch, struct cache_detail *cd) | 99 | ent_put(struct cache_head *ch, struct cache_detail *cd) |
103 | { | 100 | { |
@@ -107,6 +104,16 @@ ent_put(struct cache_head *ch, struct cache_detail *cd) | |||
107 | } | 104 | } |
108 | } | 105 | } |
109 | 106 | ||
107 | static struct cache_head * | ||
108 | ent_alloc(void) | ||
109 | { | ||
110 | struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL); | ||
111 | if (e) | ||
112 | return &e->h; | ||
113 | else | ||
114 | return NULL; | ||
115 | } | ||
116 | |||
110 | /* | 117 | /* |
111 | * ID -> Name cache | 118 | * ID -> Name cache |
112 | */ | 119 | */ |
@@ -143,9 +150,12 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, | |||
143 | (*bpp)[-1] = '\n'; | 150 | (*bpp)[-1] = '\n'; |
144 | } | 151 | } |
145 | 152 | ||
146 | static inline int | 153 | static int |
147 | idtoname_match(struct ent *a, struct ent *b) | 154 | idtoname_match(struct cache_head *ca, struct cache_head *cb) |
148 | { | 155 | { |
156 | struct ent *a = container_of(ca, struct ent, h); | ||
157 | struct ent *b = container_of(cb, struct ent, h); | ||
158 | |||
149 | return (a->id == b->id && a->type == b->type && | 159 | return (a->id == b->id && a->type == b->type && |
150 | strcmp(a->authname, b->authname) == 0); | 160 | strcmp(a->authname, b->authname) == 0); |
151 | } | 161 | } |
@@ -178,7 +188,8 @@ warn_no_idmapd(struct cache_detail *detail) | |||
178 | 188 | ||
179 | 189 | ||
180 | static int idtoname_parse(struct cache_detail *, char *, int); | 190 | static int idtoname_parse(struct cache_detail *, char *, int); |
181 | static struct ent *idtoname_lookup(struct ent *, int); | 191 | static struct ent *idtoname_lookup(struct ent *); |
192 | static struct ent *idtoname_update(struct ent *, struct ent *); | ||
182 | 193 | ||
183 | static struct cache_detail idtoname_cache = { | 194 | static struct cache_detail idtoname_cache = { |
184 | .owner = THIS_MODULE, | 195 | .owner = THIS_MODULE, |
@@ -190,6 +201,10 @@ static struct cache_detail idtoname_cache = { | |||
190 | .cache_parse = idtoname_parse, | 201 | .cache_parse = idtoname_parse, |
191 | .cache_show = idtoname_show, | 202 | .cache_show = idtoname_show, |
192 | .warn_no_listener = warn_no_idmapd, | 203 | .warn_no_listener = warn_no_idmapd, |
204 | .match = idtoname_match, | ||
205 | .init = ent_init, | ||
206 | .update = ent_init, | ||
207 | .alloc = ent_alloc, | ||
193 | }; | 208 | }; |
194 | 209 | ||
195 | int | 210 | int |
@@ -232,6 +247,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
232 | if (ent.h.expiry_time == 0) | 247 | if (ent.h.expiry_time == 0) |
233 | goto out; | 248 | goto out; |
234 | 249 | ||
250 | error = -ENOMEM; | ||
251 | res = idtoname_lookup(&ent); | ||
252 | if (!res) | ||
253 | goto out; | ||
254 | |||
235 | /* Name */ | 255 | /* Name */ |
236 | error = qword_get(&buf, buf1, PAGE_SIZE); | 256 | error = qword_get(&buf, buf1, PAGE_SIZE); |
237 | if (error == -EINVAL) | 257 | if (error == -EINVAL) |
@@ -246,7 +266,8 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
246 | memcpy(ent.name, buf1, sizeof(ent.name)); | 266 | memcpy(ent.name, buf1, sizeof(ent.name)); |
247 | } | 267 | } |
248 | error = -ENOMEM; | 268 | error = -ENOMEM; |
249 | if ((res = idtoname_lookup(&ent, 1)) == NULL) | 269 | res = idtoname_update(&ent, res); |
270 | if (res == NULL) | ||
250 | goto out; | 271 | goto out; |
251 | 272 | ||
252 | ent_put(&res->h, &idtoname_cache); | 273 | ent_put(&res->h, &idtoname_cache); |
@@ -258,7 +279,31 @@ out: | |||
258 | return error; | 279 | return error; |
259 | } | 280 | } |
260 | 281 | ||
261 | static DefineSimpleCacheLookup(ent, idtoname); | 282 | |
283 | static struct ent * | ||
284 | idtoname_lookup(struct ent *item) | ||
285 | { | ||
286 | struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache, | ||
287 | &item->h, | ||
288 | idtoname_hash(item)); | ||
289 | if (ch) | ||
290 | return container_of(ch, struct ent, h); | ||
291 | else | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
295 | static struct ent * | ||
296 | idtoname_update(struct ent *new, struct ent *old) | ||
297 | { | ||
298 | struct cache_head *ch = sunrpc_cache_update(&idtoname_cache, | ||
299 | &new->h, &old->h, | ||
300 | idtoname_hash(new)); | ||
301 | if (ch) | ||
302 | return container_of(ch, struct ent, h); | ||
303 | else | ||
304 | return NULL; | ||
305 | } | ||
306 | |||
262 | 307 | ||
263 | /* | 308 | /* |
264 | * Name -> ID cache | 309 | * Name -> ID cache |
@@ -285,9 +330,12 @@ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, | |||
285 | (*bpp)[-1] = '\n'; | 330 | (*bpp)[-1] = '\n'; |
286 | } | 331 | } |
287 | 332 | ||
288 | static inline int | 333 | static int |
289 | nametoid_match(struct ent *a, struct ent *b) | 334 | nametoid_match(struct cache_head *ca, struct cache_head *cb) |
290 | { | 335 | { |
336 | struct ent *a = container_of(ca, struct ent, h); | ||
337 | struct ent *b = container_of(cb, struct ent, h); | ||
338 | |||
291 | return (a->type == b->type && strcmp(a->name, b->name) == 0 && | 339 | return (a->type == b->type && strcmp(a->name, b->name) == 0 && |
292 | strcmp(a->authname, b->authname) == 0); | 340 | strcmp(a->authname, b->authname) == 0); |
293 | } | 341 | } |
@@ -311,7 +359,8 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) | |||
311 | return 0; | 359 | return 0; |
312 | } | 360 | } |
313 | 361 | ||
314 | static struct ent *nametoid_lookup(struct ent *, int); | 362 | static struct ent *nametoid_lookup(struct ent *); |
363 | static struct ent *nametoid_update(struct ent *, struct ent *); | ||
315 | static int nametoid_parse(struct cache_detail *, char *, int); | 364 | static int nametoid_parse(struct cache_detail *, char *, int); |
316 | 365 | ||
317 | static struct cache_detail nametoid_cache = { | 366 | static struct cache_detail nametoid_cache = { |
@@ -324,6 +373,10 @@ static struct cache_detail nametoid_cache = { | |||
324 | .cache_parse = nametoid_parse, | 373 | .cache_parse = nametoid_parse, |
325 | .cache_show = nametoid_show, | 374 | .cache_show = nametoid_show, |
326 | .warn_no_listener = warn_no_idmapd, | 375 | .warn_no_listener = warn_no_idmapd, |
376 | .match = nametoid_match, | ||
377 | .init = ent_init, | ||
378 | .update = ent_init, | ||
379 | .alloc = ent_alloc, | ||
327 | }; | 380 | }; |
328 | 381 | ||
329 | static int | 382 | static int |
@@ -373,7 +426,11 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen) | |||
373 | set_bit(CACHE_NEGATIVE, &ent.h.flags); | 426 | set_bit(CACHE_NEGATIVE, &ent.h.flags); |
374 | 427 | ||
375 | error = -ENOMEM; | 428 | error = -ENOMEM; |
376 | if ((res = nametoid_lookup(&ent, 1)) == NULL) | 429 | res = nametoid_lookup(&ent); |
430 | if (res == NULL) | ||
431 | goto out; | ||
432 | res = nametoid_update(&ent, res); | ||
433 | if (res == NULL) | ||
377 | goto out; | 434 | goto out; |
378 | 435 | ||
379 | ent_put(&res->h, &nametoid_cache); | 436 | ent_put(&res->h, &nametoid_cache); |
@@ -384,7 +441,30 @@ out: | |||
384 | return (error); | 441 | return (error); |
385 | } | 442 | } |
386 | 443 | ||
387 | static DefineSimpleCacheLookup(ent, nametoid); | 444 | |
445 | static struct ent * | ||
446 | nametoid_lookup(struct ent *item) | ||
447 | { | ||
448 | struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache, | ||
449 | &item->h, | ||
450 | nametoid_hash(item)); | ||
451 | if (ch) | ||
452 | return container_of(ch, struct ent, h); | ||
453 | else | ||
454 | return NULL; | ||
455 | } | ||
456 | |||
457 | static struct ent * | ||
458 | nametoid_update(struct ent *new, struct ent *old) | ||
459 | { | ||
460 | struct cache_head *ch = sunrpc_cache_update(&nametoid_cache, | ||
461 | &new->h, &old->h, | ||
462 | nametoid_hash(new)); | ||
463 | if (ch) | ||
464 | return container_of(ch, struct ent, h); | ||
465 | else | ||
466 | return NULL; | ||
467 | } | ||
388 | 468 | ||
389 | /* | 469 | /* |
390 | * Exported API | 470 | * Exported API |
@@ -452,24 +532,24 @@ idmap_defer(struct cache_req *req) | |||
452 | } | 532 | } |
453 | 533 | ||
454 | static inline int | 534 | static inline int |
455 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key, | 535 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
456 | struct cache_detail *detail, struct ent **item, | 536 | struct cache_detail *detail, struct ent **item, |
457 | struct idmap_defer_req *mdr) | 537 | struct idmap_defer_req *mdr) |
458 | { | 538 | { |
459 | *item = lookup_fn(key, 0); | 539 | *item = lookup_fn(key); |
460 | if (!*item) | 540 | if (!*item) |
461 | return -ENOMEM; | 541 | return -ENOMEM; |
462 | return cache_check(detail, &(*item)->h, &mdr->req); | 542 | return cache_check(detail, &(*item)->h, &mdr->req); |
463 | } | 543 | } |
464 | 544 | ||
465 | static inline int | 545 | static inline int |
466 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int), | 546 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *), |
467 | struct ent *key, struct cache_detail *detail, | 547 | struct ent *key, struct cache_detail *detail, |
468 | struct ent **item) | 548 | struct ent **item) |
469 | { | 549 | { |
470 | int ret = -ENOMEM; | 550 | int ret = -ENOMEM; |
471 | 551 | ||
472 | *item = lookup_fn(key, 0); | 552 | *item = lookup_fn(key); |
473 | if (!*item) | 553 | if (!*item) |
474 | goto out_err; | 554 | goto out_err; |
475 | ret = -ETIMEDOUT; | 555 | ret = -ETIMEDOUT; |
@@ -490,7 +570,7 @@ out_err: | |||
490 | 570 | ||
491 | static int | 571 | static int |
492 | idmap_lookup(struct svc_rqst *rqstp, | 572 | idmap_lookup(struct svc_rqst *rqstp, |
493 | struct ent *(*lookup_fn)(struct ent *, int), struct ent *key, | 573 | struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
494 | struct cache_detail *detail, struct ent **item) | 574 | struct cache_detail *detail, struct ent **item) |
495 | { | 575 | { |
496 | struct idmap_defer_req *mdr; | 576 | struct idmap_defer_req *mdr; |