This new utility interprets the passed-in key as a FedFS domain,
performs a DNS SRV lookup, and generates the mount.nfs parameters
needed to mount the domain.  It can handle multiple read-only and
read-write domain root replicas using support already built into the
automounter.

The FedFS entry in the master map might look like this:

  /nfs4         /usr/sbin/fedfs-map-nfs4

To support other file system protocols, additional lines in the master
map and another program map utility (or options for this one) would be
needed.

Benefits:

  o  Simple to configure

  o  The TLD can be placed anywhere on the client

  o  No additional build or package dependencies on nfs-utils or
     autofs

Signed-off-by: Chuck Lever <chuck.le...@oracle.com>
---

 .gitignore                 |    1 
 INSTALL                    |   10 +-
 README                     |   14 ++-
 doc/man/Makefile.am        |    2 
 doc/man/fedfs-map-nfs4.8   |  154 ++++++++++++++++++++++++++++
 doc/man/fedfs.7            |    4 +
 src/mount/Makefile.am      |    5 +
 src/mount/fedfs-map-nfs4.c |  242 ++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 422 insertions(+), 10 deletions(-)
 create mode 100644 doc/man/fedfs-map-nfs4.8
 create mode 100644 src/mount/fedfs-map-nfs4.c

diff --git a/.gitignore b/.gitignore
index ce06ff1..41daf0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ src/fedfsd/fedfsd
 src/resolve-junction/resolve-junction
 src/nsdbparams/nsdbparams
 src/mount/mount.fedfs
+src/mount/fedfs-map-nfs4
 libadmin.a
 libjunction.a
 libnsdb.a
diff --git a/INSTALL b/INSTALL
index 8cb8e9e..548381b 100644
--- a/INSTALL
+++ b/INSTALL
@@ -143,12 +143,14 @@ FedFS file server
 
 FedFS client
 
-  o Install mount.fedfs
+  o Install /usr/sbin/fedfs-map-nfs4
 
-  o Create a local /nfs4 directory, and subdirectories for the FedFS
-    domains you want to mount
+  o Create a local /nfs4 directory
 
-  o Add lines to /etc/fstab to mount the domains
+  o Install and configure autofs
+
+  o Add an entry to the master map (usually /etc/auto.master) for
+    the /nfs4 directory and restart autofs
 
 
 FedFS admin client
diff --git a/README b/README
index 0067ac2..78b9647 100644
--- a/README
+++ b/README
@@ -59,7 +59,10 @@ changed over time.
 
 Installable components include:
 
-   o  A mount command to mount the top of a FedFS domain namespace
+   o  An automounter program map to manage the FedFS domain namespace
+      on FedFS-enabled clients
+
+   o  A mount command to mount parts of a FedFS domain namespace
 
    o  An ONC RPC service daemon that runs on file servers enabling the
       management by remote FedFS ADMIN clients of FedFS junctions
@@ -81,9 +84,14 @@ Installable components include:
    o  HTML Doxygen style documentation with built-in source browser
 
 
+The automounter program map is a subcommand invoked by the automounter
+to locate FedFS domains and construct appropriate mount options for
+mounting domain roots.  It is used in conjunction with the Linux
+autofs facility.
+
 The mount command is a subcommand invoked by mount(8) to handle the
-housekeeping needed to find and mount FedFS domains at the top of the
-client's FedFS namespace (usually /nfs4 for NFSv4 servers).
+housekeeping needed to find and mount part or all of FedFS domain
+name spaces.
 
 The fedfsd program is an RPC server that allows remote administrators to
 create FedFS junctions in local file systems.  FedFS ADMIN requests that
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 7f92ebf..83c6d03 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -24,6 +24,6 @@
 ##
 
 dist_man7_MANS         = fedfs.7
-dist_man8_MANS         = rpc.fedfsd.8 mount.fedfs.8
+dist_man8_MANS         = rpc.fedfsd.8 mount.fedfs.8 fedfs-map-nfs4.8
 CLEANFILES             = cscope.in.out cscope.out cscope.po.out
 DISTCLEANFILES         = Makefile.in
