Extend the exportfs interface to pass fslocations info into the kernel.
authorFred Isaman <iisaman@citi.umich.edu>
Thu, 22 Feb 2007 04:48:53 +0000 (15:48 +1100)
committerNeil Brown <neilb@suse.de>
Thu, 22 Feb 2007 04:48:53 +0000 (15:48 +1100)
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 <iisaman@citi.umich.edu>
Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
support/include/exportfs.h
support/include/nfslib.h
support/nfs/exports.c
utils/exportfs/exportfs.c
utils/exportfs/exports.man
utils/mountd/Makefile.am
utils/mountd/cache.c

index 10f38c7..458611b 100644 (file)
@@ -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];
index 13a89da..c085029 100644 (file)
@@ -80,6 +80,8 @@ struct exportent {
        int             e_nsqgids;
        int             e_fsid;
        char *          e_mountpoint;
+       int             e_fslocmethod;
+       char *          e_fslocdata;
        char *          e_uuid;
 };
 
index 0994ea2..31b38c3 100644 (file)
@@ -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);
index 2e2b6f3..40a6b56 100644 (file)
@@ -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 != '(')? ')' : ' ');
                }
        }
index 3aa8de8..27a30f9 100644 (file)
@@ -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
index c8500cb..1e76cf8 100644 (file)
@@ -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 \
index 629d567..a14f4f2 100644 (file)
@@ -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);
 }