walters / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
8653dda
diff -up nfs-utils-1.2.0/support/export/xtab.c.save nfs-utils-1.2.0/support/export/xtab.c
8653dda
--- nfs-utils-1.2.0/support/export/xtab.c.save	2009-10-20 08:46:50.000000000 -0400
8653dda
+++ nfs-utils-1.2.0/support/export/xtab.c	2009-10-20 08:47:26.000000000 -0400
8653dda
@@ -19,7 +19,9 @@
8653dda
 #include "exportfs.h"
8653dda
 #include "xio.h"
8653dda
 #include "xlog.h"
8653dda
+#include "v4root.h"
8653dda
 
8653dda
+int v4root_needed;
8653dda
 static void cond_rename(char *newfile, char *oldfile);
8653dda
 
8653dda
 static int
8653dda
@@ -36,6 +38,8 @@ xtab_read(char *xtab, char *lockfn, int 
8653dda
 	if ((lockid = xflock(lockfn, "r")) < 0)
8653dda
 		return 0;
8653dda
 	setexportent(xtab, "r");
8653dda
+	if (is_export == 1)
8653dda
+		v4root_needed = 1;
8653dda
 	while ((xp = getexportent(is_export==0, 0)) != NULL) {
8653dda
 		if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
8653dda
 		    !(exp = export_create(xp, is_export!=1))) {
8653dda
@@ -48,6 +52,8 @@ xtab_read(char *xtab, char *lockfn, int 
8653dda
 		case 1:
8653dda
 			exp->m_xtabent = 1;
8653dda
 			exp->m_mayexport = 1;
8653dda
+			if ((xp->e_flags & NFSEXP_FSID) && xp->e_fsid == 0)
8653dda
+				v4root_needed = 0;
8653dda
 			break;
8653dda
 		case 2:
8653dda
 			exp->m_exported = -1;/* may be exported */
8653dda
diff -up nfs-utils-1.2.0/support/include/exportfs.h.save nfs-utils-1.2.0/support/include/exportfs.h
8653dda
--- nfs-utils-1.2.0/support/include/exportfs.h.save	2009-10-20 08:46:50.000000000 -0400
8653dda
+++ nfs-utils-1.2.0/support/include/exportfs.h	2009-10-20 08:47:07.000000000 -0400
8653dda
@@ -12,6 +12,17 @@
8653dda
 #include <netdb.h>
8653dda
 #include "nfslib.h"
8653dda
 
8653dda
+enum nfsd_fsid {
8653dda
+	FSID_DEV = 0,
8653dda
+	FSID_NUM,
8653dda
+	FSID_MAJOR_MINOR,
8653dda
+	FSID_ENCODE_DEV,
8653dda
+	FSID_UUID4_INUM,
8653dda
+	FSID_UUID8,
8653dda
+	FSID_UUID16,
8653dda
+	FSID_UUID16_INUM,
8653dda
+};
8653dda
+
8653dda
 enum {
8653dda
 	MCL_FQDN = 0,
8653dda
 	MCL_SUBNETWORK,
8653dda
diff -up nfs-utils-1.2.0/support/include/nfs/export.h.save nfs-utils-1.2.0/support/include/nfs/export.h
8653dda
--- nfs-utils-1.2.0/support/include/nfs/export.h.save	2009-10-20 08:46:50.000000000 -0400
8653dda
+++ nfs-utils-1.2.0/support/include/nfs/export.h	2009-10-20 08:47:07.000000000 -0400
8653dda
@@ -24,6 +24,7 @@
8653dda
 #define NFSEXP_FSID		0x2000
8653dda
 #define	NFSEXP_CROSSMOUNT	0x4000
8653dda
 #define NFSEXP_NOACL		0x8000 /* reserved for possible ACL related use */
8653dda
-#define NFSEXP_ALLFLAGS		0xFFFF
8653dda
+#define NFSEXP_V4ROOT       0x10000
8653dda
+#define NFSEXP_ALLFLAGS		0x1FFFF
8653dda
 
8653dda
 #endif /* _NSF_EXPORT_H */
8653dda
diff -up nfs-utils-1.2.0/support/include/nfslib.h.save nfs-utils-1.2.0/support/include/nfslib.h
8653dda
--- nfs-utils-1.2.0/support/include/nfslib.h.save	2009-10-20 08:46:50.000000000 -0400
8653dda
+++ nfs-utils-1.2.0/support/include/nfslib.h	2009-10-20 08:47:07.000000000 -0400
8653dda
@@ -88,6 +88,7 @@ struct exportent {
8653dda
 	int             e_fslocmethod;
8653dda
 	char *          e_fslocdata;
8653dda
 	char *		e_uuid;
8653dda
+	void *		e_v4root;
8653dda
 	struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
8653dda
 };
8653dda
 
8653dda
diff -up /dev/null nfs-utils-1.2.0/support/include/v4root.h
8653dda
--- /dev/null	2009-10-15 16:13:05.251004788 -0400
8653dda
+++ nfs-utils-1.2.0/support/include/v4root.h	2009-10-20 08:47:16.000000000 -0400
8653dda
@@ -0,0 +1,20 @@
8653dda
+/*
8653dda
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
8653dda
+ * support/include/v4root.h
8653dda
+ *
8653dda
+ * Support routines for dynamic pseudo roots.
8653dda
+ *
8653dda
+ */
8653dda
+
8653dda
+#ifndef V4ROOT_H
8653dda
+#define V4ROOT_H
8653dda
+
8653dda
+extern int v4root_needed;
8653dda
+
8653dda
+extern struct exportent *v4root_chkroot(int , unsigned int , char *);
8653dda
+extern struct exportent *v4root_export(char *, int);
8653dda
+extern struct exportent *v4root_lookup(char *, nfs_export *);
8653dda
+extern void v4root_free(struct exportent *);
8653dda
+extern void v4root_unset(void), v4root_set(void);
8653dda
+
8653dda
+#endif /* V4ROOT_H */
8653dda
diff -up nfs-utils-1.2.0/utils/mountd/auth.c.save nfs-utils-1.2.0/utils/mountd/auth.c
8653dda
--- nfs-utils-1.2.0/utils/mountd/auth.c.save	2009-10-20 08:46:50.000000000 -0400
8653dda
+++ nfs-utils-1.2.0/utils/mountd/auth.c	2009-10-20 08:47:26.000000000 -0400
8653dda
@@ -20,6 +20,7 @@
8653dda
 #include "exportfs.h"
8653dda
 #include "mountd.h"
8653dda
 #include "xmalloc.h"
8653dda
+#include "v4root.h"
8653dda
 
8653dda
 enum auth_error
8653dda
 {
8653dda
@@ -98,10 +99,13 @@ auth_reload()
8653dda
 		last_inode = stb.st_ino;
8653dda
 	}
8653dda
 
8653dda
+	v4root_unset();
8653dda
 	export_freeall();
8653dda
 	memset(&my_client, 0, sizeof(my_client));
8653dda
 	xtab_export_read();
8653dda
 	check_useipaddr();
8653dda
+	v4root_set();
8653dda
+
8653dda
 	++counter;
8653dda
 
8653dda
 	return counter;
8653dda
diff -up nfs-utils-1.2.0/utils/mountd/cache.c.save nfs-utils-1.2.0/utils/mountd/cache.c
8653dda
--- nfs-utils-1.2.0/utils/mountd/cache.c.save	2009-10-20 08:46:50.000000000 -0400
8653dda
+++ nfs-utils-1.2.0/utils/mountd/cache.c	2009-10-20 08:47:21.000000000 -0400
8653dda
@@ -32,23 +32,12 @@
8653dda
 #include "xmalloc.h"
8653dda
 #include "fsloc.h"
8653dda
 #include "pseudoflavors.h"
8653dda
+#include "v4root.h"
8653dda
 
8653dda
 #ifdef USE_BLKID
8653dda
 #include "blkid/blkid.h"
8653dda
 #endif
8653dda
 
8653dda
-
8653dda
-enum nfsd_fsid {
8653dda
-	FSID_DEV = 0,
8653dda
-	FSID_NUM,
8653dda
-	FSID_MAJOR_MINOR,
8653dda
-	FSID_ENCODE_DEV,
8653dda
-	FSID_UUID4_INUM,
8653dda
-	FSID_UUID8,
8653dda
-	FSID_UUID16,
8653dda
-	FSID_UUID16_INUM,
8653dda
-};
8653dda
-
8653dda
 /*
8653dda
  * Support routines for text-based upcalls.
8653dda
  * Fields are separated by spaces.
8653dda
@@ -135,6 +124,8 @@ void auth_unix_gid(FILE *f)
8653dda
 	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
8653dda
 		return;
8653dda
 
8653dda
+	xlog(D_CALL, "auth_unix_gid: '%s'", lbuf);
8653dda
+
8653dda
 	cp = lbuf;
8653dda
 	if (qword_get_int(&cp, &uid) != 0)
8653dda
 		return;
8653dda
@@ -391,6 +382,12 @@ void nfsd_fh(FILE *f)
8653dda
 
8653dda
 	auth_reload();
8653dda
 
8653dda
+	/* Check to see if the kenel is looking for the pseudo root */
8653dda
+	if ((found = v4root_chkroot(fsidtype, fsidnum, fhuuid))) {
8653dda
+		found_path = strdup(found->e_path);
8653dda
+		goto found;
8653dda
+	}
8653dda
+
8653dda
 	/* Now determine export point for this fsid/domain */
8653dda
 	for (i=0 ; i < MCL_MAXTYPES; i++) {
8653dda
 		nfs_export *next_exp;
8653dda
@@ -511,7 +508,23 @@ void nfsd_fh(FILE *f)
8653dda
 		 */
8653dda
 		goto out;
8653dda
 	}
8653dda
+	if (!found) {
8653dda
+		/*
8653dda
+		 * See if this is a pesudo export
8653dda
+		 */
8653dda
+		switch(fsidtype) {
8653dda
+		case FSID_UUID4_INUM:
8653dda
+		case FSID_UUID8:
8653dda
+		case FSID_UUID16:
8653dda
+		case FSID_UUID16_INUM:
8653dda
+			found = v4root_export(fhuuid, uuidlen);
8653dda
+			break;
8653dda
+		}
8653dda
+		if (found)
8653dda
+			found_path = strdup(found->e_path);
8653dda
+	}
8653dda
 
8653dda
+found:
8653dda
 	if (found)
8653dda
 		if (cache_export_ent(dom, found, found_path) < 0)
8653dda
 			found = 0;
8653dda
@@ -629,6 +642,7 @@ void nfsd_export(FILE *f)
8653dda
 	int found_type = 0;
8653dda
 	struct in_addr addr;
8653dda
 	struct hostent *he = NULL;
8653dda
+	struct exportent *v4root = NULL;
8653dda
 
8653dda
 
8653dda
 	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
8653dda
@@ -663,10 +677,18 @@ void nfsd_export(FILE *f)
8653dda
 				     path[l] == '/' &&
8653dda
 				     is_mountpoint(path)))
8653dda
 					/* ok */;
8653dda
-				else
8653dda
+				else {
8653dda
+					/* See if the path is part of the psuedo root */
8653dda
+					if (v4root_needed && !v4root) 
8653dda
+						v4root = v4root_lookup(path, exp); 
8653dda
 					continue;
8653dda
-			} else if (strcmp(path, exp->m_export.e_path) != 0)
8653dda
+				}
8653dda
+			} else if (strcmp(path, exp->m_export.e_path) != 0) {
8653dda
+				/* See if the path is part of the psuedo root */
8653dda
+				if (v4root_needed && !v4root) 
8653dda
+					v4root = v4root_lookup(path, exp); 
8653dda
 				continue;
8653dda
+			}
8653dda
 			if (use_ipaddr) {
8653dda
 				if (he == NULL) {
8653dda
 					if (!inet_aton(dom, &addr))
8653dda
@@ -705,17 +727,28 @@ void nfsd_export(FILE *f)
8653dda
 	}
8653dda
 
8653dda
 	if (found) {
8653dda
+		xlog(D_CALL, "nfsd_export: found: path %s", path);
8653dda
 		if (dump_to_cache(f, dom, path, &found->m_export) < 0) {
8653dda
 			xlog(L_WARNING,
8653dda
 			     "Cannot export %s, possibly unsupported filesystem"
8653dda
 			     " or fsid= required", path);
8653dda
 			dump_to_cache(f, dom, path, NULL);
8653dda
 		}
8653dda
-	} else {
8653dda
+	} else if (v4root) {
8653dda
+		xlog(D_CALL, "nfsd_export: vroot: path %s", path);
8653dda
+		dump_to_cache(f, dom, path, v4root);
8653dda
+		found = (nfs_export *)v4root;
8653dda
+	} else { 
8653dda
 		dump_to_cache(f, dom, path, NULL);
8653dda
 	}
8653dda
  out:
8653dda
-	xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
8653dda
+	/*
8653dda
+	 * If a psuedo export was create and its not needed
8653dda
+	 * free it up.
8653dda
+	 */
8653dda
+	if (v4root && found != (nfs_export *)v4root)
8653dda
+		v4root_free(v4root);
8653dda
+
8653dda
 	if (dom) free(dom);
8653dda
 	if (path) free(path);
8653dda
 	if (he) free(he);
8653dda
@@ -743,7 +776,9 @@ void cache_open(void) 
8653dda
 		if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid)