diff --git a/doc/man/fedfs-map-nfs4.8 b/doc/man/fedfs-map-nfs4.8
new file mode 100644
index 0000000..ffc5b6a
--- /dev/null
+++ b/doc/man/fedfs-map-nfs4.8
@@ -0,0 +1,154 @@
+.\"@(#)fedfs-map-nfs4.8"
+.\"
+.\" @file doc/man/fedfs-map-nfs4.8
+.\" @brief man page for fedfs-map-nfs4 command
+.\"
+
+.\"
+.\" Copyright 2011 Oracle.  All rights reserved.
+.\"
+.\" This file is part of fedfs-utils.
+.\"
+.\" fedfs-utils is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License version 2.0 as
+.\" published by the Free Software Foundation.
+.\"
+.\" fedfs-utils is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+.\" GNU General Public License version 2.0 for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" version 2.0 along with fedfs-utils.  If not, see:
+.\"
+.\"    http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+.\"
+.TH FEDFS-MAP-NFS4 8 "30 Apr 2011"
+.SH NAME
+fedfs-map-nfs4 \- generate automounter program map entries for FedFS
+.SH SYNOPSIS
+.B fedfs-map-nfs4
+.I domainname
+.SH INTRODUCTION
+RFC 5716 introduces the Federated File System (FedFS, for short).
+FedFS is an extensible standardized mechanism
+by which system administrators construct
+a coherent namespace across multiple file servers using
+.IR "file system referrals" .
+For further details, see
+.BR fedfs (7).
+.SH DESCRIPTION
+The
+.BR fedfs-map-nfs4 (8)
+command provides a FedFS program map for the local system's automounter.
+Although it is typically intended to be invoked by the automounter,
+it is also safe to invoke directly for scripting or debugging purposes.
+See
+.BR autofs (5)
+for information about how program maps work.
+.SS Operation
+The
+.BR fedfs-map-nfs4 (8)
+command locates FedFS domains by looking for DNS SRV records
+that advertise file servers exporting domain root replicas.
+The
+.I domainname
+argument determines what FedFS domain is to be mounted.
+.P
+It retrieves and sorts the domain root replica records
+according to SRV record sorting rules outlined in RFC 2782.
+It then generates a sun format map entry on
+.I stdout
+representing the set of servers contained in the SRV record,
+a standard export path to the domain root,
+and appropriate NFS mount options.
+Error messages are output on
+.IR stderr .
+.SS Globally useful names
+Across all FedFS-enabled file system clients,
+a unique file object in a FedFS domain is always accessed
+via the same pathname.
+Such pathnames are referred to as
+.IR "globally useful names" .
+See
+.BR fedfs (7)
+for a full discussion.
+.P
+The top-level directory of a globally useful name is always
+the networked file system type (NFS version 4, CIFS, and so on).
+A
+.BR fedfs-map-nfs4 (8)
+program map entry is used with the NFS version 4 top-level directory
+to provide globally useful names via the NFS version 4 protocol.
+.SH EXAMPLES
+Typically, a
+.BR fedfs-map-nfs4 (8)
+entry in
+.I /etc/auto.master
+looks like this:
+.P
+.NF
+.TA 2.5i +0.7i +0.7i
+       /nfs4   /usr/sbin/fedfs-map-nfs4
+.FI
+.P
+Under the /nfs4 directory on the local system, the automounter uses
+.BR fedfs-map-nfs4 (8)
+to convert a FedFS domain name to a set of servers and an export path,
+which are then passed to
+.BR mount.nfs (8).
+.P
+The automounter mounts this FedFS domain on the directory
+.IR /nfs4/domainname .
+Note that this also works for dot-prefixed domain names, in order to
+support mounting read-write domain root replicas.
+.P
+After configuring and restarting
+.BR autofs ,
+to access files in the
+.I example.net
+FedFS domain, for instance, you can start with:
+.RS
+.sp
+cd /nfs4/example.net
+.sp
+.RE
+The automounter uses the
+.BR fedfs-map-nfs4 (8)
+command to look up the file servers that provide the domain root for the
+.I example.net
+domain.  It then mounts one of these servers on
+.IR /nfs4/example.net .
+.P
+If the
+.BR fedfs-map-nfs4 (8)
+command cannot find the requested domain, no local directory is created
+and no mount operation is performed.  Applications receive an ENOENT
+error in this case.
+.P
+While these mounted domains remain active on the local system,
+the mounted-on directories remain visible.
+After a period of inactivity, the automounter automatically unmounts
+a FedFS domain.
+Local applications browsing the top-level directory
+do not see all available FedFS domains.  They see only the ones that
+are mounted and active.
+.SH FILES
+.TP 18n
+.I /etc/auto.master
+master automounter map
+.SH "SEE ALSO"
+.BR fedfs (7),
+.BR nfs (5),
+.BR autofs (5),
+.sp
+RFC 2782 for a discussion of DNS SRV records
+.sp
+RFC 5716 for FedFS requirements and overview
+.SH COLOPHON
+This page is part of the fedfs-utils package.
+A description of the project and information about reporting bugs
+can be found at
+.IR http://oss.oracle.com/projects/fedfs-utils .
+.SH "AUTHOR"
+Chuck Lever <chuck.le...@oracle.com>
diff --git a/doc/man/fedfs.7 b/doc/man/fedfs.7
index a2d2759..83eb215 100644
--- a/doc/man/fedfs.7
+++ b/doc/man/fedfs.7
@@ -164,7 +164,8 @@ file system below them,
 are visible at a different point in a client's name space
 than are read-only replicas.
 .SS Globally Useful Names
