diff options
author | Manoj Naik <manoj@almaden.ibm.com> | 2006-10-04 05:16:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:22 -0400 |
commit | 933469190ed5915b0568bc564346bb8db718f460 (patch) | |
tree | fdb811ebfb962b0dc5e9b567ef13df234d49918a | |
parent | b009a873de05c6e0d7613df3584b6dcb2e4280ee (diff) |
[PATCH] knfsd: nfsd4: fslocations data structures
Define FS locations structures, some functions to manipulate them, and add
code to parse FS locations in downcall and add to the exports structure.
[bfields@fieldses.org: bunch of fixes and cleanups]
Signed-off-by: Manoj Naik <manoj@almaden.ibm.com>
Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/nfsd/export.c | 118 | ||||
-rw-r--r-- | include/linux/nfsd/export.h | 20 |
2 files changed, 134 insertions, 4 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index d3178de589e4..e13fa23bd108 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -319,6 +319,17 @@ svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) | |||
319 | 319 | ||
320 | static struct cache_head *export_table[EXPORT_HASHMAX]; | 320 | static struct cache_head *export_table[EXPORT_HASHMAX]; |
321 | 321 | ||
322 | static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) | ||
323 | { | ||
324 | int i; | ||
325 | |||
326 | for (i = 0; i < fsloc->locations_count; i++) { | ||
327 | kfree(fsloc->locations[i].path); | ||
328 | kfree(fsloc->locations[i].hosts); | ||
329 | } | ||
330 | kfree(fsloc->locations); | ||
331 | } | ||
332 | |||
322 | static void svc_export_put(struct kref *ref) | 333 | static void svc_export_put(struct kref *ref) |
323 | { | 334 | { |
324 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); | 335 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
@@ -326,6 +337,7 @@ static void svc_export_put(struct kref *ref) | |||
326 | mntput(exp->ex_mnt); | 337 | mntput(exp->ex_mnt); |
327 | auth_domain_put(exp->ex_client); | 338 | auth_domain_put(exp->ex_client); |
328 | kfree(exp->ex_path); | 339 | kfree(exp->ex_path); |
340 | nfsd4_fslocs_free(&exp->ex_fslocs); | ||
329 | kfree(exp); | 341 | kfree(exp); |
330 | } | 342 | } |
331 | 343 | ||
@@ -387,6 +399,69 @@ static int check_export(struct inode *inode, int flags) | |||
387 | 399 | ||
388 | } | 400 | } |
389 | 401 | ||
402 | #ifdef CONFIG_NFSD_V4 | ||
403 | |||
404 | static int | ||
405 | fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) | ||
406 | { | ||
407 | int len; | ||
408 | int migrated, i, err; | ||
409 | |||
410 | len = qword_get(mesg, buf, PAGE_SIZE); | ||
411 | if (len != 5 || memcmp(buf, "fsloc", 5)) | ||
412 | return 0; | ||
413 | |||
414 | /* listsize */ | ||
415 | err = get_int(mesg, &fsloc->locations_count); | ||
416 | if (err) | ||
417 | return err; | ||
418 | if (fsloc->locations_count > MAX_FS_LOCATIONS) | ||
419 | return -EINVAL; | ||
420 | if (fsloc->locations_count == 0) | ||
421 | return 0; | ||
422 | |||
423 | fsloc->locations = kzalloc(fsloc->locations_count | ||
424 | * sizeof(struct nfsd4_fs_location), GFP_KERNEL); | ||
425 | if (!fsloc->locations) | ||
426 | return -ENOMEM; | ||
427 | for (i=0; i < fsloc->locations_count; i++) { | ||
428 | /* colon separated host list */ | ||
429 | err = -EINVAL; | ||
430 | len = qword_get(mesg, buf, PAGE_SIZE); | ||
431 | if (len <= 0) | ||
432 | goto out_free_all; | ||
433 | err = -ENOMEM; | ||
434 | fsloc->locations[i].hosts = kstrdup(buf, GFP_KERNEL); | ||
435 | if (!fsloc->locations[i].hosts) | ||
436 | goto out_free_all; | ||
437 | err = -EINVAL; | ||
438 | /* slash separated path component list */ | ||
439 | len = qword_get(mesg, buf, PAGE_SIZE); | ||
440 | if (len <= 0) | ||
441 | goto out_free_all; | ||
442 | err = -ENOMEM; | ||
443 | fsloc->locations[i].path = kstrdup(buf, GFP_KERNEL); | ||
444 | if (!fsloc->locations[i].path) | ||
445 | goto out_free_all; | ||
446 | } | ||
447 | /* migrated */ | ||
448 | err = get_int(mesg, &migrated); | ||
449 | if (err) | ||
450 | goto out_free_all; | ||
451 | err = -EINVAL; | ||
452 | if (migrated < 0 || migrated > 1) | ||
453 | goto out_free_all; | ||
454 | fsloc->migrated = migrated; | ||
455 | return 0; | ||
456 | out_free_all: | ||
457 | nfsd4_fslocs_free(fsloc); | ||
458 | return err; | ||
459 | } | ||
460 | |||
461 | #else /* CONFIG_NFSD_V4 */ | ||
462 | static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; } | ||
463 | #endif | ||
464 | |||
390 | static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | 465 | static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) |
391 | { | 466 | { |
392 | /* client path expiry [flags anonuid anongid fsid] */ | 467 | /* client path expiry [flags anonuid anongid fsid] */ |
@@ -441,6 +516,11 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
441 | if (exp.h.expiry_time == 0) | 516 | if (exp.h.expiry_time == 0) |
442 | goto out; | 517 | goto out; |
443 | 518 | ||
519 | /* fs locations */ | ||
520 | exp.ex_fslocs.locations = NULL; | ||
521 | exp.ex_fslocs.locations_count = 0; | ||
522 | exp.ex_fslocs.migrated = 0; | ||
523 | |||
444 | /* flags */ | 524 | /* flags */ |
445 | err = get_int(&mesg, &an_int); | 525 | err = get_int(&mesg, &an_int); |
446 | if (err == -ENOENT) | 526 | if (err == -ENOENT) |
@@ -466,6 +546,10 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
466 | 546 | ||
467 | err = check_export(nd.dentry->d_inode, exp.ex_flags); | 547 | err = check_export(nd.dentry->d_inode, exp.ex_flags); |
468 | if (err) goto out; | 548 | if (err) goto out; |
549 | |||
550 | err = fsloc_parse(&mesg, buf, &exp.ex_fslocs); | ||
551 | if (err) | ||
552 | goto out; | ||
469 | } | 553 | } |
470 | 554 | ||
471 | expp = svc_export_lookup(&exp); | 555 | expp = svc_export_lookup(&exp); |
@@ -489,7 +573,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
489 | return err; | 573 | return err; |
490 | } | 574 | } |
491 | 575 | ||
492 | static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong); | 576 | static void exp_flags(struct seq_file *m, int flag, int fsid, |
577 | uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs); | ||
493 | 578 | ||
494 | static int svc_export_show(struct seq_file *m, | 579 | static int svc_export_show(struct seq_file *m, |
495 | struct cache_detail *cd, | 580 | struct cache_detail *cd, |
@@ -508,8 +593,8 @@ static int svc_export_show(struct seq_file *m, | |||
508 | seq_putc(m, '('); | 593 | seq_putc(m, '('); |
509 | if (test_bit(CACHE_VALID, &h->flags) && | 594 | if (test_bit(CACHE_VALID, &h->flags) && |
510 | !test_bit(CACHE_NEGATIVE, &h->flags)) | 595 | !test_bit(CACHE_NEGATIVE, &h->flags)) |
511 | exp_flags(m, exp->ex_flags, exp->ex_fsid, | 596 | exp_flags(m, exp->ex_flags, exp->ex_fsid, |
512 | exp->ex_anon_uid, exp->ex_anon_gid); | 597 | exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs); |
513 | seq_puts(m, ")\n"); | 598 | seq_puts(m, ")\n"); |
514 | return 0; | 599 | return 0; |
515 | } | 600 | } |
@@ -532,6 +617,9 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) | |||
532 | new->ex_dentry = dget(item->ex_dentry); | 617 | new->ex_dentry = dget(item->ex_dentry); |
533 | new->ex_mnt = mntget(item->ex_mnt); | 618 | new->ex_mnt = mntget(item->ex_mnt); |
534 | new->ex_path = NULL; | 619 | new->ex_path = NULL; |
620 | new->ex_fslocs.locations = NULL; | ||
621 | new->ex_fslocs.locations_count = 0; | ||
622 | new->ex_fslocs.migrated = 0; | ||
535 | } | 623 | } |
536 | 624 | ||
537 | static void export_update(struct cache_head *cnew, struct cache_head *citem) | 625 | static void export_update(struct cache_head *cnew, struct cache_head *citem) |
@@ -545,6 +633,12 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem) | |||
545 | new->ex_fsid = item->ex_fsid; | 633 | new->ex_fsid = item->ex_fsid; |
546 | new->ex_path = item->ex_path; | 634 | new->ex_path = item->ex_path; |
547 | item->ex_path = NULL; | 635 | item->ex_path = NULL; |
636 | new->ex_fslocs.locations = item->ex_fslocs.locations; | ||
637 | item->ex_fslocs.locations = NULL; | ||
638 | new->ex_fslocs.locations_count = item->ex_fslocs.locations_count; | ||
639 | item->ex_fslocs.locations_count = 0; | ||
640 | new->ex_fslocs.migrated = item->ex_fslocs.migrated; | ||
641 | item->ex_fslocs.migrated = 0; | ||
548 | } | 642 | } |
549 | 643 | ||
550 | static struct cache_head *svc_export_alloc(void) | 644 | static struct cache_head *svc_export_alloc(void) |
@@ -1159,7 +1253,8 @@ static struct flags { | |||
1159 | { 0, {"", ""}} | 1253 | { 0, {"", ""}} |
1160 | }; | 1254 | }; |
1161 | 1255 | ||
1162 | static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong) | 1256 | static void exp_flags(struct seq_file *m, int flag, int fsid, |
1257 | uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc) | ||
1163 | { | 1258 | { |
1164 | int first = 0; | 1259 | int first = 0; |
1165 | struct flags *flg; | 1260 | struct flags *flg; |
@@ -1175,6 +1270,21 @@ static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t | |||
1175 | seq_printf(m, "%sanonuid=%d", first++?",":"", anonu); | 1270 | seq_printf(m, "%sanonuid=%d", first++?",":"", anonu); |
1176 | if (anong != (gid_t)-2 && anong != (0x10000-2)) | 1271 | if (anong != (gid_t)-2 && anong != (0x10000-2)) |
1177 | seq_printf(m, "%sanongid=%d", first++?",":"", anong); | 1272 | seq_printf(m, "%sanongid=%d", first++?",":"", anong); |
1273 | if (fsloc && fsloc->locations_count > 0) { | ||
1274 | char *loctype = (fsloc->migrated) ? "refer" : "replicas"; | ||
1275 | int i; | ||
1276 | |||
1277 | seq_printf(m, "%s%s=", first++?",":"", loctype); | ||
1278 | seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\"); | ||
1279 | seq_putc(m, '@'); | ||
1280 | seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\"); | ||
1281 | for (i = 1; i < fsloc->locations_count; i++) { | ||
1282 | seq_putc(m, ';'); | ||
1283 | seq_escape(m, fsloc->locations[i].path, ",;@ \t\n\\"); | ||
1284 | seq_putc(m, '@'); | ||
1285 | seq_escape(m, fsloc->locations[i].hosts, ",;@ \t\n\\"); | ||
1286 | } | ||
1287 | } | ||
1178 | } | 1288 | } |
1179 | 1289 | ||
1180 | static int e_show(struct seq_file *m, void *p) | 1290 | static int e_show(struct seq_file *m, void *p) |
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 47d96684b611..6e78ea969f49 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h | |||
@@ -45,6 +45,25 @@ | |||
45 | 45 | ||
46 | #ifdef __KERNEL__ | 46 | #ifdef __KERNEL__ |
47 | 47 | ||
48 | /* | ||
49 | * FS Locations | ||
50 | */ | ||
51 | |||
52 | #define MAX_FS_LOCATIONS 128 | ||
53 | |||
54 | struct nfsd4_fs_location { | ||
55 | char *hosts; /* colon separated list of hosts */ | ||
56 | char *path; /* slash separated list of path components */ | ||
57 | }; | ||
58 | |||
59 | struct nfsd4_fs_locations { | ||
60 | uint32_t locations_count; | ||
61 | struct nfsd4_fs_location *locations; | ||
62 | /* If we're not actually serving this data ourselves (only providing a | ||
63 | * list of replicas that do serve it) then we set "migrated": */ | ||
64 | int migrated; | ||
65 | }; | ||
66 | |||
48 | struct svc_export { | 67 | struct svc_export { |
49 | struct cache_head h; | 68 | struct cache_head h; |
50 | struct auth_domain * ex_client; | 69 | struct auth_domain * ex_client; |
@@ -55,6 +74,7 @@ struct svc_export { | |||
55 | uid_t ex_anon_uid; | 74 | uid_t ex_anon_uid; |
56 | gid_t ex_anon_gid; | 75 | gid_t ex_anon_gid; |
57 | int ex_fsid; | 76 | int ex_fsid; |
77 | struct nfsd4_fs_locations ex_fslocs; | ||
58 | }; | 78 | }; |
59 | 79 | ||
60 | /* an "export key" (expkey) maps a filehandlefragement to an | 80 | /* an "export key" (expkey) maps a filehandlefragement to an |