8653dda
 			continue;
8653dda
 		sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name);
8653dda
-		cachelist[i].f = fopen(path, "r+");
8653dda
+		if ((cachelist[i].f = fopen(path, "r+")) == NULL)
8653dda
+			xlog(L_ERROR, "cache_open: Unable to open '%s': errno %d (%s)", 
8653dda
+				path, errno, strerror(errno));
8653dda
 	}
8653dda
 }
8653dda
 
8653dda
diff -up nfs-utils-1.2.0/utils/mountd/Makefile.am.save nfs-utils-1.2.0/utils/mountd/Makefile.am
8653dda
--- nfs-utils-1.2.0/utils/mountd/Makefile.am.save	2009-10-20 08:46:50.000000000 -0400
8653dda
+++ nfs-utils-1.2.0/utils/mountd/Makefile.am	2009-10-20 08:47:16.000000000 -0400
8653dda
@@ -8,7 +8,7 @@ KPREFIX		= @kprefix@
8653dda
 sbin_PROGRAMS	= mountd
8653dda
 
8653dda
 mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
8653dda
-		 svc_run.c fsloc.c mountd.h
8653dda
+		 svc_run.c fsloc.c v4root.c mountd.h
8653dda
 mountd_LDADD = ../../support/export/libexport.a \
