From 5fb04a376e6d5ba940e66507e4a615f4e94116e6 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Thu, 22 Feb 2007 15:48:53 +1100 Subject: [PATCH] Extend the exportfs interface to pass fslocations info into the kernel. Extend exportfs interface to pass fslocations info into the kernel, using syntax modelled after AIX. Adds "refer=" and "replicas=" options to /etc/exports to enable use of the kernel fslocation code. Signed-off-by: Fred Isaman Signed-off-by: Kevin Coffman Signed-off-by: Neil Brown --- support/include/exportfs.h | 7 +++++++ support/include/nfslib.h | 2 ++ support/nfs/exports.c | 37 ++++++++++++++++++++++++++++++++++++- utils/exportfs/exportfs.c | 14 +++++++++++++- utils/exportfs/exports.man | 14 ++++++++++++++ utils/mountd/Makefile.am | 2 +- utils/mountd/cache.c | 25 +++++++++++++++++++++++++ 7 files changed, 98 insertions(+), 3 deletions(-) diff --git a/support/include/exportfs.h b/support/include/exportfs.h index 10f38c7..458611b 100644 --- a/support/include/exportfs.h +++ b/support/include/exportfs.h @@ -23,6 +23,13 @@ enum { MCL_MAXTYPES }; +enum { + FSLOC_NONE = 0, + FSLOC_REFER, + FSLOC_REPLICA, + FSLOC_STUB +}; + typedef struct mclient { struct mclient * m_next; char m_hostname[NFSCLNT_IDMAX+1]; diff --git a/support/include/nfslib.h b/support/include/nfslib.h index 13a89da..c085029 100644 --- a/support/include/nfslib.h +++ b/support/include/nfslib.h @@ -80,6 +80,8 @@ struct exportent { int e_nsqgids; int e_fsid; char * e_mountpoint; + int e_fslocmethod; + char * e_fslocdata; char * e_uuid; }; diff --git a/support/nfs/exports.c b/support/nfs/exports.c index 0994ea2..31b38c3 100644 --- a/support/nfs/exports.c +++ b/support/nfs/exports.c @@ -100,6 +100,8 @@ getexportent(int fromkernel, int fromexports) def_ee.e_squids = NULL; def_ee.e_sqgids = NULL; def_ee.e_mountpoint = NULL; + def_ee.e_fslocmethod = FSLOC_NONE; + def_ee.e_fslocdata = NULL; def_ee.e_nsquids = 0; def_ee.e_nsqgids = 0; @@ -225,7 +227,22 @@ putexportent(struct exportent *ep) if (ep->e_mountpoint) fprintf(fp, "mountpoint%s%s,", ep->e_mountpoint[0]?"=":"", ep->e_mountpoint); - + switch (ep->e_fslocmethod) { + case FSLOC_NONE: + break; + case FSLOC_REFER: + fprintf(fp, "refer=%s,", ep->e_fslocdata); + break; + case FSLOC_REPLICA: + fprintf(fp, "replicas=%s,", ep->e_fslocdata); + break; + case FSLOC_STUB: + fprintf(fp, "fsloc=stub,"); + break; + default: + xlog(L_ERROR, "unknown fsloc method for %s:%s", + ep->e_hostname, ep->e_path); + } fprintf(fp, "mapping="); switch (ep->e_maptype) { case CLE_MAP_IDENT: @@ -288,6 +305,8 @@ dupexportent(struct exportent *dst, struct exportent *src) } if (src->e_mountpoint) dst->e_mountpoint = strdup(src->e_mountpoint); + if (src->e_fslocdata) + dst->e_fslocdata = strdup(src->e_fslocdata); } struct exportent * @@ -302,6 +321,8 @@ mkexportent(char *hname, char *path, char *options) ee.e_squids = NULL; ee.e_sqgids = NULL; ee.e_mountpoint = NULL; + ee.e_fslocmethod = FSLOC_NONE; + ee.e_fslocdata = NULL; ee.e_nsquids = 0; ee.e_nsqgids = 0; ee.e_uuid = NULL; @@ -483,6 +504,20 @@ bad_option: ep->e_mountpoint = strdup(mp+1); else ep->e_mountpoint = strdup(""); + } else if (strncmp(opt, "fsloc=", 6) == 0) { + if (strcmp(opt+6, "stub") == 0) + ep->e_fslocmethod = FSLOC_STUB; + else { + xlog(L_ERROR, "%s:%d: bad option %s\n", + flname, flline, opt); + goto bad_option; + } + } else if (strncmp(opt, "refer=", 6) == 0) { + ep->e_fslocmethod = FSLOC_REFER; + ep->e_fslocdata = strdup(opt+6); + } else if (strncmp(opt, "replicas=", 9) == 0) { + ep->e_fslocmethod = FSLOC_REPLICA; + ep->e_fslocdata = strdup(opt+9); } else { xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n", flname, flline, opt); diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index 2e2b6f3..40a6b56 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -418,7 +418,19 @@ dump(int verbose) c = dumpopt(c, "anonuid=%d", ep->e_anonuid); if (ep->e_anongid != 65534) c = dumpopt(c, "anongid=%d", ep->e_anongid); - + switch(ep->e_fslocmethod) { + case FSLOC_NONE: + break; + case FSLOC_REFER: + c = dumpopt(c, "refer=%s", ep->e_fslocdata); + break; + case FSLOC_REPLICA: + c = dumpopt(c, "replicas=%s", ep->e_fslocdata); + break; + case FSLOC_STUB: + c = dumpopt(c, "fsloc=stub"); + break; + } printf("%c\n", (c != '(')? ')' : ' '); } } diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man index 3aa8de8..27a30f9 100644 --- a/utils/exportfs/exports.man +++ b/utils/exportfs/exports.man @@ -334,6 +334,20 @@ set for such kernels. Setting both a small number and a UUID is supported so the same configuration can be made to work on old and new kernels alike. +.TP +.IR refer= path@host[+host][:path@host[+host]] +A client referencing the export point will be directed to choose from +the given list an alternative location for the filesystem. +(Note that the server must have a mountpoint here, though a different +filesystem is not required; so, for example, +.IR "mount --bind" " /path /path" +is sufficient.) +.TP +.IR replicas= path@host[+host][:path@host[+host]] +If the client asks for alternative locations for the export point, it +will be given this list of alternatives. (Note that actual replication +of the filesystem must be handled elsewhere.) + .SS User ID Mapping .PP .I nfsd diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am index c8500cb..1e76cf8 100644 --- a/utils/mountd/Makefile.am +++ b/utils/mountd/Makefile.am @@ -8,7 +8,7 @@ KPREFIX = @kprefix@ sbin_PROGRAMS = mountd mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \ - svc_run.c mountd.h + svc_run.c fsloc.c mountd.h mountd_LDADD = ../../support/export/libexport.a \ ../../support/nfs/libnfs.a \ ../../support/misc/libmisc.a \ diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index 629d567..a14f4f2 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -28,6 +28,7 @@ #include "exportfs.h" #include "mountd.h" #include "xmalloc.h" +#include "fsloc.h" #include "blkid/blkid.h" @@ -421,6 +422,29 @@ void nfsd_fh(FILE *f) return; } +static void write_fsloc(FILE *f, struct exportent *ep, char *path) +{ + struct servers *servers; + + if (ep->e_fslocmethod == FSLOC_NONE) + return; + + servers = replicas_lookup(ep->e_fslocmethod, ep->e_fslocdata, path); + if (!servers) + return; + qword_print(f, "fsloc"); + qword_printint(f, servers->h_num); + if (servers->h_num >= 0) { + int i; + for (i=0; ih_num; i++) { + qword_print(f, servers->h_mp[i]->h_host); + qword_print(f, servers->h_mp[i]->h_path); + } + } + qword_printint(f, servers->h_referral); + release_replicas(servers); +} + static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp) { qword_print(f, domain); @@ -441,6 +465,7 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex qword_print(f, "uuid"); qword_printhex(f, exp->e_uuid, 16); } + write_fsloc(f, &exp, path); } return qword_eol(f); } -- 2.39.5