-On FedFS-enabled Linux clients, the
+On FedFS-enabled Linux clients,
+either the automounter, with a special program map, or the
 .BR mount.fedfs (8)
 command finds and mounts the root of a FedFS domain.
 .P
@@ -258,6 +259,7 @@ when administering junctions and filesets,
 junctions are created on file servers and
 registered with the domain's NSDB in two separate steps.
 .SH SEE ALSO
+.BR fedfs-map-nfs4 (8),
 .BR mount.fedfs (8),
 .BR rpc.fedfsd (8),
 .BR rpc.mountd (8),
diff --git a/src/mount/Makefile.am b/src/mount/Makefile.am
index 9338d47..93c6b72 100644
--- a/src/mount/Makefile.am
+++ b/src/mount/Makefile.am
@@ -24,7 +24,10 @@
 ##
 
 noinst_HEADERS         = nls.h
-sbin_PROGRAMS          = mount.fedfs
+sbin_PROGRAMS          = mount.fedfs fedfs-map-nfs4
+fedfs_map_nfs4_SOURCES = fedfs-map-nfs4.c
+fedfs_map_nfs4_LDADD   = -lresolv \
+                         $(top_builddir)/src/libsi/libsi.a
 mount_fedfs_SOURCES    = main.c
 mount_fedfs_LDADD      = -lresolv \
                          $(top_builddir)/src/libsi/libsi.a
