linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
@ 2018-01-08 21:49 Chuck Lever
  2018-01-08 21:50 ` [PATCH RFC 2/3] Add LDAP-free version of libnfsjunct " Chuck Lever
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Chuck Lever @ 2018-01-08 21:49 UTC (permalink / raw)
  To: linux-nfs

THIS IS AN UNTESTED RFC SERIES. I'm posting this for review only.

A while back I announced the deprecation of fedfs-utils. There were
a handful of components in fedfs-utils that we decided to keep. One
of those keepers was the "nfsref" command. (The other was autofs
support for /nfs4, which I hope Ian Kent is making progress on ;-)

This is an RFC patch series to introduce "nfsref" to nfs-utils,
minus the overhead of the LDAP / FedFS machinery. It also adds a
version of libnfsjunct which mountd can dynamically load to handle
non-FedFS junctions, replacing the same part from fedfs-utils.

I didn't apply a lot of brain cells to this port, so it's perhaps a
little larger than it needs to be. Still, it achieves a completely
LDAP-free implementation. I'm interested in comments about the
approach before I do more testing and refinement.

  ./configure --enable-junction --enable-caps

is needed before building.

Perhaps one thing that can be done is simply getting rid of the DLL
and building junction support into mountd. I'm not sure if a
transition period is necessary where the DLL is retained for a bit
until fedfs-utils is entirely gone. Does anything but mountd use
libnfsjunct ?


---

Chuck Lever (3):
      Add LDAP-free version of libjunction to nfs-utils
      Add LDAP-free version of libnfsjunct to nfs-utils
      Add 'nfsref' command


 aclocal/libxml2.m4                   |   15 
 configure.ac                         |   12 
 support/Makefile.am                  |    4 
 support/include/Makefile.am          |    3 
 support/include/fedfs_admin.h        |  342 +++++++
 support/include/junction.h           |  124 +++
 support/include/nfs-plugin.h         |  101 ++
 support/junction/Makefile.am         |   40 +
 support/junction/display.c           |  159 +++
 support/junction/export-cache.c      |  118 +++
 support/junction/junction-internal.h |  121 +++
 support/junction/junction.c          |  494 +++++++++++
 support/junction/locations.c         |  131 +++
 support/junction/nfs-plugin.c        |  350 ++++++++
 support/junction/nfs.c               | 1564 ++++++++++++++++++++++++++++++++++
 support/junction/path.c              |  345 ++++++++
 support/junction/xml.c               |  401 +++++++++
 utils/Makefile.am                    |    4 
 utils/nfsref/Makefile.am             |   39 +
 utils/nfsref/add.c                   |  271 ++++++
 utils/nfsref/lookup.c                |  211 +++++
 utils/nfsref/nfsref.c                |  188 ++++
 utils/nfsref/nfsref.h                |   47 +
 utils/nfsref/nfsref.man              |  180 ++++
 utils/nfsref/remove.c                |  145 +++
 25 files changed, 5409 insertions(+)
 create mode 100644 aclocal/libxml2.m4
 create mode 100644 support/include/fedfs_admin.h
 create mode 100644 support/include/junction.h
 create mode 100644 support/include/nfs-plugin.h
 create mode 100644 support/junction/Makefile.am
 create mode 100644 support/junction/display.c
 create mode 100644 support/junction/export-cache.c
 create mode 100644 support/junction/junction-internal.h
 create mode 100644 support/junction/junction.c
 create mode 100644 support/junction/locations.c
 create mode 100644 support/junction/nfs-plugin.c
 create mode 100644 support/junction/nfs.c
 create mode 100644 support/junction/path.c
 create mode 100644 support/junction/xml.c
 create mode 100644 utils/nfsref/Makefile.am
 create mode 100644 utils/nfsref/add.c
 create mode 100644 utils/nfsref/lookup.c
 create mode 100644 utils/nfsref/nfsref.c
 create mode 100644 utils/nfsref/nfsref.h
 create mode 100644 utils/nfsref/nfsref.man
 create mode 100644 utils/nfsref/remove.c

--
Chuck Lever

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH RFC 2/3] Add LDAP-free version of libnfsjunct to nfs-utils
  2018-01-08 21:49 [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils Chuck Lever
@ 2018-01-08 21:50 ` Chuck Lever
  2018-01-08 21:50 ` [PATCH RFC 3/3] Add 'nfsref' command Chuck Lever
  2018-01-09 19:21 ` [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils J. Bruce Fields
  2 siblings, 0 replies; 12+ messages in thread
From: Chuck Lever @ 2018-01-08 21:50 UTC (permalink / raw)
  To: linux-nfs

libnfsjunct is a dynamic library that mountd can load to enable
the Linux NFS server to support junctions. This patch moves the
non-LDAP parts of libnfsjunct into nfs-utils. This enables mountd to
continue to recognize and support NFS basic junctions.

mountd works fine whether or not there is a libnfsjunct installed
on the local system, just as it did before. Without libnfsjunct,
junctions on the NFS server appear to NFS clients like weird
directories.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 support/include/Makefile.am   |    1 
 support/include/nfs-plugin.h  |  101 ++++++++++++
 support/junction/Makefile.am  |    6 +
 support/junction/nfs-plugin.c |  350 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 458 insertions(+)
 create mode 100644 support/include/nfs-plugin.h
 create mode 100644 support/junction/nfs-plugin.c

diff --git a/support/include/Makefile.am b/support/include/Makefile.am
index 11cb162..a207d21 100644
--- a/support/include/Makefile.am
+++ b/support/include/Makefile.am
@@ -9,6 +9,7 @@ noinst_HEADERS = \
 	ha-callout.h \
 	junction.h \
 	misc.h \
+	nfs-plugin.h \
 	nfs_mntent.h \
 	nfs_paths.h \
 	nfslib.h \
diff --git a/support/include/nfs-plugin.h b/support/include/nfs-plugin.h
new file mode 100644
index 0000000..33e63f3
--- /dev/null
+++ b/support/include/nfs-plugin.h
@@ -0,0 +1,101 @@
+/*
+ * @file support/include/nfs-plugin.h
+ * @brief Definition of NFS junction plug-in API
+ */
+
+/*
+ * Copyright 2011, 2018 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-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.
+ *
+ * nfs-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 nfs-utils.  If not, see:
+ *
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+/*
+ * The purpose of this API is to provide an opaque mechanism for
+ * the NFS mountd daemon to resolve NFS basic and FedFS junctions.
+ * This interface is therefore quite specific to NFS.
+ */
+
+#ifndef NFS_PLUGIN_H
+#define NFS_PLUGIN_H
+
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+/**
+ * Current version of API
+ */
+#define JP_API_VERSION		(1)
+
+/**
+ * NFS plug-in library soname; passed to dlopen(3)
+ */
+#define JP_NFSPLUGIN_SONAME	"libnfsjunct.so.0"
+
+/**
+ * A set of NFS FS locations
+ */
+struct nfs_fsloc_set;
+typedef struct nfs_fsloc_set	 *nfs_fsloc_set_t;
+
+/**
+ * Junction operation status codes
+ */
+enum jp_status {
+	JP_OK			=  0,
+	JP_INVAL		= -1,
+	JP_ACCESS		= -2,
+	JP_EXIST		= -3,
+	JP_TYPE_NOT_SUPP	= -4,
+	JP_OP_NOT_SUPP		= -5,
+	JP_ISJUNCTION		= -6,
+	JP_NOTJUNCTION		= -7,
+	JP_NSDBLOCAL		= -8,
+	JP_NSDBREMOTE		= -9,
+	JP_MEMORY		= -10,
+	JP_SYSTEM		= -11,
+	JP_PARSE		= -1000,
+	JP_EMPTY		= -1001,
+};
+
+/**
+ * Vector of methods provided by a junction plug-in
+ */
+struct jp_ops {
+	unsigned int	  jp_api_version;
+
+	enum jp_status	  (*jp_init)(_Bool want_debugging);
+	void		  (*jp_done)(void);
+
+	const char *	  (*jp_error)(enum jp_status status);
+	void		  (*jp_put_locations)(nfs_fsloc_set_t locset);
+	enum jp_status	  (*jp_get_locations)(const char *junct_path,
+					nfs_fsloc_set_t *locset);
+	void		  (*jp_rewind_locations)(nfs_fsloc_set_t locset);
+	enum jp_status	  (*jp_get_next_location)(nfs_fsloc_set_t locset,
+					char **hostname, char **export_path,
+					int *ttl);
+};
+
+/**
+ * Load this symbol to get access to the junction API
+ */
+extern struct jp_ops	  nfs_junction_ops;
+
+__END_DECLS
+
+#endif	/* !NFS_PLUGIN_H */
diff --git a/support/junction/Makefile.am b/support/junction/Makefile.am
index 97e7426..9494f55 100644
--- a/support/junction/Makefile.am
+++ b/support/junction/Makefile.am
@@ -29,6 +29,12 @@ noinst_LTLIBRARIES	= libjunction.la
 libjunction_la_SOURCES	= display.c export-cache.c junction.c \
 			  locations.c nfs.c path.c xml.c
 
+lib_LTLIBRARIES		= libnfsjunct.la
+libnfsjunct_la_SOURCES	= nfs-plugin.c
+libnfsjunct_la_LIBADD	= $(LIBXML2) \
+			  ../../support/nfs/libnfs.la \
+			  libjunction.la
+
 MAINTAINERCLEANFILES	= Makefile.in
 
 AM_CPPFLAGS		= -I. -I../include -I/usr/include/libxml2
diff --git a/support/junction/nfs-plugin.c b/support/junction/nfs-plugin.c
new file mode 100644
index 0000000..61039ca
--- /dev/null
+++ b/support/junction/nfs-plugin.c
@@ -0,0 +1,350 @@
+/**
+ * @file support/junction/nfs-plugin.c
+ * @brief DLL to resolve junction information
+ */
+
+/*
+ * Copyright 2011, 2018 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-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.
+ *
+ * nfs-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 nfs-utils.  If not, see:
+ *
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <libxml/parser.h>
+
+#include "fedfs_admin.h"
+#include "nfs-plugin.h"
+#include "junction.h"
+
+#define VERSION			"0.12.0"
+#define FEDFS_NFS_BASIC_TTL	(300)
+
+struct nfs_fsloc_set {
+	int			  ns_ttl;
+	struct nfs_fsloc	 *ns_current;
+	struct nfs_fsloc	 *ns_list;
+};
+
+static _Bool debug = false;
+
+/**
+ * Write a debugging message to stderr
+ *
+ * @param fmt NUL-terminated C string containing output format specification
+ *
+ * NB:	Caller may have already opened syslog for her own use.  We can't
+ *	hijack it here, so using xlog() is right out.  Thus output is
+ *	directed to stderr via fprintf(3).
+ */
+static void
+nfs_jp_debug(const char *fmt, ...)
+{
+	va_list args;
+
+	if (!debug)
+		return;
+
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	va_end(args);
+}
+
+/**
+ * Perform any plug-in startup processing
+ *
+ * @param want_debugging true if caller wants to enable debugging output
+ * @return a junction status code
+ */
+static enum jp_status
+nfs_jp_init(_Bool want_debugging)
+{
+	debug = want_debugging;
+	nfs_jp_debug("%s: Junction plug-in version " VERSION "\n", __func__);
+	xmlInitParser();
+	return JP_OK;
+}
+
+/**
+ * Perform any plug-in shutdown processing
+ *
+ * Nothing to be done for NFS junctions.
+ */
+static void
+nfs_jp_done(void)
+{
+	nfs_jp_debug("%s: Finishing\n", __func__);
+	xmlCleanupParser();
+	return;
+}
+
+/**
+ * Given an status code, return a pointer to a static error message
+ *
+ * @param status a junction plug-in status code
+ * @return a static NUL-terminated string
+ */
+static const char *
+nfs_jp_error(enum jp_status status)
+{
+	static char buf[128];
+
+	switch (status) {
+	case JP_OK:
+		return "Success";
+	case JP_INVAL:
+		return "Invalid parameter";
+	case JP_ACCESS:
+		return "Permission denied";
+	case JP_EXIST:
+		return "Object cannot be made into a junction";
+	case JP_TYPE_NOT_SUPP:
+		return "Junction type not supported";
+	case JP_OP_NOT_SUPP:
+		return "Junction method not supported";
+	case JP_ISJUNCTION:
+		return "Object is a junction";
+	case JP_NOTJUNCTION:
+		return "Object is not a junction";
+	case JP_NSDBLOCAL:
+		return "A local NSDB configuration error occurred";
+	case JP_NSDBREMOTE:
+		return "An error occurred on the NSDB";
+	case JP_MEMORY:
+		return "Memory allocation failure";
+	case JP_SYSTEM:
+		snprintf(buf, sizeof(buf), "System error (%d): %s",
+				status, strerror(errno));
+		return buf;
+	case JP_PARSE:
+		return "Failed to parse locations data";
+	case JP_EMPTY:
+		return "No more locations in location set";
+	}
+
+	snprintf(buf, sizeof(buf), "Unknown error (%d)", status);
+	return buf;
+}
+
+/**
+ * Release a set of NFS locations
+ *
+ * @param locset set of NFS locations to release
+ */
+static void
+nfs_jp_put_locations(nfs_fsloc_set_t locset)
+{
+	if (locset == NULL) {
+		nfs_jp_debug("%s: Invalid parameters\n", __func__);
+		return;
+	}
+
+	nfs_jp_debug("%s: Freeing location set %p, ns_list=%p\n",
+		__func__, locset, locset->ns_list);
+	nfs_free_locations(locset->ns_list);
+	free(locset);
+}
+
+/**
+ * Internal function to allocate a set of NFS locations
+ *
+ * @return dynamically allocated nfs_fsloc_set_t object
+ *
+ * If return value is non-NULL, caller must free it with
+ * nfs_jp_put_locations().
+ */
+__attribute_malloc__
+static nfs_fsloc_set_t
+nfs_jp_alloc_locations(void)
+{
+	return calloc(1, sizeof(struct nfs_fsloc_set));
+}
+
+/**
+ * Internal function to rewind a set of locations
+ *
+ * @param locset set of NFS locations to rewind
+ */
+static void
+nfs_jp_do_rewind_locations(nfs_fsloc_set_t locset)
+{
+	locset->ns_current = locset->ns_list;
+}
+
+/**
+ * Resolve NFS basic junction information into a set of NFS locations
+ *
+ * @param junct_path NUL-terminated C string containing POSIX path of junction
+ * @param locset OUT set of NFS locations
+ * @return a junction status code
+ *
+ * If this entry point returns JP_OK, the caller must free the returned
+ * set of locations by calling the jp_put_locations entry point.
+ */
+static enum jp_status
+nfs_jp_get_basic(const char *junct_path, nfs_fsloc_set_t *locset)
+{
+	nfs_fsloc_set_t new;
+	FedFsStatus retval;
+
+	new = nfs_jp_alloc_locations();
+	if (new == NULL) {
+		nfs_jp_debug("%s: No memory\n", __func__);
+		return JP_MEMORY;
+	}
+
+	retval = nfs_get_locations(junct_path, &new->ns_list);
+	if (retval != FEDFS_OK) {
+		nfs_jp_debug("%s: Failed to get locations: %s\n",
+			__func__, nsdb_display_fedfsstatus(retval));
+		nfs_jp_put_locations(new);
+		return JP_PARSE;
+	}
+
+	nfs_jp_debug("%s: Returning location set %p\n", __func__, new);
+	nfs_jp_do_rewind_locations(new);
+	new->ns_ttl = FEDFS_NFS_BASIC_TTL;
+	*locset = new;
+	return JP_OK;
+}
+
+/**
+ * Resolve junction information into a set of NFS locations
+ *
+ * @param junct_path NUL-terminated C string containing POSIX path of junction
+ * @param locset OUT set of NFS locations
+ * @return a junction status code
+ *
+ * If this entry point returns JP_OK, the caller must free the returned
+ * set of locations by calling the jp_put_locations entry point.
+ */
+static enum jp_status
+nfs_jp_get_locations(const char *junct_path, nfs_fsloc_set_t *locset)
+{
+	FedFsStatus retval;
+
+	if (junct_path == NULL || locset == NULL) {
+		nfs_jp_debug("%s: Invalid parameters\n", __func__);
+		return JP_INVAL;
+	}
+	nfs_jp_debug("%s: %s\n", __func__, junct_path);
+
+	retval = nfs_is_junction(junct_path);
+	if (retval == FEDFS_OK)
+		return nfs_jp_get_basic(junct_path, locset);
+
+	nfs_jp_debug("%s: Not a junction\n", __func__);
+	return JP_NOTJUNCTION;
+}
+
+/**
+ * Reset the current location to the first location in the list
+ *
+ * @param locset set of NFS locations
+ */
+static void
+nfs_jp_rewind_locations(nfs_fsloc_set_t locset)
+{
+	if (locset == NULL) {
+		nfs_jp_debug("%s: Invalid parameters\n", __func__);
+		return;
+	}
+
+	nfs_jp_debug("%s: Rewinding %p\n", __func__, locset);
+	nfs_jp_do_rewind_locations(locset);
+}
+
+/**
+ * Get the fileserver hostname and export path from the next location in the set
+ *
+ * @param locset set of NFS locations
+ * @param hostname OUT NUL-terminated C string containing hostname of fileserver
+ * @param export_path OUT NUL-terminated C string containing export path
+ * @param ttl OUT cache time-to-live, in seconds
+ * @return a junction status code
+ *
+ * If this entry point returns JP_OK, the caller must free the hostname
+ * and export_path strings with free(3).
+ */
+static enum jp_status
+nfs_jp_get_next_location(nfs_fsloc_set_t locset,
+		char **hostname, char **export_path, int *ttl)
+{
+	char *hostname_tmp, *export_path_tmp;
+	struct nfs_fsloc *fsloc;
+
+	if (locset == NULL || hostname == NULL ||
+	    export_path == NULL || ttl == NULL) {
+		nfs_jp_debug("%s: Invalid parameters\n", __func__);
+		return JP_INVAL;
+	}
+	nfs_jp_debug("%s: locset=%p, ns_current=%p, ns_list=%p\n",
+		__func__, locset, locset->ns_current, locset->ns_list);
+
+	if (locset->ns_current == NULL) {
+		nfs_jp_debug("%s: No locations\n", __func__);
+		return JP_EMPTY;
+	}
+	fsloc = locset->ns_current;
+
+	hostname_tmp = strdup(fsloc->nfl_hostname);
+	if (hostname_tmp == NULL) {
+		nfs_jp_debug("%s: No memory\n", __func__);
+		return JP_MEMORY;
+	}
+
+	if (nsdb_path_array_to_posix(fsloc->nfl_rootpath,
+					&export_path_tmp) != FEDFS_OK) {
+		free(hostname_tmp);
+		nfs_jp_debug("%s: Failed to parse\n", __func__);
+		return JP_PARSE;
+	}
+
+	nfs_jp_debug("%s: Success; hostname=%s path=%s\n",
+		__func__, hostname_tmp, export_path_tmp);
+	*hostname = hostname_tmp;
+	*export_path = export_path_tmp;
+	*ttl = locset->ns_ttl;
+	locset->ns_current = locset->ns_current->nfl_next;
+	return JP_OK;
+}
+
+/**
+ * Vector of methods provided by this plug-in
+ */
+struct jp_ops nfs_junction_ops = {
+	.jp_api_version		= JP_API_VERSION,
+	.jp_init		= nfs_jp_init,
+	.jp_done		= nfs_jp_done,
+	.jp_error		= nfs_jp_error,
+	.jp_put_locations	= nfs_jp_put_locations,
+	.jp_get_locations	= nfs_jp_get_locations,
+	.jp_rewind_locations	= nfs_jp_rewind_locations,
+	.jp_get_next_location	= nfs_jp_get_next_location,
+};


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH RFC 3/3] Add 'nfsref' command
  2018-01-08 21:49 [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils Chuck Lever
  2018-01-08 21:50 ` [PATCH RFC 2/3] Add LDAP-free version of libnfsjunct " Chuck Lever
@ 2018-01-08 21:50 ` Chuck Lever
  2018-01-09 19:21 ` [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils J. Bruce Fields
  2 siblings, 0 replies; 12+ messages in thread
From: Chuck Lever @ 2018-01-08 21:50 UTC (permalink / raw)
  To: linux-nfs

The 'nfsref' command administers junctions. On an NFS server, it
can create new junctions, remove existing junctions, or display
the contents of junctions.

A man page with more details is included.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 configure.ac             |    1 
 utils/Makefile.am        |    4 +
 utils/nfsref/Makefile.am |   39 +++++++
 utils/nfsref/add.c       |  271 ++++++++++++++++++++++++++++++++++++++++++++++
 utils/nfsref/lookup.c    |  211 ++++++++++++++++++++++++++++++++++++
 utils/nfsref/nfsref.c    |  188 ++++++++++++++++++++++++++++++++
 utils/nfsref/nfsref.h    |   47 ++++++++
 utils/nfsref/nfsref.man  |  180 +++++++++++++++++++++++++++++++
 utils/nfsref/remove.c    |  145 +++++++++++++++++++++++++
 9 files changed, 1086 insertions(+)
 create mode 100644 utils/nfsref/Makefile.am
 create mode 100644 utils/nfsref/add.c
 create mode 100644 utils/nfsref/lookup.c
 create mode 100644 utils/nfsref/nfsref.c
 create mode 100644 utils/nfsref/nfsref.h
 create mode 100644 utils/nfsref/nfsref.man
 create mode 100644 utils/nfsref/remove.c

diff --git a/configure.ac b/configure.ac
index 8e7f036..59199f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -604,6 +604,7 @@ AC_CONFIG_FILES([
 	utils/mount/Makefile
 	utils/mountd/Makefile
 	utils/nfsd/Makefile
+	utils/nfsref/Makefile
 	utils/nfsstat/Makefile
 	utils/nfsidmap/Makefile
 	utils/showmount/Makefile
diff --git a/utils/Makefile.am b/utils/Makefile.am
index c75a5a0..d361aea 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -23,6 +23,10 @@ if CONFIG_NFSDCLTRACK
 OPTDIRS += nfsdcltrack
 endif
 
+if CONFIG_JUNCTION
+OPTDIRS += nfsref
+endif
+
 SUBDIRS = \
 	exportfs \
 	mountd \
diff --git a/utils/nfsref/Makefile.am b/utils/nfsref/Makefile.am
new file mode 100644
index 0000000..2b2bb53
--- /dev/null
+++ b/utils/nfsref/Makefile.am
@@ -0,0 +1,39 @@
+##
+## @file utils/nfsref/Makefile.am
+## @brief Process this file with automake to produce utils/nfsref/Makefile.in
+##
+
+##
+## Copyright 2011, 2018 Oracle.  All rights reserved.
+##
+## This file is part of nfs-utils.
+##
+## nfs-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.
+##
+## nfs-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 nfs-utils.  If not, see:
+##
+##	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+##
+
+noinst_HEADERS		= nfsref.h
+
+sbin_PROGRAMS		= nfsref
+nfsref_SOURCES		= add.c lookup.c nfsref.c remove.c
+LDADD			= $(LIBXML2) $(LIBCAP) \
+			  ../../support/nfs/libnfs.la \
+			  ../../support/junction/libjunction.la
+
+man8_MANS		= nfsref.man
+
+MAINTAINERCLEANFILES	= Makefile.in
+
+AM_CPPFLAGS		= -I. -I../../support/include
+##AM_LDFLAGS		= -Wl,--as-needed
diff --git a/utils/nfsref/add.c b/utils/nfsref/add.c
new file mode 100644
index 0000000..d5d0cf8
--- /dev/null
+++ b/utils/nfsref/add.c
@@ -0,0 +1,271 @@
+/**
+ * @file utils/nfsref/add.c
+ * @brief Add junction metadata to a local file system object
+ */
+
+/*
+ * Copyright 2011, 2018 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-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.
+ *
+ * nfs-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 nfs-utils.  If not, see:
+ *
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <uuid/uuid.h>
+
+#include "junction.h"
+#include "xlog.h"
+#include "nfsref.h"
+
+/**
+ * Default cache expiration for FSN information
+ */
+#define FSN_DEFAULT_TTL		(300)
+
+/**
+ * Display help message for "add" subcommand
+ *
+ * @param progname NUL-terminated C string containing name of program
+ * @return program exit status
+ */
+int
+nfsref_add_help(const char *progname)
+{
+	fprintf(stderr, " \n");
+
+	fprintf(stderr, "Usage: %s [ -t type ] add <junction path> "
+			"<server> <export> [ <server> <export> ... ]\n\n",
+		progname);
+
+	fprintf(stderr, "Add a new junction containing the specified list "
+			"of fileset locations.\n");
+	fprintf(stderr, "<junction path> is the filename of the new junction.  "
+			"<server> is the hostname\n");
+	fprintf(stderr, "or IP address of an NFS server where the fileset is "
+			"located.  <export> is the\n");
+	fprintf(stderr, "export pathname of the fileset on that server.\n\n");
+
+	fprintf(stderr, "For NFS basic junctions, the location list is stored "
+			"locally in the junction.\n");
+	fprintf(stderr, "For FedFS junctions, the location list is stored "
+			"as new FSN and FSL records\n");
+	fprintf(stderr, "on an NSDB.\n");
+
+	return EXIT_SUCCESS;
+}
+
+/**
+ * Fill in default settings for NFSv4.0 fs_locations4
+ *
+ * @param new NFS location structure to fill in
+ *
+ * See section 5.1.3.2 of the NSDB protocol draft.
+ */
+static void
+nfsref_add_fsloc_defaults(struct nfs_fsloc *new)
+{
+	new->nfl_hostport = 0;
+	new->nfl_flags.nfl_varsub = false;
+	new->nfl_currency = -1;
+	new->nfl_validfor = 0;
+	new->nfl_genflags.nfl_writable = false;
+	new->nfl_genflags.nfl_going = false;
+	new->nfl_genflags.nfl_split = true;
+	new->nfl_transflags.nfl_rdma = true;
+	new->nfl_info.nfl_simul = 0;
+	new->nfl_info.nfl_handle = 0;
+	new->nfl_info.nfl_fileid = 0;
+	new->nfl_info.nfl_writever = 0;
+	new->nfl_info.nfl_change = 0;
+	new->nfl_info.nfl_readdir = 0;
+	new->nfl_info.nfl_readrank = 0;
+	new->nfl_info.nfl_readorder = 0;
+	new->nfl_info.nfl_writerank = 0;
+	new->nfl_info.nfl_writeorder = 0;
+}
+
+/**
+ * Convert a pair of command line arguments to one nfs_fsloc structure
+ *
+ * @param server NUL-terminated C string containing file server hostname
+ * @param rootpath NUL-terminated C string containing POSIX-style export path
+ * @param fsloc OUT: NFS location structure
+ * @return a FedFsStatus code
+ *
+ * If nfsref_add_build_fsloc() returns FEDFS_OK, caller must free the
+ * returned fsloc with nfs_free_location().
+ */
+static FedFsStatus
+nfsref_add_build_fsloc(const char *server, const char *rootpath,
+		struct nfs_fsloc **fsloc)
+{
+	struct nfs_fsloc *new;
+	FedFsStatus retval;
+
+	if (server == NULL || rootpath == NULL)
+		return FEDFS_ERR_INVAL;
+
+	xlog(D_GENERAL, "%s: Building fsloc for %s:%s",
+		__func__, server, rootpath);
+
+	new = nfs_new_location();
+	if (new == NULL) {
+		xlog(D_GENERAL, "%s: No memory", __func__);
+		return FEDFS_ERR_SVRFAULT;
+	}
+
+	new->nfl_hostname = strdup(server);
+	if (new->nfl_hostname == NULL) {
+		nfs_free_location(new);
+		xlog(D_GENERAL, "%s: No memory", __func__);
+		return FEDFS_ERR_SVRFAULT;
+	}
+
+	retval = nsdb_posix_to_path_array(rootpath, &new->nfl_rootpath);
+	if (retval != FEDFS_OK) {
+		nfs_free_location(new);
+		return retval;
+	}
+
+	nfsref_add_fsloc_defaults(new);
+	*fsloc = new;
+	return FEDFS_OK;
+}
+
+/**
+ * Convert array of command line arguments to list of nfs_fsloc structures
+ *
+ * @param argv array of pointers to NUL-terminated C strings contains arguments
+ * @param optind index of "argv" where "add" subcommand arguments start
+ * @param fslocs OUT: list of NFS locations
+ * @return a FedFsStatus code
+ *
+ * If nfsref_add_build_fsloc_list() returns FEDFS_OK, caller must free the
+ * returned list of fslocs with nfs_free_locations().
+ */
+static FedFsStatus
+nfsref_add_build_fsloc_list(char **argv, int optind, struct nfs_fsloc **fslocs)
+{
+	struct nfs_fsloc *fsloc, *result = NULL;
+	FedFsStatus retval;
+	int i;
+
+	for (i = optind + 2; argv[i] != NULL; i += 2) {
+		retval = nfsref_add_build_fsloc(argv[i], argv[i + 1], &fsloc);
+		if (retval != FEDFS_OK) {
+			nfs_free_locations(result);
+			return retval;
+		}
+		if (result == NULL)
+			result = fsloc;
+		else
+			result->nfl_next = fsloc;
+	}
+	if (result == NULL)
+		return FEDFS_ERR_INVAL;
+
+	*fslocs = result;
+	return FEDFS_OK;
+}
+
+/**
+ * Add NFS locations to a junction
+ *
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @param argv array of pointers to NUL-terminated C strings contains arguments
+ * @param optind index of "argv" where "add" subcommand arguments start
+ * @return program exit status
+ */
+static int
+nfsref_add_nfs_basic(const char *junct_path, char **argv, int optind)
+{
+	struct nfs_fsloc *fslocs = NULL;
+	FedFsStatus retval;
+
+	xlog(D_GENERAL, "%s: Adding basic junction to %s",
+		__func__, junct_path);
+
+	retval = nfsref_add_build_fsloc_list(argv, optind, &fslocs);
+	switch (retval) {
+	case FEDFS_OK:
+		break;
+	case FEDFS_ERR_INVAL:
+		xlog(L_ERROR, "Missing arguments");
+		return EXIT_FAILURE;
+	case FEDFS_ERR_SVRFAULT:
+		xlog(L_ERROR, "No memory");
+		return EXIT_FAILURE;
+	default:
+		xlog(L_ERROR, "Failed to add NFS location metadata to %s: %s",
+			junct_path, nsdb_display_fedfsstatus(retval));
+		return EXIT_FAILURE;
+	}
+
+	retval = nfs_add_junction(junct_path, fslocs);
+	nfs_free_locations(fslocs);
+	switch (retval) {
+	case FEDFS_OK:
+		break;
+	case FEDFS_ERR_EXIST:
+		xlog(L_ERROR, "%s already contains junction metadata",
+			junct_path);
+		return EXIT_FAILURE;
+	default:
+		xlog(L_ERROR, "Failed to add NFS location metadata to %s: %s",
+			junct_path, nsdb_display_fedfsstatus(retval));
+		return EXIT_FAILURE;
+	}
+
+	printf("Created junction %s\n", junct_path);
+	return EXIT_SUCCESS;
+}
+
+/**
+ * Add locations to a junction
+ *
+ * @param type type of junction to add
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @param argv array of pointers to NUL-terminated C strings contains arguments
+ * @param optind index of "argv" where "add" subcommand arguments start
+ * @return program exit status
+ */
+int
+nfsref_add(enum nfsref_type type, const char *junct_path, char **argv, int optind)
+{
+	if (mkdir(junct_path, 0755) == -1)
+		if (errno != EEXIST) {
+			xlog(L_ERROR, "Failed to create junction object: %m");
+			return EXIT_FAILURE;
+		}
+
+	switch (type) {
+	case NFSREF_TYPE_UNSPECIFIED:
+	case NFSREF_TYPE_NFS_BASIC:
+		return nfsref_add_nfs_basic(junct_path, argv, optind);
+	default:
+		xlog(L_ERROR, "Unrecognized junction type");
+	}
+	return EXIT_FAILURE;
+}
diff --git a/utils/nfsref/lookup.c b/utils/nfsref/lookup.c
new file mode 100644
index 0000000..16fca2e
--- /dev/null
+++ b/utils/nfsref/lookup.c
@@ -0,0 +1,211 @@
+/**
+ * @file utils/nfsref/lookup.c
+ * @brief Examine junction metadata from a local file system object
+ */
+
+/*
+ * Copyright 2011, 2018 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-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.
+ *
+ * nfs-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 nfs-utils.  If not, see:
+ *
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <rpcsvc/nfs_prot.h>
+
+#include "junction.h"
+#include "xlog.h"
+#include "nfsref.h"
+
+/**
+ * Display help message for "lookup" subcommand
+ *
+ * @param progname NUL-terminated C string containing name of program
+ * @return program exit status
+ */
+int
+nfsref_lookup_help(const char *progname)
+{
+	fprintf(stderr, " \n");
+
+	fprintf(stderr, "Usage: %s [ -t type ] lookup <junction path>\n\n",
+		progname);
+
+	fprintf(stderr, "Display the contents of the junction at "
+			"<junction path>.  For NFS basic\n");
+	fprintf(stderr, "junctions, the local contents of the junction "
+			"are displayed.  For FedFS\n");
+	fprintf(stderr, "junctions, FSL records are retrieved from the "
+			"NSDB and displayed.\n");
+
+	return EXIT_SUCCESS;
+}
+
+/**
+ * Convert a boolean value into a displayable string constant
+ *
+ * @param value boolean value
+ * @return NUL-terminated static constant C string
+ */
+static const char *
+nfsref_lookup_display_boolean(_Bool value)
+{
+	return value ? "true" : "false";
+}
+
+/**
+ * Display a single NFS location
+ *
+ * @param fsloc pointer to an NFS location structure
+ */
+static void
+nfsref_lookup_display_nfs_location(struct nfs_fsloc *fsloc)
+{
+	char *rootpath;
+
+	if (nsdb_path_array_to_posix(fsloc->nfl_rootpath, &rootpath) == FEDFS_OK) {
+		printf("%s:%s\n", fsloc->nfl_hostname, rootpath);
+		free(rootpath);
+	} else
+		printf("%s: - Invalid root path -\n", fsloc->nfl_hostname);
+	printf("\n");
+
+	printf("\tNFS port:\t%u\n", fsloc->nfl_hostport);
+	printf("\tValid for:\t%d\n", fsloc->nfl_validfor);
+	printf("\tCurrency:\t%d\n", fsloc->nfl_currency);
+	printf("\tFlags:\t\tvarsub(%s)\n",
+		nfsref_lookup_display_boolean(fsloc->nfl_flags.nfl_varsub));
+
+	printf("\tGenFlags:\twritable(%s), going(%s), split(%s)\n",
+		nfsref_lookup_display_boolean(fsloc->nfl_genflags.nfl_writable),
+		nfsref_lookup_display_boolean(fsloc->nfl_genflags.nfl_going),
+		nfsref_lookup_display_boolean(fsloc->nfl_genflags.nfl_split));
+	printf("\tTransFlags:\trdma(%s)\n",
+		nfsref_lookup_display_boolean(fsloc->nfl_transflags.nfl_rdma));
+
+	printf("\tClass:\t\tsimul(%u), handle(%u), fileid(%u)\n",
+		fsloc->nfl_info.nfl_simul,
+		fsloc->nfl_info.nfl_handle,
+		fsloc->nfl_info.nfl_fileid);
+	printf("\tClass:\t\twritever(%u), change(%u), readdir(%u)\n",
+		fsloc->nfl_info.nfl_writever,
+		fsloc->nfl_info.nfl_change,
+		fsloc->nfl_info.nfl_readdir);
+	printf("\tRead:\t\trank(%u), order(%u)\n",
+		fsloc->nfl_info.nfl_readrank, fsloc->nfl_info.nfl_readorder);
+	printf("\tWrite:\t\trank(%u), order(%u)\n",
+		fsloc->nfl_info.nfl_writerank, fsloc->nfl_info.nfl_writeorder);
+
+	printf("\n");
+}
+
+/**
+ * Display a list of NFS locations
+ *
+ * @param fslocs list of NFS locations to display
+ */
+static void
+nfsref_lookup_display_nfs_locations(struct nfs_fsloc *fslocs)
+{
+	struct nfs_fsloc *fsloc;
+
+	for (fsloc = fslocs; fsloc != NULL; fsloc = fsloc->nfl_next)
+		nfsref_lookup_display_nfs_location(fsloc);
+}
+
+/**
+ * List NFS locations in an nfs-basic junction
+ *
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @return program exit status
+ */
+static int
+nfsref_lookup_nfs_basic(const char *junct_path)
+{
+	struct nfs_fsloc *fslocs = NULL;
+	FedFsStatus retval;
+
+	xlog(D_GENERAL, "%s: Looking up basic junction in %s",
+		__func__, junct_path);
+
+	retval = nfs_is_junction(junct_path);
+	switch (retval) {
+	case FEDFS_OK:
+		break;
+	case FEDFS_ERR_NOTJUNCT:
+		xlog(L_ERROR, "%s is not an nfs-basic junction", junct_path);
+		return EXIT_FAILURE;
+	default:
+		xlog(L_ERROR, "Failed to access %s: %s",
+			junct_path, nsdb_display_fedfsstatus(retval));
+		return EXIT_FAILURE;
+	}
+
+	retval = nfs_get_locations(junct_path, &fslocs);
+	if (retval != FEDFS_OK) {
+		xlog(L_ERROR, "Failed to access %s: %s",
+			junct_path, nsdb_display_fedfsstatus(retval));
+		return EXIT_FAILURE;
+	}
+
+	nfsref_lookup_display_nfs_locations(fslocs);
+
+	nfs_free_locations(fslocs);
+	return EXIT_SUCCESS;
+}
+
+/**
+ * Resolve either a FedFS or NFS basic junction
+ *
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @return program exit status
+ */
+static int
+nfsref_lookup_unspecified(const char *junct_path)
+{
+	FedFsStatus retval;
+
+	retval = nfs_is_junction(junct_path);
+	if (retval == FEDFS_OK)
+		return nfsref_lookup_nfs_basic(junct_path);
+	xlog(L_ERROR, "%s is not a junction", junct_path);
+	return EXIT_FAILURE;
+}
+
+/**
+ * Enumerate metadata of a junction
+ *
+ * @param type type of junction to add
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @return program exit status
+ */
+int
+nfsref_lookup(enum nfsref_type type, const char *junct_path)
+{
+	switch (type) {
+	case NFSREF_TYPE_UNSPECIFIED:
+		return nfsref_lookup_unspecified(junct_path);
+	case NFSREF_TYPE_NFS_BASIC:
+		return nfsref_lookup_nfs_basic(junct_path);
+	default:
+		xlog(L_ERROR, "Unrecognized junction type");
+	}
+	return EXIT_FAILURE;
+}
diff --git a/utils/nfsref/nfsref.c b/utils/nfsref/nfsref.c
new file mode 100644
index 0000000..ff7013e
--- /dev/null
+++ b/utils/nfsref/nfsref.c
@@ -0,0 +1,188 @@
+/**
+ * @file utils/nfsref/nfsref.c
+ * @brief Manage NFS referrals
+ */
+
+/*
+ * Copyright 2011, 2018 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-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.
+ *
+ * nfs-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 nfs-utils.  If not, see:
+ *
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+#include <sys/types.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <time.h>
+
+#include <locale.h>
+#include <langinfo.h>
+
+#include "junction.h"
+#include "xlog.h"
+#include "nfsref.h"
+
+/**
+ * Short form command line options
+ */
+static const char nfsref_opts[] = "?dt:";
+
+/**
+ * Long form command line options
+ */
+static const struct option nfsref_longopts[] = {
+	{ "debug", 0, NULL, 'd', },
+	{ "help", 0, NULL, '?', },
+	{ "type", 1, NULL, 't', },
+	{ NULL, 0, NULL, 0, },
+};
+
+/**
+ * Display program synopsis
+ *
+ * @param progname NUL-terminated C string containing name of program
+ */
+static void
+nfsref_usage(const char *progname)
+{
+	fprintf(stderr, "Usage: %s [ -t type ] SUBCOMMAND [ ARGUMENTS ]\n\n",
+		progname);
+
+	fprintf(stderr, "SUBCOMMAND is one of:\n");
+	fprintf(stderr, "\tadd        Add a new junction\n");
+	fprintf(stderr, "\tremove     Remove an existing junction\n");
+	fprintf(stderr, "\tlookup     Enumerate a junction\n");
+
+	fprintf(stderr, "\nUse \"%s SUBCOMMAND -?\" for details.\n", progname);
+}
+
+/**
+ * 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)
+{
+	char *progname, *subcommand, *junct_path;
+	enum nfsref_type type;
+	int arg, exit_status;
+	_Bool help;
+
+	(void)setlocale(LC_ALL, "");
+	(void)umask(S_IWGRP | S_IWOTH);
+
+	exit_status = EXIT_FAILURE;
+
+	/* Set the basename */
+	if ((progname = strrchr(argv[0], '/')) != NULL)
+		progname++;
+	else
+		progname = argv[0];
+
+	xlog_stderr(1);
+	xlog_syslog(0);
+	xlog_open(progname);
+
+	if (argc < 2) {
+		nfsref_usage(progname);
+		goto out;
+	}
+
+	help = false;
+	type = NFSREF_TYPE_UNSPECIFIED;
+	while ((arg = getopt_long(argc, argv, nfsref_opts,
+			nfsref_longopts, NULL)) != -1) {
+		switch (arg) {
+		case 'd':
+			xlog_config(D_ALL, 1);
+			break;
+		case 't':
+			if (strcmp(optarg, "nfs-basic") == 0)
+				type = NFSREF_TYPE_NFS_BASIC;
+			else if (strcmp(optarg, "nfs-fedfs") == 0)
+				type = NFSREF_TYPE_NFS_FEDFS;
+			else {
+				xlog(L_ERROR,
+					"Unrecognized junction type: %s",
+					optarg);
+				exit(EXIT_FAILURE);
+			}
+			break;
+		case '?':
+			help = true;
+		}
+	}
+
+	if (argc < optind + 1) {
+		nfsref_usage(progname);
+		goto out;
+	}
+
+	if (!help && geteuid() != 0) {
+		xlog(L_ERROR, "Root permission is required");
+		goto out;
+	}
+
+	subcommand = argv[optind];
+	junct_path = argv[optind + 1];
+
+	if (strcasecmp(subcommand, "add") == 0) {
+		if (help) {
+			exit_status = nfsref_add_help(progname);
+			goto out;
+		}
+		if (argc < optind + 3) {
+			xlog(L_ERROR, "Not enough positional parameters");
+			nfsref_usage(progname);
+			goto out;
+		}
+		exit_status = nfsref_add(type, junct_path, argv, optind);
+		if (exit_status == EXIT_SUCCESS)
+			(void)junction_flush_exports_cache();
+	} else if (strcasecmp(subcommand, "remove") == 0) {
+		if (help) {
+			exit_status = nfsref_remove_help(progname);
+			goto out;
+		}
+		exit_status = nfsref_remove(type, junct_path);
+		if (exit_status == EXIT_SUCCESS)
+			(void)junction_flush_exports_cache();
+	} else if (strcasecmp(subcommand, "lookup") == 0) {
+		if (help) {
+			exit_status = nfsref_lookup_help(progname);
+			goto out;
+		}
+		exit_status = nfsref_lookup(type, junct_path);
+	} else {
+		xlog(L_ERROR, "Unrecognized subcommand: %s", subcommand);
+		nfsref_usage(progname);
+	}
+
+out:
+	exit(exit_status);
+}
diff --git a/utils/nfsref/nfsref.h b/utils/nfsref/nfsref.h
new file mode 100644
index 0000000..e9dd9ae
--- /dev/null
+++ b/utils/nfsref/nfsref.h
@@ -0,0 +1,47 @@
+/**
+ * @file src/nfsref/nfsref.h
+ * @brief Declarations and definitions for nfsref command line tool
+ */
+
+/*
+ * 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
+ */
+
+#ifndef FEDFS_NFSREF_H
+#define FEDFS_NFSREF_H
+
+/**
+ * Junction types supported by the "nfsref" command
+ */
+enum nfsref_type {
+	NFSREF_TYPE_UNSPECIFIED = 1,
+	NFSREF_TYPE_NFS_BASIC,
+	NFSREF_TYPE_NFS_FEDFS
+};
+
+int	 nfsref_add(enum nfsref_type type, const char *junct_path, char **argv,
+				int optind);
+int	 nfsref_remove(enum nfsref_type type, const char *junct_path);
+int	 nfsref_lookup(enum nfsref_type type, const char *junct_path);
+
+int	 nfsref_add_help(const char *progname);
+int	 nfsref_remove_help(const char *progname);
+int	 nfsref_lookup_help(const char *progname);
+
+#endif	/* !FEDFS_NFSREF_H */
diff --git a/utils/nfsref/nfsref.man b/utils/nfsref/nfsref.man
new file mode 100644
index 0000000..1261549
--- /dev/null
+++ b/utils/nfsref/nfsref.man
@@ -0,0 +1,180 @@
+.\"@(#)nfsref.8"
+.\"
+.\" @file utils/nfsref/nfsref.man
+.\" @brief man page for nfsref command
+.\"
+
+.\"
+.\" Copyright 2011, 2018 Oracle.  All rights reserved.
+.\"
+.\" This file is part of nfs-utils.
+.\"
+.\" nfs-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.
+.\"
+.\" nfs-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 nfs-utils.  If not, see:
+.\"
+.\"	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+.\"
+.TH NFSREF 8 "9 Jan 2018"
+.SH NAME
+nfsref \- manage NFS referrals
+.SH SYNOPSIS
+.B nfsref
+.RB [ \-?d ]
+.RB [ \-t
+.IB type ]
+.B add
+.I pathname server export
+.RI [ " server"
+.IR export " ... ]"
+.P
+.B nfsref
+.RB [ \-?d ]
+.RB [ \-t
+.IB type ]
+.B remove
+.I pathname
+.P
+.B nfsref
+.RB [ \-?d ]
+.RB [ \-t
+.IB type ]
+.B lookup
+.I pathname
+.SH INTRODUCTION
+NFS version 4 introduces the concept of
+.I file system referrals
+to NFS.
+A file system referral is like a symbolic link on a file server
+to another file system share, possibly on another file server.
+On an NFS client, a referral behaves like an automounted directory.
+The client, under the server's direction, mounts a new NFS export
+automatically when an application first accesses that directory.
+.P
+Referrals are typically used to construct a single file name space
+across multiple file servers.
+Because file servers control the shape of the name space,
+no client configuration is required,
+and all clients see the same referral information.
+.P
+The Linux NFS server supports NFS version 4 referrals.
+Administrators can specify the
+.B refer=
+export option in
+.I /etc/exports
+to configure a list of exports from which the client can choose.
+See
+.BR exports (5)
+for details.
+.P
+.SH DESCRIPTION
+The
+.BR nfsref (8)
+command is a simple way to get started managing junction metadata.
+Other administrative commands provide richer access to junction information.
+.SS Subcommands
+Valid
+.BR nfsref (8)
+subcommands are:
+.IP "\fBadd\fP"
+Adds junction information to the directory named by
+.IR pathname .
+The named directory must already exist,
+and must not already contain junction information.
+Regular directory contents are obscured to NFS clients by this operation.
+.IP
+A list of one or more file server and export path pairs
+is also specified on the command line.
+When creating an NFS basic junction, this list is
+stored in an extended attribute of the directory.
+.IP
+If junction creation is successful, the
+.BR nfsref (8)
+command flushes the kernel's export cache
+to remove previously cached junction information.
+.IP "\fBremove\fP"
+Removes junction information from the directory named by
+.IR pathname .
+The named directory must exist,
+and must contain junction information.
+Regular directory contents are made visible to NFS clients again by this operation.
+.IP
+If junction deletion is successful, the
+.BR nfsref (8)
+command flushes the kernel's export cache
+to remove previously cached junction information.
+.IP "\fBlookup\fP"
+Displays junction information stored in the directory named by
+.IR pathname .
+The named directory must exist,
+and must contain junction information.
+.IP
+When looking up an NFS basic junction, the junction information
+in the directory is listed on
+.IR stdout .
+.SS Command line options
+.IP "\fB\-d, \-\-debug"
+Enables debugging messages during operation.
+.IP "\fB\-t, \-\-type=\fIjunction-type\fP"
+Specifies the junction type for the operation.  Valid values for
+.I junction-type
+are
+.B nfs-basic
+or
+.BR nfs-fedfs .
+.IP
+For the
+.B add
+subcommand, the default value if this option is not specified is
+.BR nfs-basic .
+For the
+.B remove
+and
+.B lookup
+subcommands, the
+.B \-\-type
+option is not required.  The
+.BR nfsref (8)
+command operates on whatever junction contents are available.
+.SH EXAMPLES
+Suppose you have two file servers,
+.I top.example.net
+and
+.IR home.example.net .
+You want all your clients to mount
+.I top.example.net:/
+and then see the files under
+.I home.example.net:/
+automatically in
+.IR top:/home .
+.P
+On
+.IR top.example.net ,
+you might issue this command as root:
+.RS
+.sp
+# mkdir /home
+.br
+# nfsref --type=nfs-basic add /home home.example.net /
+.br
+Created junction /home.
+.sp
+.RE
+.SH FILES
+.TP
+.I /etc/exports
+NFS server export table
+.SH "SEE ALSO"
+.BR exports (5)
+.sp
+RFC 5661 for a description of NFS version 4 referrals
+.SH "AUTHOR"
+Chuck Lever <chuck.lever@oracle.com>
diff --git a/utils/nfsref/remove.c b/utils/nfsref/remove.c
new file mode 100644
index 0000000..1a4e371
--- /dev/null
+++ b/utils/nfsref/remove.c
@@ -0,0 +1,145 @@
+/**
+ * @file utils/nfsref/remove.c
+ * @brief Remove junction metadata from a local file system object
+ */
+
+/*
+ * Copyright 2011, 2018 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-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.
+ *
+ * nfs-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 nfs-utils.  If not, see:
+ *
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "junction.h"
+#include "xlog.h"
+#include "nfsref.h"
+
+/**
+ * Display help message for "remove" subcommand
+ *
+ * @param progname NUL-terminated C string containing name of program
+ * @return program exit status
+ */
+int
+nfsref_remove_help(const char *progname)
+{
+	fprintf(stderr, " \n");
+
+	fprintf(stderr, "Usage: %s [ -t type ] remove <junction path>\n\n",
+		progname);
+
+	fprintf(stderr, "Remove the junction at <junction path>.  For FedFS "
+			"junctions, FSL and FSN\n");
+	fprintf(stderr, "records are removed from the NSDB.\n");
+
+	return EXIT_SUCCESS;
+}
+
+/**
+ * Remove an NFS locations-style junction
+ *
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @return program exit status
+ */
+static int
+nfsref_remove_nfs_basic(const char *junct_path)
+{
+	int status = EXIT_FAILURE;
+	FedFsStatus retval;
+
+	xlog(D_GENERAL, "%s: Removing FedFS junction from %s",
+		__func__, junct_path);
+
+	retval = nfs_delete_junction(junct_path);
+	switch (retval) {
+	case FEDFS_OK:
+		printf("Removed nfs-basic junction from %s\n", junct_path);
+		status = EXIT_SUCCESS;
+		break;
+	case FEDFS_ERR_NOTJUNCT:
+		xlog(L_ERROR, "%s is not an nfs-basic junction", junct_path);
+		break;
+	default:
+		xlog(L_ERROR, "Failed to delete %s: %s",
+			junct_path, nsdb_display_fedfsstatus(retval));
+	}
+
+	return status;
+}
+
+/**
+ * Remove any NFS junction information
+ *
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @return program exit status
+ */
+static int
+nfsref_remove_unspecified(const char *junct_path)
+{
+	FedFsStatus retval;
+
+	xlog(D_GENERAL, "%s: Removing junction from %s",
+		__func__, junct_path);
+
+	retval = nfs_delete_junction(junct_path);
+	if (retval != FEDFS_OK) {
+		if (retval != FEDFS_ERR_NOTJUNCT)
+			goto out_err;
+	}
+
+	printf("Removed junction from %s\n", junct_path);
+	return EXIT_SUCCESS;
+
+out_err:
+	switch (retval) {
+	case FEDFS_ERR_NOTJUNCT:
+		xlog(L_ERROR, "No junction information found in %s", junct_path);
+		break;
+	default:
+		xlog(L_ERROR, "Failed to delete %s: %s",
+			junct_path, nsdb_display_fedfsstatus(retval));
+	}
+	return EXIT_FAILURE;
+}
+
+/**
+ * Remove an NFS junction
+ *
+ * @param type type of junction to add
+ * @param junct_path NUL-terminated C string containing pathname of junction
+ * @return program exit status
+ */
+int
+nfsref_remove(enum nfsref_type type, const char *junct_path)
+{
+	switch (type) {
+	case NFSREF_TYPE_UNSPECIFIED:
+		return nfsref_remove_unspecified(junct_path);
+	case NFSREF_TYPE_NFS_BASIC:
+		return nfsref_remove_nfs_basic(junct_path);
+	default:
+		xlog(L_ERROR, "Unrecognized junction type");
+	}
+	return EXIT_FAILURE;
+}


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-08 21:49 [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils Chuck Lever
  2018-01-08 21:50 ` [PATCH RFC 2/3] Add LDAP-free version of libnfsjunct " Chuck Lever
  2018-01-08 21:50 ` [PATCH RFC 3/3] Add 'nfsref' command Chuck Lever
@ 2018-01-09 19:21 ` J. Bruce Fields
  2018-01-09 19:36   ` Chuck Lever
  2 siblings, 1 reply; 12+ messages in thread
From: J. Bruce Fields @ 2018-01-09 19:21 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

Thanks for doing this!  I may not get the chance to do a real review,
but I'm in favor of the basic idea.

--b.

On Mon, Jan 08, 2018 at 04:49:50PM -0500, Chuck Lever wrote:
> THIS IS AN UNTESTED RFC SERIES. I'm posting this for review only.
> 
> A while back I announced the deprecation of fedfs-utils. There were
> a handful of components in fedfs-utils that we decided to keep. One
> of those keepers was the "nfsref" command. (The other was autofs
> support for /nfs4, which I hope Ian Kent is making progress on ;-)
> 
> This is an RFC patch series to introduce "nfsref" to nfs-utils,
> minus the overhead of the LDAP / FedFS machinery. It also adds a
> version of libnfsjunct which mountd can dynamically load to handle
> non-FedFS junctions, replacing the same part from fedfs-utils.
> 
> I didn't apply a lot of brain cells to this port, so it's perhaps a
> little larger than it needs to be. Still, it achieves a completely
> LDAP-free implementation. I'm interested in comments about the
> approach before I do more testing and refinement.
> 
>   ./configure --enable-junction --enable-caps
> 
> is needed before building.
> 
> Perhaps one thing that can be done is simply getting rid of the DLL
> and building junction support into mountd. I'm not sure if a
> transition period is necessary where the DLL is retained for a bit
> until fedfs-utils is entirely gone. Does anything but mountd use
> libnfsjunct ?
> 
> 
> ---
> 
> Chuck Lever (3):
>       Add LDAP-free version of libjunction to nfs-utils
>       Add LDAP-free version of libnfsjunct to nfs-utils
>       Add 'nfsref' command
> 
> 
>  aclocal/libxml2.m4                   |   15 
>  configure.ac                         |   12 
>  support/Makefile.am                  |    4 
>  support/include/Makefile.am          |    3 
>  support/include/fedfs_admin.h        |  342 +++++++
>  support/include/junction.h           |  124 +++
>  support/include/nfs-plugin.h         |  101 ++
>  support/junction/Makefile.am         |   40 +
>  support/junction/display.c           |  159 +++
>  support/junction/export-cache.c      |  118 +++
>  support/junction/junction-internal.h |  121 +++
>  support/junction/junction.c          |  494 +++++++++++
>  support/junction/locations.c         |  131 +++
>  support/junction/nfs-plugin.c        |  350 ++++++++
>  support/junction/nfs.c               | 1564 ++++++++++++++++++++++++++++++++++
>  support/junction/path.c              |  345 ++++++++
>  support/junction/xml.c               |  401 +++++++++
>  utils/Makefile.am                    |    4 
>  utils/nfsref/Makefile.am             |   39 +
>  utils/nfsref/add.c                   |  271 ++++++
>  utils/nfsref/lookup.c                |  211 +++++
>  utils/nfsref/nfsref.c                |  188 ++++
>  utils/nfsref/nfsref.h                |   47 +
>  utils/nfsref/nfsref.man              |  180 ++++
>  utils/nfsref/remove.c                |  145 +++
>  25 files changed, 5409 insertions(+)
>  create mode 100644 aclocal/libxml2.m4
>  create mode 100644 support/include/fedfs_admin.h
>  create mode 100644 support/include/junction.h
>  create mode 100644 support/include/nfs-plugin.h
>  create mode 100644 support/junction/Makefile.am
>  create mode 100644 support/junction/display.c
>  create mode 100644 support/junction/export-cache.c
>  create mode 100644 support/junction/junction-internal.h
>  create mode 100644 support/junction/junction.c
>  create mode 100644 support/junction/locations.c
>  create mode 100644 support/junction/nfs-plugin.c
>  create mode 100644 support/junction/nfs.c
>  create mode 100644 support/junction/path.c
>  create mode 100644 support/junction/xml.c
>  create mode 100644 utils/nfsref/Makefile.am
>  create mode 100644 utils/nfsref/add.c
>  create mode 100644 utils/nfsref/lookup.c
>  create mode 100644 utils/nfsref/nfsref.c
>  create mode 100644 utils/nfsref/nfsref.h
>  create mode 100644 utils/nfsref/nfsref.man
>  create mode 100644 utils/nfsref/remove.c
> 
> --
> Chuck Lever
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-09 19:21 ` [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils J. Bruce Fields
@ 2018-01-09 19:36   ` Chuck Lever
  2018-01-10 17:13     ` Steve Dickson
  0 siblings, 1 reply; 12+ messages in thread
From: Chuck Lever @ 2018-01-09 19:36 UTC (permalink / raw)
  To: Bruce Fields; +Cc: Linux NFS Mailing List



> On Jan 9, 2018, at 2:21 PM, bfields@fieldses.org wrote:
>=20
> Thanks for doing this!  I may not get the chance to do a real review,
> but I'm in favor of the basic idea.

How do you feel about building support for junctions into mountd,
and getting rid of the libnfsjunct DLL ?


> --b.
>=20
> On Mon, Jan 08, 2018 at 04:49:50PM -0500, Chuck Lever wrote:
>> THIS IS AN UNTESTED RFC SERIES. I'm posting this for review only.
>>=20
>> A while back I announced the deprecation of fedfs-utils. There were
>> a handful of components in fedfs-utils that we decided to keep. One
>> of those keepers was the "nfsref" command. (The other was autofs
>> support for /nfs4, which I hope Ian Kent is making progress on ;-)
>>=20
>> This is an RFC patch series to introduce "nfsref" to nfs-utils,
>> minus the overhead of the LDAP / FedFS machinery. It also adds a
>> version of libnfsjunct which mountd can dynamically load to handle
>> non-FedFS junctions, replacing the same part from fedfs-utils.
>>=20
>> I didn't apply a lot of brain cells to this port, so it's perhaps a
>> little larger than it needs to be. Still, it achieves a completely
>> LDAP-free implementation. I'm interested in comments about the
>> approach before I do more testing and refinement.
>>=20
>>  ./configure --enable-junction --enable-caps
>>=20
>> is needed before building.
>>=20
>> Perhaps one thing that can be done is simply getting rid of the DLL
>> and building junction support into mountd. I'm not sure if a
>> transition period is necessary where the DLL is retained for a bit
>> until fedfs-utils is entirely gone. Does anything but mountd use
>> libnfsjunct ?
>>=20
>>=20
>> ---
>>=20
>> Chuck Lever (3):
>>      Add LDAP-free version of libjunction to nfs-utils
>>      Add LDAP-free version of libnfsjunct to nfs-utils
>>      Add 'nfsref' command
>>=20
>>=20
>> aclocal/libxml2.m4                   |   15=20
>> configure.ac                         |   12=20
>> support/Makefile.am                  |    4=20
>> support/include/Makefile.am          |    3=20
>> support/include/fedfs_admin.h        |  342 +++++++
>> support/include/junction.h           |  124 +++
>> support/include/nfs-plugin.h         |  101 ++
>> support/junction/Makefile.am         |   40 +
>> support/junction/display.c           |  159 +++
>> support/junction/export-cache.c      |  118 +++
>> support/junction/junction-internal.h |  121 +++
>> support/junction/junction.c          |  494 +++++++++++
>> support/junction/locations.c         |  131 +++
>> support/junction/nfs-plugin.c        |  350 ++++++++
>> support/junction/nfs.c               | 1564 =
++++++++++++++++++++++++++++++++++
>> support/junction/path.c              |  345 ++++++++
>> support/junction/xml.c               |  401 +++++++++
>> utils/Makefile.am                    |    4=20
>> utils/nfsref/Makefile.am             |   39 +
>> utils/nfsref/add.c                   |  271 ++++++
>> utils/nfsref/lookup.c                |  211 +++++
>> utils/nfsref/nfsref.c                |  188 ++++
>> utils/nfsref/nfsref.h                |   47 +
>> utils/nfsref/nfsref.man              |  180 ++++
>> utils/nfsref/remove.c                |  145 +++
>> 25 files changed, 5409 insertions(+)
>> create mode 100644 aclocal/libxml2.m4
>> create mode 100644 support/include/fedfs_admin.h
>> create mode 100644 support/include/junction.h
>> create mode 100644 support/include/nfs-plugin.h
>> create mode 100644 support/junction/Makefile.am
>> create mode 100644 support/junction/display.c
>> create mode 100644 support/junction/export-cache.c
>> create mode 100644 support/junction/junction-internal.h
>> create mode 100644 support/junction/junction.c
>> create mode 100644 support/junction/locations.c
>> create mode 100644 support/junction/nfs-plugin.c
>> create mode 100644 support/junction/nfs.c
>> create mode 100644 support/junction/path.c
>> create mode 100644 support/junction/xml.c
>> create mode 100644 utils/nfsref/Makefile.am
>> create mode 100644 utils/nfsref/add.c
>> create mode 100644 utils/nfsref/lookup.c
>> create mode 100644 utils/nfsref/nfsref.c
>> create mode 100644 utils/nfsref/nfsref.h
>> create mode 100644 utils/nfsref/nfsref.man
>> create mode 100644 utils/nfsref/remove.c
>>=20
>> --
>> Chuck Lever
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" =
in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Chuck Lever




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-09 19:36   ` Chuck Lever
@ 2018-01-10 17:13     ` Steve Dickson
  2018-01-10 17:17       ` Bruce Fields
  2018-01-10 19:42       ` Chuck Lever
  0 siblings, 2 replies; 12+ messages in thread
From: Steve Dickson @ 2018-01-10 17:13 UTC (permalink / raw)
  To: Chuck Lever, Bruce Fields; +Cc: Linux NFS Mailing List



On 01/09/2018 02:36 PM, Chuck Lever wrote:
> 
> 
>> On Jan 9, 2018, at 2:21 PM, bfields@fieldses.org wrote:
>>
>> Thanks for doing this!  I may not get the chance to do a real review,
>> but I'm in favor of the basic idea.
> 
> How do you feel about building support for junctions into mountd,
> and getting rid of the libnfsjunct DLL ?
I would rather not put new functionality in daemons that needs rpcbind.
With the idea of, someday, having clean v4-only configuration
(aka no mountd, statd, or lockd).  

>>
>> On Mon, Jan 08, 2018 at 04:49:50PM -0500, Chuck Lever wrote:
>>> THIS IS AN UNTESTED RFC SERIES. I'm posting this for review only.
>>>
>>> A while back I announced the deprecation of fedfs-utils. There were
>>> a handful of components in fedfs-utils that we decided to keep. One
>>> of those keepers was the "nfsref" command. (The other was autofs
>>> support for /nfs4, which I hope Ian Kent is making progress on ;-)
>>>
>>> This is an RFC patch series to introduce "nfsref" to nfs-utils,
>>> minus the overhead of the LDAP / FedFS machinery. It also adds a
>>> version of libnfsjunct which mountd can dynamically load to handle
>>> non-FedFS junctions, replacing the same part from fedfs-utils.
>>>
>>> I didn't apply a lot of brain cells to this port, so it's perhaps a
>>> little larger than it needs to be. Still, it achieves a completely
>>> LDAP-free implementation. I'm interested in comments about the
>>> approach before I do more testing and refinement.
>>>
>>>  ./configure --enable-junction --enable-caps
>>>
>>> is needed before building.
>>>
>>> Perhaps one thing that can be done is simply getting rid of the DLL
>>> and building junction support into mountd. I'm not sure if a
>>> transition period is necessary where the DLL is retained for a bit
>>> until fedfs-utils is entirely gone. Does anything but mountd use
>>> libnfsjunct ?
So nfsref is to manage NFS referrals... got it... which I think
is a good thing to put into nfs-utils.. but again I wold like
to move a way from using mountd for exporting stuff.

I must admit my memory on how referrals work is a bet strained, 
but does it make any sense at all to move the referral code out 
of mountd and into a new command maybe called nfsexport. Then
have the kernel call up to that command (similar to how it
does with nfsidmap) to get the referrals info. That way
only nfsexport would link with libnfsjunct.

Now I realize this has nothing to do with putting nfsref
into nfs-utils... I'm all for that... and I'm not asking you
to do the work... I'm thinking out loud... Does it 
make sense to use this opportunity to build new mechanisms 
to handle referrals and then possibly all exports??
Again, with the idea of eliminating need for legacy daemons.

steved.
  

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-10 17:13     ` Steve Dickson
@ 2018-01-10 17:17       ` Bruce Fields
  2018-01-10 17:26         ` Steve Dickson
  2018-01-10 19:42       ` Chuck Lever
  1 sibling, 1 reply; 12+ messages in thread
From: Bruce Fields @ 2018-01-10 17:17 UTC (permalink / raw)
  To: Steve Dickson; +Cc: Chuck Lever, Linux NFS Mailing List

On Wed, Jan 10, 2018 at 12:13:39PM -0500, Steve Dickson wrote:
> 
> 
> On 01/09/2018 02:36 PM, Chuck Lever wrote:
> > 
> > 
> >> On Jan 9, 2018, at 2:21 PM, bfields@fieldses.org wrote:
> >>
> >> Thanks for doing this!  I may not get the chance to do a real review,
> >> but I'm in favor of the basic idea.
> > 
> > How do you feel about building support for junctions into mountd,
> > and getting rid of the libnfsjunct DLL ?
> I would rather not put new functionality in daemons that needs rpcbind.
> With the idea of, someday, having clean v4-only configuration
> (aka no mountd, statd, or lockd).  

rpc.mountd is used by v4 for a lot of stuff already, so it's not going
away.  Is it trying to register with rpcbind in the case it's called
with -N2 -N3?  That would be a bug.

--b.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-10 17:17       ` Bruce Fields
@ 2018-01-10 17:26         ` Steve Dickson
  2018-01-10 17:36           ` Bruce Fields
  0 siblings, 1 reply; 12+ messages in thread
From: Steve Dickson @ 2018-01-10 17:26 UTC (permalink / raw)
  To: Bruce Fields; +Cc: Chuck Lever, Linux NFS Mailing List



On 01/10/2018 12:17 PM, Bruce Fields wrote:
> On Wed, Jan 10, 2018 at 12:13:39PM -0500, Steve Dickson wrote:
>>
>>
>> On 01/09/2018 02:36 PM, Chuck Lever wrote:
>>>
>>>
>>>> On Jan 9, 2018, at 2:21 PM, bfields@fieldses.org wrote:
>>>>
>>>> Thanks for doing this!  I may not get the chance to do a real review,
>>>> but I'm in favor of the basic idea.
>>>
>>> How do you feel about building support for junctions into mountd,
>>> and getting rid of the libnfsjunct DLL ?
>> I would rather not put new functionality in daemons that needs rpcbind.
>> With the idea of, someday, having clean v4-only configuration
>> (aka no mountd, statd, or lockd).  
> 
> rpc.mountd is used by v4 for a lot of stuff already, so it's not going
> away.  
Understood.... I guess I'm looking for a way to replace it with
a command the kernel can call to only do v4 stuff.
Would something like that make sense?

> Is it trying to register with rpcbind in the case it's called
> with -N2 -N3?  That would be a bug.
Looking at the code... probably not... 

steved.
> 
> --b.
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-10 17:26         ` Steve Dickson
@ 2018-01-10 17:36           ` Bruce Fields
  0 siblings, 0 replies; 12+ messages in thread
From: Bruce Fields @ 2018-01-10 17:36 UTC (permalink / raw)
  To: Steve Dickson; +Cc: Chuck Lever, Linux NFS Mailing List

On Wed, Jan 10, 2018 at 12:26:10PM -0500, Steve Dickson wrote:
> 
> 
> On 01/10/2018 12:17 PM, Bruce Fields wrote:
> > On Wed, Jan 10, 2018 at 12:13:39PM -0500, Steve Dickson wrote:
> >>
> >>
> >> On 01/09/2018 02:36 PM, Chuck Lever wrote:
> >>>
> >>>
> >>>> On Jan 9, 2018, at 2:21 PM, bfields@fieldses.org wrote:
> >>>>
> >>>> Thanks for doing this!  I may not get the chance to do a real review,
> >>>> but I'm in favor of the basic idea.
> >>>
> >>> How do you feel about building support for junctions into mountd,
> >>> and getting rid of the libnfsjunct DLL ?
> >> I would rather not put new functionality in daemons that needs rpcbind.
> >> With the idea of, someday, having clean v4-only configuration
> >> (aka no mountd, statd, or lockd).  
> > 
> > rpc.mountd is used by v4 for a lot of stuff already, so it's not going
> > away.  
> Understood.... I guess I'm looking for a way to replace it with
> a command the kernel can call to only do v4 stuff.
> Would something like that make sense?

It would be a fair amount of work and I don't think there's a strong
reason to do it.

rpc.mountd -N2 -N3 should do what we want.

--b.

> 
> > Is it trying to register with rpcbind in the case it's called
> > with -N2 -N3?  That would be a bug.
> Looking at the code... probably not... 
> 
> steved.
> > 
> > --b.
> > 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-10 17:13     ` Steve Dickson
  2018-01-10 17:17       ` Bruce Fields
@ 2018-01-10 19:42       ` Chuck Lever
  2018-01-11 14:20         ` Steve Dickson
  1 sibling, 1 reply; 12+ messages in thread
From: Chuck Lever @ 2018-01-10 19:42 UTC (permalink / raw)
  To: Steve Dickson; +Cc: Bruce Fields, Linux NFS Mailing List



> On Jan 10, 2018, at 12:13 PM, Steve Dickson <SteveD@RedHat.com> wrote:
> 
> 
> 
> On 01/09/2018 02:36 PM, Chuck Lever wrote:
>> 
>> 
>>> On Jan 9, 2018, at 2:21 PM, bfields@fieldses.org wrote:
>>> 
>>> Thanks for doing this!  I may not get the chance to do a real review,
>>> but I'm in favor of the basic idea.
>> 
>> How do you feel about building support for junctions into mountd,
>> and getting rid of the libnfsjunct DLL ?
> I would rather not put new functionality in daemons that needs rpcbind.
> With the idea of, someday, having clean v4-only configuration
> (aka no mountd, statd, or lockd).

Hi Steve, junction support is not new functionality.

Currently, mountd handles junction support by loading a DLL
called libnfsjunct. We did this because you didn't want to add
an LDAP dependency to nfs-utils in order to support FedFS.

What I'm proposing is that because we no longer need LDAP support,
we could build support for NFS basic junctions directly into mountd.
This would be straightforward: just put nfs-plugin.c under
utils/mountd and link it in at build time. Then dump the logic to
load a plug-in (or we could even conditionally compile it in or out).

The NFS basic junction code is already being ported into nfs-utils
to support the nfsref command.

The long-term implication is that this removes the pluggable API
for supporting other types of junctions, like reparse points should
Linux ever choose to implement them. Since Linux doesn't have these
now, and it's not a standard API anyway, maybe this is moot and I
should go ahead and rip out the plug-in logic.


>>> On Mon, Jan 08, 2018 at 04:49:50PM -0500, Chuck Lever wrote:
>>>> THIS IS AN UNTESTED RFC SERIES. I'm posting this for review only.
>>>> 
>>>> A while back I announced the deprecation of fedfs-utils. There were
>>>> a handful of components in fedfs-utils that we decided to keep. One
>>>> of those keepers was the "nfsref" command. (The other was autofs
>>>> support for /nfs4, which I hope Ian Kent is making progress on ;-)
>>>> 
>>>> This is an RFC patch series to introduce "nfsref" to nfs-utils,
>>>> minus the overhead of the LDAP / FedFS machinery. It also adds a
>>>> version of libnfsjunct which mountd can dynamically load to handle
>>>> non-FedFS junctions, replacing the same part from fedfs-utils.
>>>> 
>>>> I didn't apply a lot of brain cells to this port, so it's perhaps a
>>>> little larger than it needs to be. Still, it achieves a completely
>>>> LDAP-free implementation. I'm interested in comments about the
>>>> approach before I do more testing and refinement.
>>>> 
>>>> ./configure --enable-junction --enable-caps
>>>> 
>>>> is needed before building.
>>>> 
>>>> Perhaps one thing that can be done is simply getting rid of the DLL
>>>> and building junction support into mountd. I'm not sure if a
>>>> transition period is necessary where the DLL is retained for a bit
>>>> until fedfs-utils is entirely gone. Does anything but mountd use
>>>> libnfsjunct ?
> So nfsref is to manage NFS referrals... got it... which I think
> is a good thing to put into nfs-utils.. but again I wold like
> to move a way from using mountd for exporting stuff.
> 
> I must admit my memory on how referrals work is a bet strained, 
> but does it make any sense at all to move the referral code out 
> of mountd and into a new command maybe called nfsexport. Then
> have the kernel call up to that command (similar to how it
> does with nfsidmap) to get the referrals info. That way
> only nfsexport would link with libnfsjunct.

Since FedFS support is no longer needed, junction support
could also be built directly into nfsexport (no separate DLL
is necessary).


> Now I realize this has nothing to do with putting nfsref
> into nfs-utils... I'm all for that... and I'm not asking you
> to do the work... I'm thinking out loud... Does it 
> make sense to use this opportunity to build new mechanisms 
> to handle referrals and then possibly all exports??
> Again, with the idea of eliminating need for legacy daemons.

I don't have any quarrel with carving out the non-network-exposed
functionality of mountd and putting it in an upcall similar to
nfsidmap. Seems like an entirely separate project, though, and
probably a significant chunk of work.

Given the heightened security consciousness in today's world,
sandboxing the network-exposed part is a sensible precaution
for deployments that continue to need a MNT RPC service.

In the long run, IMO the existing mountd upcall is going to have
to be replaced. The current upcall mechanism is limited to moving
just a page of data; fs_locations and fs_locations_info can
comprise more than a page. And the upcall API might have to be
revisited carefully to support fs_locations_info.


--
Chuck Lever




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-10 19:42       ` Chuck Lever
@ 2018-01-11 14:20         ` Steve Dickson
  2018-01-11 15:17           ` Bruce Fields
  0 siblings, 1 reply; 12+ messages in thread
From: Steve Dickson @ 2018-01-11 14:20 UTC (permalink / raw)
  To: Chuck Lever; +Cc: Bruce Fields, Linux NFS Mailing List



On 01/10/2018 02:42 PM, Chuck Lever wrote:
> 
> 
>> On Jan 10, 2018, at 12:13 PM, Steve Dickson <SteveD@RedHat.com> wrote:
>>
>>
>>
>> On 01/09/2018 02:36 PM, Chuck Lever wrote:
>>>
>>>
>>>> On Jan 9, 2018, at 2:21 PM, bfields@fieldses.org wrote:
>>>>
>>>> Thanks for doing this!  I may not get the chance to do a real review,
>>>> but I'm in favor of the basic idea.
>>>
>>> How do you feel about building support for junctions into mountd,
>>> and getting rid of the libnfsjunct DLL ?
>> I would rather not put new functionality in daemons that needs rpcbind.
>> With the idea of, someday, having clean v4-only configuration
>> (aka no mountd, statd, or lockd).
> 
> Hi Steve, junction support is not new functionality.
> 
> Currently, mountd handles junction support by loading a DLL
> called libnfsjunct. We did this because you didn't want to add
> an LDAP dependency to nfs-utils in order to support FedFS.
Right.. I remember now... 

> 
> What I'm proposing is that because we no longer need LDAP support,
> we could build support for NFS basic junctions directly into mountd.
> This would be straightforward: just put nfs-plugin.c under
> utils/mountd and link it in at build time. Then dump the logic to
> load a plug-in (or we could even conditionally compile it in or out).
I see... why would we do it conditionally? Are they ever coming back?

> 
> The NFS basic junction code is already being ported into nfs-utils
> to support the nfsref command.
> 
> The long-term implication is that this removes the pluggable API
> for supporting other types of junctions, like reparse points should
> Linux ever choose to implement them. Since Linux doesn't have these
> now, and it's not a standard API anyway, maybe this is moot and I
> should go ahead and rip out the plug-in logic.
I guess this answers my question above... They could come back
if reparse points is supported. 

> 
> 
>>>> On Mon, Jan 08, 2018 at 04:49:50PM -0500, Chuck Lever wrote:
>>>>> THIS IS AN UNTESTED RFC SERIES. I'm posting this for review only.
>>>>>
>>>>> A while back I announced the deprecation of fedfs-utils. There were
>>>>> a handful of components in fedfs-utils that we decided to keep. One
>>>>> of those keepers was the "nfsref" command. (The other was autofs
>>>>> support for /nfs4, which I hope Ian Kent is making progress on ;-)
>>>>>
>>>>> This is an RFC patch series to introduce "nfsref" to nfs-utils,
>>>>> minus the overhead of the LDAP / FedFS machinery. It also adds a
>>>>> version of libnfsjunct which mountd can dynamically load to handle
>>>>> non-FedFS junctions, replacing the same part from fedfs-utils.
>>>>>
>>>>> I didn't apply a lot of brain cells to this port, so it's perhaps a
>>>>> little larger than it needs to be. Still, it achieves a completely
>>>>> LDAP-free implementation. I'm interested in comments about the
>>>>> approach before I do more testing and refinement.
>>>>>
>>>>> ./configure --enable-junction --enable-caps
>>>>>
>>>>> is needed before building.
>>>>>
>>>>> Perhaps one thing that can be done is simply getting rid of the DLL
>>>>> and building junction support into mountd. I'm not sure if a
>>>>> transition period is necessary where the DLL is retained for a bit
>>>>> until fedfs-utils is entirely gone. Does anything but mountd use
>>>>> libnfsjunct ?
>> So nfsref is to manage NFS referrals... got it... which I think
>> is a good thing to put into nfs-utils.. but again I wold like
>> to move a way from using mountd for exporting stuff.
>>
>> I must admit my memory on how referrals work is a bet strained, 
>> but does it make any sense at all to move the referral code out 
>> of mountd and into a new command maybe called nfsexport. Then
>> have the kernel call up to that command (similar to how it
>> does with nfsidmap) to get the referrals info. That way
>> only nfsexport would link with libnfsjunct.
> 
> Since FedFS support is no longer needed, junction support
> could also be built directly into nfsexport (no separate DLL
> is necessary).
Got it... but a v4only exporter did seem to impress anybody ;-) 
> 
> 
>> Now I realize this has nothing to do with putting nfsref
>> into nfs-utils... I'm all for that... and I'm not asking you
>> to do the work... I'm thinking out loud... Does it 
>> make sense to use this opportunity to build new mechanisms 
>> to handle referrals and then possibly all exports??
>> Again, with the idea of eliminating need for legacy daemons.
> 
> I don't have any quarrel with carving out the non-network-exposed
> functionality of mountd and putting it in an upcall similar to
> nfsidmap. Seems like an entirely separate project, though, and
> probably a significant chunk of work.
It is... I was just floating the idea. 

> 
> Given the heightened security consciousness in today's world,
> sandboxing the network-exposed part is a sensible precaution
> for deployments that continue to need a MNT RPC service.
> 
> In the long run, IMO the existing mountd upcall is going to have
> to be replaced. The current upcall mechanism is limited to moving
> just a page of data; fs_locations and fs_locations_info can
> comprise more than a page. And the upcall API might have to be
> revisited carefully to support fs_locations_info.
nfsimdap uses keyrings to communicate with the kernel.
Maybe that could be used to replace the kernel upcalls?

steved.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils
  2018-01-11 14:20         ` Steve Dickson
@ 2018-01-11 15:17           ` Bruce Fields
  0 siblings, 0 replies; 12+ messages in thread
From: Bruce Fields @ 2018-01-11 15:17 UTC (permalink / raw)
  To: Steve Dickson; +Cc: Chuck Lever, Linux NFS Mailing List

On Thu, Jan 11, 2018 at 09:20:54AM -0500, Steve Dickson wrote:
> On 01/10/2018 02:42 PM, Chuck Lever wrote:
> > I don't have any quarrel with carving out the non-network-exposed
> > functionality of mountd and putting it in an upcall similar to
> > nfsidmap. Seems like an entirely separate project, though, and
> > probably a significant chunk of work.
> It is... I was just floating the idea. 

Yeah, I don't mean to veto the idea, I think we've discussed it before
and it's kind of appealing.  I just think we haven't thought it through
and we don't have any real reason it's necessary right now.  I'd hate to
send someone down that rabbit hole and have the come back with a bunch
of work and us say "uh, but why do we want this?".

--b.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2018-01-11 15:17 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-08 21:49 [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils Chuck Lever
2018-01-08 21:50 ` [PATCH RFC 2/3] Add LDAP-free version of libnfsjunct " Chuck Lever
2018-01-08 21:50 ` [PATCH RFC 3/3] Add 'nfsref' command Chuck Lever
2018-01-09 19:21 ` [PATCH RFC 0/3] Add server-side support for junctions to nfs-utils J. Bruce Fields
2018-01-09 19:36   ` Chuck Lever
2018-01-10 17:13     ` Steve Dickson
2018-01-10 17:17       ` Bruce Fields
2018-01-10 17:26         ` Steve Dickson
2018-01-10 17:36           ` Bruce Fields
2018-01-10 19:42       ` Chuck Lever
2018-01-11 14:20         ` Steve Dickson
2018-01-11 15:17           ` Bruce Fields

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).