summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--support/include/exportfs.h7
-rw-r--r--support/include/nfslib.h2
-rw-r--r--support/nfs/exports.c37
-rw-r--r--utils/exportfs/exportfs.c14
-rw-r--r--utils/exportfs/exports.man14
-rw-r--r--utils/mountd/Makefile.am2
-rw-r--r--utils/mountd/cache.c25
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; i<servers->h_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);
}