aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManoj Naik <manoj@almaden.ibm.com>2006-10-04 05:16:18 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:22 -0400
commit933469190ed5915b0568bc564346bb8db718f460 (patch)
treefdb811ebfb962b0dc5e9b567ef13df234d49918a
parentb009a873de05c6e0d7613df3584b6dcb2e4280ee (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.c118
-rw-r--r--include/linux/nfsd/export.h20
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
320static struct cache_head *export_table[EXPORT_HASHMAX]; 320static struct cache_head *export_table[EXPORT_HASHMAX];
321 321
322static 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
322static void svc_export_put(struct kref *ref) 333static 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
404static int
405fsloc_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;
456out_free_all:
457 nfsd4_fslocs_free(fsloc);
458 return err;
459}
460
461#else /* CONFIG_NFSD_V4 */
462static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; }
463#endif
464
390static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) 465static 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
492static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong); 576static 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
494static int svc_export_show(struct seq_file *m, 579static 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
537static void export_update(struct cache_head *cnew, struct cache_head *citem) 625static 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
550static struct cache_head *svc_export_alloc(void) 644static struct cache_head *svc_export_alloc(void)
@@ -1159,7 +1253,8 @@ static struct flags {
1159 { 0, {"", ""}} 1253 { 0, {"", ""}}
1160}; 1254};
1161 1255
1162static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong) 1256static 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
1180static int e_show(struct seq_file *m, void *p) 1290static 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
54struct nfsd4_fs_location {
55 char *hosts; /* colon separated list of hosts */
56 char *path; /* slash separated list of path components */
57};
58
59struct 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
48struct svc_export { 67struct 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