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; |