8653dda
 	       ../../support/nfs/libnfs.a \
8653dda
 	       ../../support/misc/libmisc.a \
8653dda
diff -up /dev/null nfs-utils-1.2.0/utils/mountd/v4root.c
8653dda
--- /dev/null	2009-10-15 16:13:05.251004788 -0400
8653dda
+++ nfs-utils-1.2.0/utils/mountd/v4root.c	2009-10-20 08:47:33.000000000 -0400
8653dda
@@ -0,0 +1,414 @@
8653dda
+/*
8653dda
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
8653dda
+ *
8653dda
+ * support/export/v4root.c
8653dda
+ *
8653dda
+ * Routines used to support NFSv4 pseudo roots
8653dda
+ *
8653dda
+ */
8653dda
+
8653dda
+#ifdef HAVE_CONFIG_H
8653dda
+#include <config.h>
8653dda
+#endif
8653dda
+
8653dda
+#include <sys/types.h>
8653dda
+#include <sys/stat.h>
8653dda
+#include <sys/queue.h>
8653dda
+#include <stdio.h>
8653dda
+#include <stdlib.h>
8653dda
+#include <ctype.h>
8653dda
+
8653dda
+#include <uuid/uuid.h>
8653dda
+#include <unistd.h>
8653dda
+#include <errno.h>
8653dda
+
8653dda
+#include "xlog.h"
8653dda
+#include "exportfs.h"
8653dda
+#include "nfslib.h"
8653dda
+#include "misc.h"
8653dda
+#include "v4root.h"
8653dda
+
8653dda
+#ifndef _PATH_PSEUDO_ROOT
8653dda
+#define _PATH_PSEUDO_ROOT		"/"
8653dda
+#endif
8653dda
+
8653dda
+#ifndef _PSEUDO_ROOT_FSID
8653dda
+#define _PSEUDO_ROOT_FSID	0
8653dda
+#endif
8653dda
+
8653dda
+extern int get_uuid(char *path, char *uuid, int uuidlen, char *u);
8653dda
+
8653dda
+#define HASH_TABLE_SIZE 1021
8653dda
+typedef struct _hash_head {
8653dda
+	TAILQ_HEAD(export_list, _exports_t) h_head;
8653dda
+} hash_head;
8653dda
+hash_head exports_tbl[HASH_TABLE_SIZE];
8653dda
+
8653dda
+typedef struct _exports_t {
8653dda
+	TAILQ_ENTRY(_exports_t) list;
8653dda
+	char *path;
8653dda
+	hash_head *head;
8653dda
+	char uuid_len;
8653dda
+	char uuid[sizeof(uuid_t)];
8653dda
+	struct exportent p_export;
8653dda
+} exports_t;
8653dda
+
8653dda
+
8653dda
+
8653dda
+static exports_t *hash_export_lookup(char *, unsigned int);
8653dda
+static void hash_export_add(struct _exports_t *, int);
8653dda
+static void hash_mount_free(void);
8653dda
+
8653dda
+static inline unsigned int strtoint(char *str, int len)
8653dda
+{
8653dda
+	unsigned int n = 0;
8653dda
+	int i;
8653dda
+
8653dda
+	for (i=0; i < len; i++)
8653dda
+		n+=((int)str[i])*i;
8653dda
+	return n;
8653dda
+}
8653dda
+static inline int hashint(unsigned int num)
8653dda
+{
8653dda
+	return num % HASH_TABLE_SIZE;
8653dda
+}
8653dda
+#define HASH(_s, _l) hashint(strtoint((_s), (_l)))
8653dda
+void v4root_set(void);
8653dda
+void v4root_unset(void);
8653dda
+static int v4root_support(void);
8653dda
+
8653dda
+static struct exportent *v4root_create(char *, nfs_export *);
8653dda
+
8653dda
+int v4root_needed;
8653dda
+
8653dda
+static nfs_export pr_export = {
8653dda
+	.m_next = NULL,
8653dda
+	.m_client = NULL,
8653dda
+	.m_export = {
8653dda
+		.e_hostname = "*",
8653dda
+		.e_path = _PATH_PSEUDO_ROOT,
8653dda
+		.e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH
8653dda
+				| NFSEXP_NOSUBTREECHECK | NFSEXP_FSID
8653dda
+				| NFSEXP_CROSSMOUNT | NFSEXP_V4ROOT,
8653dda
+		.e_anonuid = 65534,
8653dda
+		.e_anongid = 65534,
8653dda
+		.e_squids = NULL,
8653dda
+		.e_nsquids = 0,
8653dda
+		.e_sqgids = NULL,
8653dda
+		.e_nsqgids = 0,
8653dda
+		.e_fsid = 0,
8653dda
+		.e_mountpoint = NULL,
8653dda
+	},
8653dda
+	.m_exported = 0,
8653dda
+	.m_xtabent = 1,
8653dda
+	.m_mayexport = 1,
8653dda
+	.m_changed = 0,
8653dda
+	.m_warned = 0,
8653dda
+};
8653dda
+static nfs_export *pseudo_root;
8653dda
+
8653dda
+/*
8653dda
+ * Return the number '/' in the path
8653dda
+ */
8653dda
+inline static int slash_count(char *path)
8653dda
+{
8653dda
+	int i, slashs=0;
8653dda
+
8653dda
+	for (i=0; i < strlen(path); i++) {
8653dda
+			if (path[i] == '/')
8653dda
+				slashs++;
8653dda
+	}
8653dda
+	return slashs;
8653dda
+}
8653dda
+/*
8653dda
+ * Make sure the kernel has pseudo root support.
8653dda
+ */
8653dda
+static int
8653dda
+v4root_support()
8653dda
+{
8653dda
+	static int kernel_support = -1;
8653dda
+	char *ptr, version[64];
8653dda
+	int major, minor;
8653dda
+	FILE *fp;
8653dda
+
8653dda
+	if (kernel_support != -1)
8653dda
+		return kernel_support;
8653dda
+
8653dda
+	kernel_support = 0;
8653dda
+	fp = fopen("/proc/fs/nfsd/exports", "r");
8653dda
+	if (fp == NULL)
8653dda
+		goto out;
8653dda
+
8653dda
+	ptr = fgets(version, 64, fp);
8653dda
+	fclose(fp);
8653dda
+	if (ptr == NULL)
8653dda
+		goto out;
8653dda
+
8653dda
+	while(*ptr && isdigit(*ptr) == 0)
8653dda
+		ptr++;
8653dda
+	if (*ptr == '\0')
8653dda
+		goto out;
8653dda
+
8653dda
+	major = minor = 0;
8653dda
+	sscanf(ptr, " %d.%d",&major, &minor);
8653dda
+	if (major >= 1 && minor >= 2)
8653dda
+		kernel_support = 1;
8653dda
+out:
8653dda
+	if (!kernel_support) {
8653dda
+		xlog(L_WARNING, "Kernel does not have pseudo root support.");
8653dda
+		xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0");
8653dda
+		xlog(L_WARNING, "is specfied in /etc/exports file.");
8653dda
+	}
8653dda
+
8653dda
+	return kernel_support;
8653dda
+}
8653dda
+/*
8653dda
+ * Build a table of pseudo exports by running through
8653dda
+ * the real export looking at the components of the path
8653dda
+ * that make up the export. Those path components, if
8653dda
+ * not exported, will become pseudo exports allowing them 
8653dda
+ * to be found when the kernel does an upcall looking for 
8653dda
+ * components of the v4 mount.
8653dda
+ */
8653dda
+void
8653dda
+v4root_set()
8653dda
+{
8653dda
+	nfs_export	*exp, *nxt;
8653dda
+	int	i;
8653dda
+	char *path, *ptr;
8653dda
+	char *hostname;
8653dda
+
8653dda
+	if (!v4root_needed)
8653dda
+		return;
8653dda
+
8653dda
+	if (!v4root_support())
8653dda
+		return;
8653dda
+
8653dda
+	pseudo_root = &pr_export;
8653dda
+
8653dda
+	for (i = 0; i < MCL_MAXTYPES; i++) {
8653dda
+		for (exp = exportlist[i].p_head; exp; exp = nxt) {
8653dda
+			nxt = exp->m_next;
8653dda
+			hostname = exp->m_export.e_hostname;
8653dda
+
8653dda
+			path = strdup(exp->m_export.e_path);
8653dda
+			ptr = path + 1;
8653dda
+			while ((ptr = strchr(ptr, '/')) != NULL) {
8653dda
+				*ptr = '\0';
8653dda
+				if (export_lookup(hostname, path, 0) == NULL)
8653dda
+					if (v4root_create(path, exp) == NULL) {
8653dda
+						xlog(L_WARNING, "v4root_set: Unable to create"
8653dda
+							"pseudo export for '%s'", path);
8653dda
+						break;
8653dda
+					}
8653dda
+				*ptr = '/';
8653dda
+				ptr++;
8653dda
+			}
8653dda
+
8653dda
+			free(path);
8653dda
+		}
8653dda
+	}
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * Unset the pseudo root export
8653dda
+ */
8653dda
+void
8653dda
+v4root_unset()
8653dda
+{
8653dda
+	pseudo_root = NULL;
8653dda
+	hash_mount_free();
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * The kernel will do an upcall looking for the pseudo
8653dda
+ * root via its fsid. When the wanted fsid equals 
8653dda
+ * PSEUDO_ROOT_FSID return the pseudo root export.
8653dda
+ */
8653dda
+struct exportent *
8653dda
+v4root_chkroot(int fsidtype, unsigned int fsidnum, char *fhuuid)
8653dda
+{
8653dda
+	if (pseudo_root == NULL)
8653dda
+		return NULL;
8653dda
+
8653dda
+	if (fsidtype != FSID_NUM)
8653dda
+		return NULL;
8653dda
+
8653dda
+	if (fsidnum != _PSEUDO_ROOT_FSID)
8653dda
+		return NULL;
8653dda
+
8653dda
+	return &pseudo_root->m_export;
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * Create a pseudo export, if one does not 
8653dda
+ * already exist.
8653dda
+ */
8653dda
+static struct exportent *
8653dda
+v4root_create(char *path, nfs_export *exp)
8653dda
+{
8653dda
+	static struct exportent *p_export = NULL;
8653dda
+	exports_t *pexp;
8653dda
+	char uuid_len = sizeof(uuid_t);
8653dda
+	char uuid[sizeof(uuid_t)];
8653dda
+
8653dda
+	if (pseudo_root == NULL)
8653dda
+		return NULL;
8653dda
+
8653dda
+	/* Check to see if the export already exists */
8653dda
+	get_uuid(path, NULL, uuid_len, uuid);
8653dda
+	if ((p_export = v4root_export(uuid, uuid_len)) != NULL)
8653dda
+		return p_export;
8653dda
+
8653dda
+	pexp = (exports_t *)malloc(sizeof(exports_t));
8653dda
+	if (pexp == NULL) {
8653dda
+		xlog(L_WARNING, "v4root_create: No memory for pseudo export");
8653dda
+		return NULL;
8653dda
+	}
8653dda
+	p_export = &pexp->p_export;
8653dda
+	pexp->path = strdup(path);
8653dda
+	if (pexp->path == 0) {
8653dda
+		xlog(L_WARNING, "v4root_create: No memory for pseudo path");
8653dda
+		free(pexp);
8653dda
+		return NULL;
8653dda
+	}
8653dda
+	pexp->uuid_len = uuid_len;
8653dda
+	memcpy(pexp->uuid, uuid, uuid_len);
8653dda
+
8653dda
+	dupexportent(&pexp->p_export, &pr_export.m_export);
8653dda
+	strcpy(p_export->e_path, path);
8653dda
+	p_export->e_flags &= ~NFSEXP_FSID;
8653dda
+	p_export->e_v4root = (void *)pexp;
8653dda
+
8653dda
+	hash_export_add(pexp, HASH(pexp->uuid, sizeof(uuid_t)));
8653dda
+
8653dda
+	xlog(D_CALL, "v4root_create: path '%s'", p_export->e_path);
8653dda
+
8653dda
+	return p_export;
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * See if the  pseudo export exists
8653dda
+ */
8653dda
+struct exportent *
8653dda
+v4root_lookup(char *path, nfs_export *exp)
8653dda
+{
8653dda
+	static struct exportent *p_export = NULL;
8653dda
+	char *epath = exp->m_export.e_path;
8653dda
+	int elen, plen;
8653dda
+	char uuid_len = sizeof(uuid_t);
8653dda
+	char uuid[sizeof(uuid_t)];
8653dda
+
8653dda
+	if (pseudo_root == NULL)
8653dda
+		return NULL;
8653dda
+
8653dda
+	/* Path needs to be a subset of e_path */
8653dda
+	elen = strlen(epath);
8653dda
+	plen = strlen(path);
8653dda
+	if (plen >= elen)
8653dda
+		return NULL;
8653dda
+
8653dda
+	if (memcmp(path, epath, plen) != 0)
8653dda
+		return NULL;
8653dda
+
8653dda
+	/* Now to see if the export exists */
8653dda
+	get_uuid(path, NULL, uuid_len, uuid);
8653dda
+	p_export = v4root_export(uuid, uuid_len);
8653dda
+
8653dda
+	return p_export;
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * Free a pseudo export
8653dda
+ */
8653dda
+void
8653dda
+v4root_free(struct exportent *p_export)
8653dda
+{
8653dda
+	exports_t *pexp = (exports_t *)p_export->e_v4root;
8653dda
+	hash_head *head = (hash_head *)pexp->head;
8653dda
+
8653dda
+	free(pexp->path);
8653dda
+	TAILQ_REMOVE(&head->h_head, pexp, list);
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * Return a pseudo export that match the given uuid
8653dda
+ */
8653dda
+struct exportent *
8653dda
+v4root_export(char *fhuuid, int uuidlen)
8653dda
+{
8653dda
+	struct exportent *p_export = NULL;
8653dda
+	exports_t *pexp;
8653dda
+	int len = MIN(uuidlen, sizeof(uuid_t));
8653dda
+
8653dda
+	if (pseudo_root == NULL)
8653dda
+		return NULL;
8653dda
+
8653dda
+	pexp = hash_export_lookup(fhuuid, len);
8653dda
+	if (pexp) {
8653dda
+		p_export = &pexp->p_export;
8653dda
+		xlog(D_CALL, "v4root_export: path %s", p_export->e_path);
8653dda
+	}
8653dda
+	return p_export;
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * Add pseudo export to export table
8653dda
+ */
8653dda
+static void hash_export_add(struct _exports_t *exp, int hash)
8653dda
+{
8653dda
+	hash_head *head;
8653dda
+
8653dda
+	head = &(exports_tbl[hash]);
8653dda
+	exp->head = head;
8653dda
+
8653dda
+	if (TAILQ_EMPTY(&head->h_head))
8653dda
+		TAILQ_INSERT_HEAD(&head->h_head, exp, list);
8653dda
+	else
8653dda
+		TAILQ_INSERT_TAIL(&head->h_head, exp, list);
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * Lookup a pseudo export using the uuid and inode number
8653dda
+ */
8653dda
+static exports_t *
8653dda
+hash_export_lookup(char *uuid, unsigned int uuidlen)
8653dda
+{
8653dda
+	exports_t *pexp;
8653dda
+	hash_head *head;
8653dda
+	int hash = HASH(uuid, uuidlen);
8653dda
+
8653dda
+	head = &(exports_tbl[hash]);
8653dda
+
8653dda
+	TAILQ_FOREACH(pexp, &head->h_head, list) {
8653dda
+		if (memcmp(pexp->uuid, uuid, uuidlen) == 0)
8653dda
+			return pexp;
8653dda
+	}
8653dda
+	return NULL;
8653dda
+
8653dda
+}
8653dda
+
8653dda
+/*
8653dda
+ * Free up pseudo export table
8653dda
+ */
8653dda
+static void hash_mount_free()
8653dda
+{
8653dda
+	hash_head *head;
8653dda
+	exports_t *e1, *e2;
8653dda
+	int hash;
8653dda
+
8653dda
+	for (hash=0; hash < HASH_TABLE_SIZE; hash++) {
8653dda
+		head = &(exports_tbl[hash]);
8653dda
+		if (head == NULL)
8653dda
+			continue;
8653dda
+		e1 = TAILQ_FIRST(&head->h_head);
8653dda
+		while (e1 != NULL) {
8653dda
+			free(e1->path);
8653dda
+			e2 =  TAILQ_NEXT(e1, list);
8653dda
+			TAILQ_REMOVE(&head->h_head, e1, list);
8653dda
+			free(e1);
8653dda
+			e1 = e2;
8653dda
+		}
8653dda
+		TAILQ_INIT(&head->h_head);
8653dda
+	}
8653dda
+}