[PATCH 2/3] Dynamic Pseudo Root
Steve Dickson
SteveD at redhat.com
Wed Feb 27 09:43:38 EST 2008
Author: Steve Dickson <steved at redhat.com>
Date: Wed Feb 27 08:57:07 2008 -0500
Main routines used in the support of dynamic pseudo roots.
Signed-off-by: Steve Dickson <steved at redhat.com>
diff --git a/support/export/Makefile.am b/support/export/Makefile.am
index 1ea1539..8a324b1 100644
--- a/support/export/Makefile.am
+++ b/support/export/Makefile.am
@@ -11,7 +11,7 @@ EXTRA_DIST = mount.x
noinst_LIBRARIES = libexport.a
libexport_a_SOURCES = client.c export.c hostname.c nfsctl.c rmtab.c \
- xtab.c mount_clnt.c mount_xdr.c
+ xtab.c mount_clnt.c mount_xdr.c v4root.c
BUILT_SOURCES = $(GENFILES)
noinst_HEADERS = mount.h
diff --git a/support/export/v4root.c b/support/export/v4root.c
new file mode 100644
index 0000000..f368be9
--- /dev/null
+++ b/support/export/v4root.c
@@ -0,0 +1,261 @@
+/*
+ * support/export/v4root.c
+ *
+ * Routines that create and destroy v4 pseudo roots
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "xlog.h"
+#include "exportfs.h"
+#include "nfslib.h"
+#include "misc.h"
+#include "mounts.h"
+#include "execute.h"
+
+#ifndef _PATH_PSEUDO_ROOT
+#define _PATH_PSEUDO_ROOT NFS_STATEDIR "/v4root"
+#endif
+
+struct mounts_t {
+ TAILQ_ENTRY(mounts_t) list;
+ nfs_export *exp;
+};
+TAILQ_HEAD(mount_list, mounts_t) head = LIST_HEAD_INITIALIZER(head);
+#define QUE_SORT(_m1) { \
+ if (TAILQ_EMPTY(&head)) \
+ TAILQ_INSERT_HEAD(&head, _m1, list); \
+ else { \
+ TAILQ_FOREACH(m2, &head, list) { \
+ if (strlen(m2->exp->m_export.e_path) > \
+ strlen(_m1->exp->m_export.e_path)) { \
+ TAILQ_INSERT_BEFORE(m2, _m1, list); \
+ break; \
+ } \
+ } \
+ if (m2 == NULL) \
+ TAILQ_INSERT_TAIL(&head, _m1, list); \
+ } \
+}
+
+void v4root_destroy(void);
+void v4root_create(void);
+void v4root_umountall(void);
+
+int v4root_needed, v4root_check;
+static char errbuf[BUFSIZ];
+static int v4root_mkroot(void);
+static int v4root_mkroot(void);
+
+static struct exportent pf_export = {
+ .e_hostname = "*",
+ .e_path = _PATH_PSEUDO_ROOT,
+ .m_path = _PATH_PSEUDO_ROOT,
+ .e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH
+ | NFSEXP_NOSUBTREECHECK | NFSEXP_FSID
+ | NFSEXP_CROSSMOUNT,
+ .e_anonuid = 65534,
+ .e_anongid = 65534,
+ .e_squids = NULL,
+ .e_nsquids = 0,
+ .e_sqgids = NULL,
+ .e_nsqgids = 0,
+ .e_fsid = 0,
+ .e_mountpoint = NULL,
+};
+static struct pseudo_ent {
+ struct exportent *export;
+ char *fh;
+} pseudo_export = {NULL, NULL};
+
+int
+v4root_mount(struct mountargs *args)
+{
+ int status;
+
+ status = mount (args->spec, args->node, args->type, args->flags, args->data);
+ if (status < 0) {
+ snprintf(errbuf, BUFSIZ, "mounting %s failed: ", args->node);
+ syserror(errbuf);
+ }
+
+ return status;
+}
+
+int
+v4root_umount(struct mountargs *args)
+{
+ int status;
+
+ if (args->flags)
+ status = umount2(args->node, args->flags);
+ else
+ status = umount(args->node);
+ if (status < 0) {
+ snprintf(errbuf, BUFSIZ, "unmounting %s failed: ", args->node);
+ syserror(errbuf);
+ }
+
+ return status;
+}
+
+/*
+ * Destroy the pseudo root
+ */
+void
+v4root_destroy()
+{
+ if (access(_PATH_PSEUDO_ROOT, F_OK) < 0)
+ return;
+
+ pseudo_export.export = NULL;
+ pseudo_export.fh = NULL;
+ lazy_umount(_PATH_PSEUDO_ROOT);
+ exec_rmdir(_PATH_PSEUDO_ROOT);
+}
+
+/*
+ * Create the pseudo root directory
+ */
+static int
+v4root_mkroot()
+{
+ struct stat sb;
+
+ if (stat(_PATH_PSEUDO_ROOT, &sb) < 0) {
+ if (errno != ENOENT) {
+ syserror(_PATH_PSEUDO_ROOT);
+ return 1;
+ }
+ if (mkdir(_PATH_PSEUDO_ROOT, 0755) < 0) {
+ syserror("Unable to create " _PATH_PSEUDO_ROOT);
+ return 1;
+ }
+ } else if (!S_ISDIR(sb.st_mode)) {
+ errno = ENOTDIR;
+ syserror(_PATH_PSEUDO_ROOT);
+ return 1;
+ }
+
+ return 0;
+}
+/*
+ * Create the pseudo tree by running through
+ * the exports and bind mounting them to
+ * directories in the tree
+ */
+void
+v4root_create()
+{
+ nfs_export *exp, *nxt;
+ struct mounts_t *m1, *m2;
+ char path[BUFSIZ];
+ int i;
+
+ if (!v4root_needed)
+ return;
+
+ if (v4root_mkroot())
+ return;
+
+ if (!is_mountpoint(_PATH_PSEUDO_ROOT))
+ tmpfs_mount(_PATH_PSEUDO_ROOT);
+
+ /*
+ * To build the mount tree correctly, we
+ * mount shortest path to longest path.
+ * So run through exports sorting the paths
+ * by shortest to longest into a queue
+ */
+ for (i = 0; i < MCL_MAXTYPES; i++)
+ for (exp = exportlist[i]; exp; exp = nxt) {
+ nxt = exp->m_next;
+
+ m1 = (struct mounts_t *)malloc(sizeof(struct mounts_t));
+ m1->exp = exp;
+ QUE_SORT(m1);
+ }
+
+ /*
+ * Now run through the sorted queue creating the
+ * bind mounts as well as freeing the que elements.
+ */
+ m1 = TAILQ_FIRST(&head);
+ while (m1 != NULL) {
+ exp = m1->exp;
+
+ snprintf(path, BUFSIZ, "%s/%s", _PATH_PSEUDO_ROOT,
+ exp->m_export.e_path);
+ exec_mkpath(path);
+ bind_mount(exp->m_export.e_path, path);
+
+ m2 = TAILQ_NEXT(m1, list);
+ free(m1);
+ m1 = m2;
+ }
+ pseudo_export.export = &pf_export;
+}
+
+void
+v4root_umountall()
+{
+ v4root_destroy();
+}
+struct exportent *
+v4root_chkroot(int fsidtype, unsigned int fsidnum, char *fhuuid)
+{
+ struct exportent *pseudo_root = NULL;
+
+ if (pseudo_export.export == NULL)
+ return NULL;
+
+ switch(fsidtype) {
+ case FSID_NUM:
+ if (fsidnum == 0)
+ pseudo_root = pseudo_export.export;
+ break;
+ }
+
+ return pseudo_root;
+}
+char *
+v4root_maproot(char *path)
+{
+ char *mpath;
+
+ if (pseudo_export.export == NULL)
+ return NULL;
+
+ if (strstr(path, _PATH_PSEUDO_ROOT) == NULL)
+ return NULL;
+
+ if (strcmp(path, _PATH_PSEUDO_ROOT) != NULL)
+ mpath = strdup(path + strlen(_PATH_PSEUDO_ROOT));
+ else
+ mpath = strdup(_PATH_PSEUDO_ROOT);
+
+ return mpath;
+}
+struct exportent *
+v4root_export(char *path)
+{
+ if (pseudo_export.export == NULL)
+ return NULL;
+
+ if (strcmp(path, _PATH_PSEUDO_ROOT) != NULL)
+ return NULL;
+
+ return pseudo_export.export;
+}
diff --git a/support/include/v4root.h b/support/include/v4root.h
new file mode 100644
index 0000000..1ec2451
--- /dev/null
+++ b/support/include/v4root.h
@@ -0,0 +1,17 @@
+/*
+ * support/include/v4root.h
+ *
+ * General support functions for Dynamic pseudo root functionality
+ *
+ */
+
+#ifndef V4ROOT_H
+#define V4ROOT_H
+
+extern int v4root_needed, v4root_check;
+
+extern struct exportent *v4root_chkroot(int , unsigned int , char *);
+extern char *v4root_maproot(char *);
+extern struct exportent *v4root_export(char *);
+
+#endif /* V4ROOT_H */
More information about the NFSv4
mailing list