diff --git a/src/mount/fedfs-map-nfs4.c b/src/mount/fedfs-map-nfs4.c
new file mode 100644
index 0000000..8376b6b
--- /dev/null
+++ b/src/mount/fedfs-map-nfs4.c
@@ -0,0 +1,242 @@
+/**
+ * @file src/mount/fedfs-map-nfs4.c
+ * @brief Convert FedFS domain name key to automounter map entry
+ */
+
+/*
+ * Copyright 2011 Oracle.  All rights reserved.
+ *
+ * This file is part of fedfs-utils.
+ *
+ * fedfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2.0 as
+ * published by the Free Software Foundation.
+ *
+ * fedfs-utils is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2.0 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2.0 along with fedfs-utils.  If not, see:
+ *
+ *     http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <libgen.h>
+#include <errno.h>
+#include <getopt.h>
+#include <locale.h>
+#include <netdb.h>
+#include <langinfo.h>
+
+#include "nls.h"
+#include "getsrvinfo.h"
+#include "token.h"
+#include "gpl-boiler.h"
+
+/**
+ * Name of SRV record containing NFSv4 r/o FedFS root
+ */
+#define FEDFS_NFS4_DOMAINROOT_RO       "_nfs4._domainroot._tcp"
+
+/**
+ * Name of SRV record containing NFSv4 r/w FedFS root
+ */
+#define FEDFS_NFS4_DOMAINROOT_RW       "_nfs4._write._domainroot._tcp"
+
+/**
+ * Export path of NFSv4 r/o FedFS root
+ */
+#define FEDFS_NFS4_EXPORTPATH_RO       "/.domainroot"
+
+/**
+ * Export path of NFSv4 r/w FedFS root
+ */
+#define FEDFS_NFS4_EXPORTPATH_RW       "/.domainroot-write"
+
+char *progname;
+
+/**
+ * Display usage message
+ */
+static void
+fedfs_map_usage(void)
+{
+       printf(_("\nUsage: %s [domain]\n\n"), progname);
+
+       printf("%s", fedfs_gpl_boilerplate);
+}
+
+/**
+ * Construct an NFSv4 map entry for "domainname" with one server
+ *
+ * @param si single-entry list of SRV records
+ * @param rw_replica true if a R/W domain root replica was requested
+ * @param domainname NUL-terminated UTF-8 string containing name of FedFS 
domain
+ * @return command exit status
+ */
+static int fedfs_map_nfs4_oneserver(struct srvinfo *si, _Bool rw_replica,
+               const char *domainname)
+{
+       printf("-fstype=nfs,vers=4,fg");
+       if (si->si_port != 2049)
+               printf(",port=%u", si->si_port);
+       printf(" %s:%s-%s\n", si->si_target,
+               rw_replica ? FEDFS_NFS4_EXPORTPATH_RW :
+                            FEDFS_NFS4_EXPORTPATH_RO, domainname);
+       return 0;
+}
+
+/**
+ * Construct an NFSv4 map entry for "domainname" with multiple servers
+ *
+ * @param si list of SRV records for requested FedFS domain
+ * @param rw_replica true if a R/W domain root replica was requested
+ * @param domainname NUL-terminated UTF-8 string containing name of FedFS 
domain
+ * @return command exit status
+ */
+static int fedfs_map_nfs4_replicas(struct srvinfo *si, _Bool rw_replica,
+               const char *domainname)
+{
+       struct srvinfo *cur;
+       unsigned short port;
+       _Bool comma;
+
+       /*
+        * Unfortunately our automounter can't handle a list of
+        * replicas where the various servers live on different
+        * ports from one another.
+        */
+       port = si->si_port;
+       for (cur = si; cur != NULL; cur = cur->si_next)
+               if (cur->si_port != port) {
+                       fprintf(stderr, _("%s: Replicas on different ports not 
supported\n"),
+                               progname);
+                       return 1;
+               }
+
+       if (port != 2049)
+               printf("-fstype=nfs,vers=4,fg,port=%u ", port);
+       else
+               printf("-fstype=nfs,vers=4,fg ");
+
+       /*
+        * Note that the export path is required to be indentical
+        * for all domain root servers for this domain.
+        */
+       for (comma = false, cur = si; cur != NULL; cur = cur->si_next) {
+               if (comma)
+                       printf(",");
+               printf("%s(%u)", cur->si_target, cur->si_weight);
+               comma = true;
+       }
+       printf(":%s-%s\n", rw_replica ? FEDFS_NFS4_EXPORTPATH_RW :
+                    FEDFS_NFS4_EXPORTPATH_RO, domainname);
+
+       return 0;
+}
+
+/**
+ * Construct an NFSv4 map entry for "domainname"
+ *
+ * @param domainname NUL-terminated UTF-8 string containing name of FedFS 
domain
+ * @return command exit status
+ */
+static int fedfs_map_nfs4(const char *domainname)
+{
+       struct srvinfo *cur, *si = NULL;
+       unsigned int count;
+       int error, result;
+       _Bool rw_replica;
+       char *rr;
+
+       rw_replica = false;
+       if (domainname[0] == '.') {
+               rw_replica = true;
+               domainname++;
+       }
+
+       result = 1;
+       rr = rw_replica ? FEDFS_NFS4_DOMAINROOT_RW : FEDFS_NFS4_DOMAINROOT_RO;
+       error = getsrvinfo(rr, domainname, &si);
+       switch (error) {
+       case ESI_SUCCESS:
+               break;
+       case ESI_NONAME:
+               fprintf(stderr, _("%s: Domain name %s not found\n"),
+                       progname, domainname);
+               goto out;
+       case ESI_SERVICE:
+               fprintf(stderr, _("%s: No FedFS domain root available for 
%s\n"),
+                       progname, domainname);
+               goto out;
+       default:
+               fprintf(stderr, _("%s: Failed to resolve %s: %s\n"),
+                       progname, domainname, gsi_strerror(error));
+               goto out;
+       }
+
+       for (count = 0, cur = si; cur != NULL; cur = cur->si_next)
+               count++;
+       if (count == 1)
+               result = fedfs_map_nfs4_oneserver(si, rw_replica,
+                                                               domainname);
+       else
+               result = fedfs_map_nfs4_replicas(si, rw_replica,
+                                                               domainname);
+
+out:
+       freesrvinfo(si);
+       return result;
+}
+
+/**
+ * Program entry point
+ *
+ * @param argc count of command line arguments
+ * @param argv array of NUL-terminated C strings containing command line 
arguments
+ * @return program exit status
+ */
+int main(int argc, char *argv[])
+{
+       /* Ensure UTF-8 strings can be handled transparently */
+       if (setlocale(LC_CTYPE, "") == NULL ||
+           strcmp(nl_langinfo(CODESET), "UTF-8") != 0) {
+               fprintf(stderr, _("Failed to set locale and langinfo\n"));
+               return 1;
+       }
+
+       progname = basename(argv[0]);
+
+       if (argc != 2) {
+               fedfs_map_usage();
+               return 1;
+       }
+
+       if (strcmp(progname, "fedfs-map-nfs4") == 0)
+               return fedfs_map_nfs4(argv[1]);
+#ifdef EXAMPLE
+       /* CIFS support might plug in here */
+       else if (strcmp(progname, "fedfs-map-cifs") == 0)
+               return fedfs_map_cifs(argv[1]);
+#endif
+
+       fprintf(stderr, _("%s: Unsupported file system type\n"), progname);
+       return 1;
+}

_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs

Reply via email to