diff --git a/nfs-utils-1.2.0-mntconf-negation.patch b/nfs-utils-1.2.0-mntconf-negation.patch deleted file mode 100644 index 6abd18a..0000000 --- a/nfs-utils-1.2.0-mntconf-negation.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff -up nfs-utils-1.2.0/utils/mount/configfile.c.orig nfs-utils-1.2.0/utils/mount/configfile.c ---- nfs-utils-1.2.0/utils/mount/configfile.c.orig 2009-09-30 13:57:48.647286000 -0400 -+++ nfs-utils-1.2.0/utils/mount/configfile.c 2009-09-30 14:50:05.365468000 -0400 -@@ -198,6 +198,15 @@ int inline check_vers(char *mopt, char * - } - return 0; - } -+int inline vers_is_set(char *mopt) -+{ -+ int i; -+ -+ for (i=0; versions[i]; i++) -+ if (strncasecmp(mopt, versions[i], strlen(versions[i])) == 0) -+ return 1; -+ return 0; -+} - /* - * Parse the given section of the configuration - * file to if there are any mount options set. -@@ -256,6 +265,8 @@ conf_parse_mntopts(char *section, char * - conf_free_list(list); - } - -+int do_version_negation; -+ - /* - * Concatenate options from the configuration file with the - * given options by building a link list of options from the -@@ -326,6 +337,8 @@ char *conf_get_mntopts(char *spec, char - strcat(config_opts, ","); - } - SLIST_FOREACH(entry, &head, entries) { -+ if (vers_is_set(entry->opt)) -+ do_version_negation = 1; - strcat(config_opts, entry->opt); - strcat(config_opts, ","); - } -diff -up nfs-utils-1.2.0/utils/mount/stropts.c.orig nfs-utils-1.2.0/utils/mount/stropts.c ---- nfs-utils-1.2.0/utils/mount/stropts.c.orig 2009-09-30 13:57:48.613288000 -0400 -+++ nfs-utils-1.2.0/utils/mount/stropts.c 2009-09-30 14:59:56.716461000 -0400 -@@ -588,6 +588,7 @@ out_fail: - po_destroy(options); - return result; - } -+extern int do_version_negation; - - /* - * This is a single pass through the fg/bg loop. -@@ -607,12 +608,20 @@ static int nfs_try_mount(struct nfsmount - if (errno != EPROTONOSUPPORT) - break; - } -- case 2: - case 3: -+ if (do_version_negation) -+ po_remove_all(mi->options, "nfsvers"); -+ case 2: - result = nfs_try_mount_v3v2(mi); - break; - case 4: - result = nfs_try_mount_v4(mi); -+ if (do_version_negation && !result) { -+ if (errno == EPROTONOSUPPORT) { -+ po_remove_all(mi->options, "nfsvers"); -+ result = nfs_try_mount_v3v2(mi); -+ } -+ } - break; - default: - errno = EIO; diff --git a/nfs-utils-1.2.0-mntconf-vers.patch b/nfs-utils-1.2.0-mntconf-vers.patch deleted file mode 100644 index 4a5ba52..0000000 --- a/nfs-utils-1.2.0-mntconf-vers.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff -up nfs-utils-1.2.0/utils/mount/configfile.c.orig nfs-utils-1.2.0/utils/mount/configfile.c ---- nfs-utils-1.2.0/utils/mount/configfile.c.orig 2009-10-02 11:10:01.000000000 -0400 -+++ nfs-utils-1.2.0/utils/mount/configfile.c 2009-10-02 11:14:30.000000000 -0400 -@@ -185,6 +185,20 @@ void free_all(void) - free(entry); - } - } -+static char *versions[] = {"v2", "v3", "v4", "vers", "nfsvers", NULL}; -+int inline check_vers(char *mopt, char *field) -+{ -+ int i; -+ -+ if (strncmp("mountvers", field, strlen("mountvers") != 0 && -+ (strcasecmp(field, "nfsvers") == 0 || -+ strcasecmp(field, "vers") == 0))) { -+ for (i=0; versions[i]; i++) -+ if (strcasestr(mopt, versions[i]) != NULL) -+ return 1; -+ } -+ return 0; -+} - /* - * Parse the given section of the configuration - * file to if there are any mount options set. -@@ -207,6 +221,12 @@ conf_parse_mntopts(char *section, char * - snprintf(buf, BUFSIZ, "%s=", node->field); - if (opts && strcasestr(opts, buf) != NULL) - continue; -+ /* -+ * Protocol verions can be set in a number of ways -+ */ -+ if (opts && check_vers(opts, node->field)) -+ continue; -+ - if (lookup_entry(node->field) != NULL) - continue; - buf[0] = '\0'; diff --git a/nfs-utils-1.2.0-mount-vers4.patch b/nfs-utils-1.2.0-mount-vers4.patch deleted file mode 100644 index e3969ad..0000000 --- a/nfs-utils-1.2.0-mount-vers4.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff -up nfs-utils-1.2.0/utils/mount/nfsmount.conf.orig nfs-utils-1.2.0/utils/mount/nfsmount.conf ---- nfs-utils-1.2.0/utils/mount/nfsmount.conf.orig 2009-09-30 11:32:14.148326000 -0400 -+++ nfs-utils-1.2.0/utils/mount/nfsmount.conf 2009-09-30 11:35:24.714787000 -0400 -@@ -24,12 +24,12 @@ - # All reads and writes to the 'nfsserver.foo.com' server - # will be done with 32k (32768 bytes) block sizes. - # --#[ NFSMount_Global_Options ] -+[ NFSMount_Global_Options ] - # This statically named section defines global mount - # options that can be applied on all NFS mount. - # --# Protocol Version [2,3] --# Nfsvers=3 -+# Protocol Version [2,3,4] -+Nfsvers=3 - # Network Transport [Udp,Tcp,Rdma] - # Proto=Tcp - # -diff -up nfs-utils-1.2.0/utils/mount/stropts.c.orig nfs-utils-1.2.0/utils/mount/stropts.c ---- nfs-utils-1.2.0/utils/mount/stropts.c.orig 2009-09-30 11:32:14.214327000 -0400 -+++ nfs-utils-1.2.0/utils/mount/stropts.c 2009-09-30 11:34:35.841020000 -0400 -@@ -601,7 +601,7 @@ static int nfs_try_mount(struct nfsmount - - switch (mi->version) { - case 0: -- if (linux_version_code() > MAKE_VERSION(2, 6, 31)) { -+ if (linux_version_code() >= MAKE_VERSION(2, 6, 31)) { - errno = 0; - result = nfs_try_mount_v4(mi); - if (errno != EPROTONOSUPPORT) diff --git a/nfs-utils-1.2.0-v4root-rel6.patch b/nfs-utils-1.2.0-v4root-rel6.patch deleted file mode 100644 index 20856bc..0000000 --- a/nfs-utils-1.2.0-v4root-rel6.patch +++ /dev/null @@ -1,716 +0,0 @@ -diff --git a/support/export/xtab.c b/support/export/xtab.c -index 3b1dcce..2a43193 100644 ---- a/support/export/xtab.c -+++ b/support/export/xtab.c -@@ -19,7 +19,9 @@ - #include "exportfs.h" - #include "xio.h" - #include "xlog.h" -+#include "v4root.h" - -+int v4root_needed; - static void cond_rename(char *newfile, char *oldfile); - - static int -@@ -36,6 +38,8 @@ xtab_read(char *xtab, char *lockfn, int is_export) - if ((lockid = xflock(lockfn, "r")) < 0) - return 0; - setexportent(xtab, "r"); -+ if (is_export == 1) -+ v4root_needed = 1; - while ((xp = getexportent(is_export==0, 0)) != NULL) { - if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) && - !(exp = export_create(xp, is_export!=1))) { -@@ -48,6 +52,8 @@ xtab_read(char *xtab, char *lockfn, int is_export) - case 1: - exp->m_xtabent = 1; - exp->m_mayexport = 1; -+ if ((xp->e_flags & NFSEXP_FSID) && xp->e_fsid == 0) -+ v4root_needed = 0; - break; - case 2: - exp->m_exported = -1;/* may be exported */ -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index a5cf482..1ad41e2 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -12,6 +12,17 @@ - #include - #include "nfslib.h" - -+enum nfsd_fsid { -+ FSID_DEV = 0, -+ FSID_NUM, -+ FSID_MAJOR_MINOR, -+ FSID_ENCODE_DEV, -+ FSID_UUID4_INUM, -+ FSID_UUID8, -+ FSID_UUID16, -+ FSID_UUID16_INUM, -+}; -+ - enum { - MCL_FQDN = 0, - MCL_SUBNETWORK, -diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h -index f7a99ba..76953ac 100644 ---- a/support/include/nfs/export.h -+++ b/support/include/nfs/export.h -@@ -24,6 +24,7 @@ - #define NFSEXP_FSID 0x2000 - #define NFSEXP_CROSSMOUNT 0x4000 - #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ --#define NFSEXP_ALLFLAGS 0xFFFF -+#define NFSEXP_V4ROOT 0x10000 -+#define NFSEXP_ALLFLAGS 0x1FFFF - - #endif /* _NSF_EXPORT_H */ -diff --git a/support/include/nfslib.h b/support/include/nfslib.h -index 537a31e..e4777dd 100644 ---- a/support/include/nfslib.h -+++ b/support/include/nfslib.h -@@ -88,6 +88,7 @@ struct exportent { - int e_fslocmethod; - char * e_fslocdata; - char * e_uuid; -+ void * e_v4root; - struct sec_entry e_secinfo[SECFLAVOR_COUNT+1]; - }; - -diff --git a/support/include/v4root.h b/support/include/v4root.h -new file mode 100644 -index 0000000..43b1d2e ---- /dev/null -+++ b/support/include/v4root.h -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2009 Red Hat -+ * support/include/v4root.h -+ * -+ * Support routines for dynamic pseudo roots. -+ * -+ */ -+ -+#ifndef V4ROOT_H -+#define V4ROOT_H -+ -+extern int v4root_needed; -+ -+extern struct exportent *v4root_chkroot(int , unsigned int , char *); -+extern struct exportent *v4root_export(char *, int); -+extern struct exportent *v4root_create(char *, nfs_export *, int); -+extern void v4root_free(struct exportent *); -+extern void v4root_unset(void), v4root_set(void); -+ -+#endif /* V4ROOT_H */ -diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am -index 1e76cf8..eba81fc 100644 ---- a/utils/mountd/Makefile.am -+++ b/utils/mountd/Makefile.am -@@ -8,7 +8,7 @@ KPREFIX = @kprefix@ - sbin_PROGRAMS = mountd - - mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \ -- svc_run.c fsloc.c mountd.h -+ svc_run.c fsloc.c v4root.c mountd.h - mountd_LDADD = ../../support/export/libexport.a \ - ../../support/nfs/libnfs.a \ - ../../support/misc/libmisc.a \ -diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c -index 575f207..041a745 100644 ---- a/utils/mountd/auth.c -+++ b/utils/mountd/auth.c -@@ -20,6 +20,7 @@ - #include "exportfs.h" - #include "mountd.h" - #include "xmalloc.h" -+#include "v4root.h" - - enum auth_error - { -@@ -98,10 +99,13 @@ auth_reload() - last_inode = stb.st_ino; - } - -+ v4root_unset(); - export_freeall(); - memset(&my_client, 0, sizeof(my_client)); - xtab_export_read(); - check_useipaddr(); -+ v4root_set(); -+ - ++counter; - - return counter; -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index e4e2f22..d631570 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -32,23 +32,12 @@ - #include "xmalloc.h" - #include "fsloc.h" - #include "pseudoflavors.h" -+#include "v4root.h" - - #ifdef USE_BLKID - #include "blkid/blkid.h" - #endif - -- --enum nfsd_fsid { -- FSID_DEV = 0, -- FSID_NUM, -- FSID_MAJOR_MINOR, -- FSID_ENCODE_DEV, -- FSID_UUID4_INUM, -- FSID_UUID8, -- FSID_UUID16, -- FSID_UUID16_INUM, --}; -- - /* - * Support routines for text-based upcalls. - * Fields are separated by spaces. -@@ -135,6 +124,8 @@ void auth_unix_gid(FILE *f) - if (readline(fileno(f), &lbuf, &lbuflen) != 1) - return; - -+ xlog(D_CALL, "auth_unix_gid: '%s'", lbuf); -+ - cp = lbuf; - if (qword_get_int(&cp, &uid) != 0) - return; -@@ -391,6 +382,12 @@ void nfsd_fh(FILE *f) - - auth_reload(); - -+ /* Check to see if the kenel is looking for the pseudo root */ -+ if ((found = v4root_chkroot(fsidtype, fsidnum, fhuuid))) { -+ found_path = strdup(found->e_path); -+ goto found; -+ } -+ - /* Now determine export point for this fsid/domain */ - for (i=0 ; i < MCL_MAXTYPES; i++) { - nfs_export *next_exp; -@@ -511,7 +508,23 @@ void nfsd_fh(FILE *f) - */ - goto out; - } -+ if (!found) { -+ /* -+ * See if this is a pesudo export -+ */ -+ switch(fsidtype) { -+ case FSID_UUID4_INUM: -+ case FSID_UUID8: -+ case FSID_UUID16: -+ case FSID_UUID16_INUM: -+ found = v4root_export(fhuuid, uuidlen); -+ break; -+ } -+ if (found) -+ found_path = strdup(found->e_path); -+ } - -+found: - if (found) - if (cache_export_ent(dom, found, found_path) < 0) - found = 0; -@@ -629,6 +642,7 @@ void nfsd_export(FILE *f) - int found_type = 0; - struct in_addr addr; - struct hostent *he = NULL; -+ struct exportent *v4root = NULL; - - - if (readline(fileno(f), &lbuf, &lbuflen) != 1) -@@ -663,10 +677,18 @@ void nfsd_export(FILE *f) - path[l] == '/' && - is_mountpoint(path))) - /* ok */; -- else -+ else { -+ /* See if the path is part of the psuedo root */ -+ if (v4root_needed && !v4root) -+ v4root = v4root_create(path, exp, TRUE); - continue; -- } else if (strcmp(path, exp->m_export.e_path) != 0) -+ } -+ } else if (strcmp(path, exp->m_export.e_path) != 0) { -+ /* See if the path is part of the psuedo root */ -+ if (v4root_needed && !v4root) -+ v4root = v4root_create(path, exp, TRUE); - continue; -+ } - if (use_ipaddr) { - if (he == NULL) { - if (!inet_aton(dom, &addr)) -@@ -705,17 +727,28 @@ void nfsd_export(FILE *f) - } - - if (found) { -+ xlog(D_CALL, "nfsd_export: found: path %s", path); - if (dump_to_cache(f, dom, path, &found->m_export) < 0) { - xlog(L_WARNING, - "Cannot export %s, possibly unsupported filesystem" - " or fsid= required", path); - dump_to_cache(f, dom, path, NULL); - } -- } else { -+ } else if (v4root) { -+ xlog(D_CALL, "nfsd_export: vroot: path %s", path); -+ dump_to_cache(f, dom, path, v4root); -+ found = (nfs_export *)v4root; -+ } else { - dump_to_cache(f, dom, path, NULL); - } - out: -- xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL); -+ /* -+ * If a psuedo export was create and its not needed -+ * free it up. -+ */ -+ if (v4root && found != (nfs_export *)v4root) -+ v4root_free(v4root); -+ - if (dom) free(dom); - if (path) free(path); - if (he) free(he); -@@ -743,7 +776,9 @@ void cache_open(void) - if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid) - continue; - sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name); -- cachelist[i].f = fopen(path, "r+"); -+ if ((cachelist[i].f = fopen(path, "r+")) == NULL) -+ xlog(L_ERROR, "cache_open: Unable to open '%s': errno %d (%s)", -+ path, errno, strerror(errno)); - } - } - -diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c -new file mode 100644 -index 0000000..8de2ab6 ---- /dev/null -+++ b/utils/mountd/v4root.c -@@ -0,0 +1,420 @@ -+/* -+ * Copyright (C) 2009 Red Hat -+ * -+ * support/export/v4root.c -+ * -+ * Routines used to support NFSv4 pseudo roots -+ * -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "xlog.h" -+#include "exportfs.h" -+#include "nfslib.h" -+#include "misc.h" -+#include "v4root.h" -+ -+#ifndef _PATH_PSEUDO_ROOT -+#define _PATH_PSEUDO_ROOT "/" -+#endif -+ -+#ifndef _PSEUDO_ROOT_FSID -+#define _PSEUDO_ROOT_FSID 0 -+#endif -+ -+extern int get_uuid(char *path, char *uuid, int uuidlen, char *u); -+ -+typedef struct _exports_t { -+ TAILQ_ENTRY(_exports_t) list; -+ char *path; -+ void *head; -+ char uuid_len; -+ char uuid[sizeof(uuid_t)]; -+ struct exportent p_export; -+} exports_t; -+ -+#define HASH_TABLE_SIZE 1021 -+typedef struct _hash_head { -+ TAILQ_HEAD(export_list, _exports_t) h_head; -+} hash_head; -+hash_head exports_tbl[HASH_TABLE_SIZE]; -+ -+ -+static exports_t *hash_export_lookup(char *, unsigned int); -+static void hash_export_add(struct _exports_t *, int); -+static void hash_mount_free(void); -+ -+static inline unsigned int strtoint(char *str, int len) -+{ -+ unsigned int n = 0; -+ int i; -+ -+ for (i=0; i < len; i++) -+ n+=((int)str[i])*i; -+ return n; -+} -+static inline int hashint(unsigned int num) -+{ -+ return num % HASH_TABLE_SIZE; -+} -+#define HASH(_s, _l) hashint(strtoint((_s), (_l))) -+void v4root_set(void); -+void v4root_unset(void); -+static int v4root_support(void); -+ -+int v4root_needed; -+ -+static nfs_export pr_export = { -+ .m_next = NULL, -+ .m_client = NULL, -+ .m_export = { -+ .e_hostname = "*", -+ .e_path = _PATH_PSEUDO_ROOT, -+ .e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH -+ | NFSEXP_NOSUBTREECHECK | NFSEXP_FSID -+ | NFSEXP_CROSSMOUNT | NFSEXP_V4ROOT, -+ .e_anonuid = 65534, -+ .e_anongid = 65534, -+ .e_squids = NULL, -+ .e_nsquids = 0, -+ .e_sqgids = NULL, -+ .e_nsqgids = 0, -+ .e_fsid = 0, -+ .e_mountpoint = NULL, -+ }, -+ .m_exported = 0, -+ .m_xtabent = 1, -+ .m_mayexport = 1, -+ .m_changed = 0, -+ .m_warned = 0, -+}; -+static nfs_export *pseudo_root; -+ -+/* -+ * Return the number '/' in the path -+ */ -+inline static int slash_count(char *path) -+{ -+ int i, slashs=0; -+ -+ for (i=0; i < strlen(path); i++) { -+ if (path[i] == '/') -+ slashs++; -+ } -+ return slashs; -+} -+/* -+ * Make sure the kernel has pseudo root support. -+ */ -+static int -+v4root_support() -+{ -+ static int kernel_support = -1; -+ char *ptr, version[64]; -+ int major, minor; -+ FILE *fp; -+ -+ if (kernel_support != -1) -+ return kernel_support; -+ -+ kernel_support = 0; -+ fp = fopen("/proc/fs/nfsd/exports", "r"); -+ if (fp == NULL) -+ goto out; -+ -+ ptr = fgets(version, 64, fp); -+ fclose(fp); -+ if (ptr == NULL) -+ goto out; -+ -+ while(*ptr && isdigit(*ptr) == 0) -+ ptr++; -+ if (*ptr == '\0') -+ goto out; -+ -+ major = minor = 0; -+ sscanf(ptr, " %d.%d",&major, &minor); -+ if (major >= 1 && minor >= 2) -+ kernel_support = 1; -+out: -+ if (!kernel_support) { -+ xlog(L_WARNING, "Kernel does not have pseudo root support."); -+ xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0"); -+ xlog(L_WARNING, "is specfied in /etc/exports file."); -+ } -+ -+ return kernel_support; -+} -+/* -+ * Build a table of pseudo exports by running through -+ * the real export looking at the components of the path -+ * that make up the export. Those path components, if -+ * not exported, will become pseudo exports allowing them -+ * to be found when the kernel does an upcall looking for -+ * components of the v4 mount. -+ */ -+void -+v4root_set() -+{ -+ nfs_export *exp, *nxt; -+ int i, slcnt; -+ char *e_path, *path, *ptr, *comp; -+ char *hostname; -+ -+ if (!v4root_needed) -+ return; -+ -+ if (!v4root_support()) -+ return; -+ -+ pseudo_root = &pr_export; -+ -+ for (i = 0; i < MCL_MAXTYPES; i++) { -+ for (exp = exportlist[i].p_head; exp; exp = nxt) { -+ nxt = exp->m_next; -+ e_path = exp->m_export.e_path; -+ hostname = exp->m_export.e_hostname; -+ -+ slcnt = slash_count(e_path); -+ if (slcnt == 1) -+ continue; -+ slcnt--; /* knock off the leanding '/' */ -+ -+ path = strdup(e_path); -+ if (path == NULL) { -+ xlog(L_WARNING, "v4root_set: No memory for pseudo export"); -+ return; -+ } -+ -+ /* -+ * Run through each component of the path to -+ * see if a pseudo export should be created. -+ */ -+ comp = path+1; -+ do { -+ if ((ptr = strchr(comp, '/')) != NULL) -+ *ptr = '\0'; -+ -+ if (export_lookup(hostname, path, 0) == NULL) -+ if (v4root_create(path, exp, FALSE) == NULL) { -+ xlog(L_WARNING, -+ "v4root_set: Unable to create pseudo export" -+ "for '%s'", path); -+ break; -+ } -+ -+ if (ptr) { -+ *ptr = '/'; -+ comp = ptr+1; -+ } -+ } while (--slcnt > 0); -+ free(path); -+ } -+ } -+} -+ -+/* -+ * Unset the pseudo root export -+ */ -+void -+v4root_unset() -+{ -+ pseudo_root = NULL; -+ hash_mount_free(); -+} -+ -+/* -+ * The kernel will do an upcall looking for the pseudo -+ * root via its fsid. When the wanted fsid equals -+ * PSEUDO_ROOT_FSID return the pseudo root export. -+ */ -+struct exportent * -+v4root_chkroot(int fsidtype, unsigned int fsidnum, char *fhuuid) -+{ -+ struct exportent *p_export = NULL; -+ -+ if (pseudo_root == NULL) -+ return NULL; -+ -+ switch(fsidtype) { -+ case FSID_NUM: -+ if (fsidnum == _PSEUDO_ROOT_FSID) { -+ p_export = &pseudo_root->m_export; -+ strncpy(p_export->e_path, _PATH_PSEUDO_ROOT, -+ NFS_MAXPATHLEN); -+ } -+ break; -+ } -+ -+ return p_export; -+} -+ -+/* -+ * Create a pseudo export, if one does not -+ * already exist. -+ */ -+struct exportent * -+v4root_create(char *path, nfs_export *exp, int docheck) -+{ -+ static struct exportent *p_export = NULL; -+ exports_t *pexp; -+ char *epath = exp->m_export.e_path; -+ int elen, plen; -+ char uuid_len = sizeof(uuid_t); -+ char uuid[sizeof(uuid_t)]; -+ -+ if (pseudo_root == NULL) -+ return NULL; -+ -+ if (docheck) { -+ -+ /* Path needs to be a subset of e_path */ -+ elen = strlen(epath); -+ plen = strlen(path); -+ if (plen >= elen) -+ return NULL; -+ -+ if (memcmp(path, epath, plen) != 0) -+ return NULL; -+ } -+ -+ /* Check to see if the export already exists */ -+ get_uuid(path, NULL, uuid_len, uuid); -+ if ((p_export = v4root_export(uuid, uuid_len)) != NULL) -+ return p_export; -+ -+ pexp = (exports_t *)malloc(sizeof(exports_t)); -+ if (pexp == NULL) { -+ xlog(L_WARNING, "v4root_create: No memory for pseudo export"); -+ return NULL; -+ } -+ p_export = &pexp->p_export; -+ pexp->path = strdup(path); -+ if (pexp->path == 0) { -+ xlog(L_WARNING, "v4root_create: No memory for pseudo path"); -+ free(pexp); -+ return NULL; -+ } -+ pexp->uuid_len = uuid_len; -+ memcpy(pexp->uuid, uuid, uuid_len); -+ -+ dupexportent(&pexp->p_export, &pr_export.m_export); -+ strcpy(p_export->e_path, path); -+ p_export->e_flags &= ~NFSEXP_FSID; -+ p_export->e_v4root = (void *)pexp; -+ -+ hash_export_add(pexp, HASH(pexp->uuid, sizeof(uuid_t))); -+ -+ xlog(D_CALL, "v4root_create: path '%s'", p_export->e_path); -+ -+ return p_export; -+} -+ -+/* -+ * Free a pseudo export -+ */ -+void -+v4root_free(struct exportent *p_export) -+{ -+ exports_t *pexp = (exports_t *)p_export->e_v4root; -+ hash_head *head = (hash_head *)pexp->head; -+ -+ free(pexp->path); -+ TAILQ_REMOVE(&head->h_head, pexp, list); -+} -+ -+/* -+ * Return a pseudo export that match the given uuid -+ */ -+struct exportent * -+v4root_export(char *fhuuid, int uuidlen) -+{ -+ struct exportent *p_export = NULL; -+ exports_t *pexp; -+ int len = MIN(uuidlen, sizeof(uuid_t)); -+ -+ if (pseudo_root == NULL) -+ return NULL; -+ -+ pexp = hash_export_lookup(fhuuid, len); -+ if (pexp) { -+ p_export = &pexp->p_export; -+ xlog(D_CALL, "v4root_export: path %s", p_export->e_path); -+ } -+ return p_export; -+} -+ -+/* -+ * Add pseudo export to export table -+ */ -+static void hash_export_add(struct _exports_t *exp, int hash) -+{ -+ hash_head *head; -+ -+ head = &(exports_tbl[hash]); -+ exp->head = head; -+ -+ if (TAILQ_EMPTY(&head->h_head)) -+ TAILQ_INSERT_HEAD(&head->h_head, exp, list); -+ else -+ TAILQ_INSERT_TAIL(&head->h_head, exp, list); -+} -+ -+/* -+ * Lookup a pseudo export using the uuid and inode number -+ */ -+static exports_t * -+hash_export_lookup(char *uuid, unsigned int uuidlen) -+{ -+ exports_t *pexp; -+ hash_head *head; -+ int hash = HASH(uuid, uuidlen); -+ -+ head = &(exports_tbl[hash]); -+ -+ TAILQ_FOREACH(pexp, &head->h_head, list) { -+ if (memcmp(pexp->uuid, uuid, uuidlen) == 0) -+ return pexp; -+ } -+ return NULL; -+ -+} -+ -+/* -+ * Free up pseudo export table -+ */ -+static void hash_mount_free() -+{ -+ hash_head *head; -+ exports_t *e1, *e2; -+ int hash; -+ -+ for (hash=0; hash < HASH_TABLE_SIZE; hash++) { -+ head = &(exports_tbl[hash]); -+ if (head == NULL) -+ continue; -+ e1 = TAILQ_FIRST(&head->h_head); -+ while (e1 != NULL) { -+ free(e1->path); -+ e2 = TAILQ_NEXT(e1, list); -+ TAILQ_REMOVE(&head->h_head, e1, list); -+ free(e1); -+ e1 = e2; -+ } -+ TAILQ_INIT(&head->h_head); -+ } -+} diff --git a/nfs-utils-1.2.0-v4root-rel7.patch b/nfs-utils-1.2.0-v4root-rel7.patch new file mode 100644 index 0000000..dc010a2 --- /dev/null +++ b/nfs-utils-1.2.0-v4root-rel7.patch @@ -0,0 +1,699 @@ +diff -up nfs-utils-1.2.0/support/export/xtab.c.save nfs-utils-1.2.0/support/export/xtab.c +--- nfs-utils-1.2.0/support/export/xtab.c.save 2009-10-20 08:46:50.000000000 -0400 ++++ nfs-utils-1.2.0/support/export/xtab.c 2009-10-20 08:47:26.000000000 -0400 +@@ -19,7 +19,9 @@ + #include "exportfs.h" + #include "xio.h" + #include "xlog.h" ++#include "v4root.h" + ++int v4root_needed; + static void cond_rename(char *newfile, char *oldfile); + + static int +@@ -36,6 +38,8 @@ xtab_read(char *xtab, char *lockfn, int + if ((lockid = xflock(lockfn, "r")) < 0) + return 0; + setexportent(xtab, "r"); ++ if (is_export == 1) ++ v4root_needed = 1; + while ((xp = getexportent(is_export==0, 0)) != NULL) { + if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) && + !(exp = export_create(xp, is_export!=1))) { +@@ -48,6 +52,8 @@ xtab_read(char *xtab, char *lockfn, int + case 1: + exp->m_xtabent = 1; + exp->m_mayexport = 1; ++ if ((xp->e_flags & NFSEXP_FSID) && xp->e_fsid == 0) ++ v4root_needed = 0; + break; + case 2: + exp->m_exported = -1;/* may be exported */ +diff -up nfs-utils-1.2.0/support/include/exportfs.h.save nfs-utils-1.2.0/support/include/exportfs.h +--- nfs-utils-1.2.0/support/include/exportfs.h.save 2009-10-20 08:46:50.000000000 -0400 ++++ nfs-utils-1.2.0/support/include/exportfs.h 2009-10-20 08:47:07.000000000 -0400 +@@ -12,6 +12,17 @@ + #include + #include "nfslib.h" + ++enum nfsd_fsid { ++ FSID_DEV = 0, ++ FSID_NUM, ++ FSID_MAJOR_MINOR, ++ FSID_ENCODE_DEV, ++ FSID_UUID4_INUM, ++ FSID_UUID8, ++ FSID_UUID16, ++ FSID_UUID16_INUM, ++}; ++ + enum { + MCL_FQDN = 0, + MCL_SUBNETWORK, +diff -up nfs-utils-1.2.0/support/include/nfs/export.h.save nfs-utils-1.2.0/support/include/nfs/export.h +--- nfs-utils-1.2.0/support/include/nfs/export.h.save 2009-10-20 08:46:50.000000000 -0400 ++++ nfs-utils-1.2.0/support/include/nfs/export.h 2009-10-20 08:47:07.000000000 -0400 +@@ -24,6 +24,7 @@ + #define NFSEXP_FSID 0x2000 + #define NFSEXP_CROSSMOUNT 0x4000 + #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ +-#define NFSEXP_ALLFLAGS 0xFFFF ++#define NFSEXP_V4ROOT 0x10000 ++#define NFSEXP_ALLFLAGS 0x1FFFF + + #endif /* _NSF_EXPORT_H */ +diff -up nfs-utils-1.2.0/support/include/nfslib.h.save nfs-utils-1.2.0/support/include/nfslib.h +--- nfs-utils-1.2.0/support/include/nfslib.h.save 2009-10-20 08:46:50.000000000 -0400 ++++ nfs-utils-1.2.0/support/include/nfslib.h 2009-10-20 08:47:07.000000000 -0400 +@@ -88,6 +88,7 @@ struct exportent { + int e_fslocmethod; + char * e_fslocdata; + char * e_uuid; ++ void * e_v4root; + struct sec_entry e_secinfo[SECFLAVOR_COUNT+1]; + }; + +diff -up /dev/null nfs-utils-1.2.0/support/include/v4root.h +--- /dev/null 2009-10-15 16:13:05.251004788 -0400 ++++ nfs-utils-1.2.0/support/include/v4root.h 2009-10-20 08:47:16.000000000 -0400 +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (C) 2009 Red Hat ++ * support/include/v4root.h ++ * ++ * Support routines for dynamic pseudo roots. ++ * ++ */ ++ ++#ifndef V4ROOT_H ++#define V4ROOT_H ++ ++extern int v4root_needed; ++ ++extern struct exportent *v4root_chkroot(int , unsigned int , char *); ++extern struct exportent *v4root_export(char *, int); ++extern struct exportent *v4root_lookup(char *, nfs_export *); ++extern void v4root_free(struct exportent *); ++extern void v4root_unset(void), v4root_set(void); ++ ++#endif /* V4ROOT_H */ +diff -up nfs-utils-1.2.0/utils/mountd/auth.c.save nfs-utils-1.2.0/utils/mountd/auth.c +--- nfs-utils-1.2.0/utils/mountd/auth.c.save 2009-10-20 08:46:50.000000000 -0400 ++++ nfs-utils-1.2.0/utils/mountd/auth.c 2009-10-20 08:47:26.000000000 -0400 +@@ -20,6 +20,7 @@ + #include "exportfs.h" + #include "mountd.h" + #include "xmalloc.h" ++#include "v4root.h" + + enum auth_error + { +@@ -98,10 +99,13 @@ auth_reload() + last_inode = stb.st_ino; + } + ++ v4root_unset(); + export_freeall(); + memset(&my_client, 0, sizeof(my_client)); + xtab_export_read(); + check_useipaddr(); ++ v4root_set(); ++ + ++counter; + + return counter; +diff -up nfs-utils-1.2.0/utils/mountd/cache.c.save nfs-utils-1.2.0/utils/mountd/cache.c +--- nfs-utils-1.2.0/utils/mountd/cache.c.save 2009-10-20 08:46:50.000000000 -0400 ++++ nfs-utils-1.2.0/utils/mountd/cache.c 2009-10-20 08:47:21.000000000 -0400 +@@ -32,23 +32,12 @@ + #include "xmalloc.h" + #include "fsloc.h" + #include "pseudoflavors.h" ++#include "v4root.h" + + #ifdef USE_BLKID + #include "blkid/blkid.h" + #endif + +- +-enum nfsd_fsid { +- FSID_DEV = 0, +- FSID_NUM, +- FSID_MAJOR_MINOR, +- FSID_ENCODE_DEV, +- FSID_UUID4_INUM, +- FSID_UUID8, +- FSID_UUID16, +- FSID_UUID16_INUM, +-}; +- + /* + * Support routines for text-based upcalls. + * Fields are separated by spaces. +@@ -135,6 +124,8 @@ void auth_unix_gid(FILE *f) + if (readline(fileno(f), &lbuf, &lbuflen) != 1) + return; + ++ xlog(D_CALL, "auth_unix_gid: '%s'", lbuf); ++ + cp = lbuf; + if (qword_get_int(&cp, &uid) != 0) + return; +@@ -391,6 +382,12 @@ void nfsd_fh(FILE *f) + + auth_reload(); + ++ /* Check to see if the kenel is looking for the pseudo root */ ++ if ((found = v4root_chkroot(fsidtype, fsidnum, fhuuid))) { ++ found_path = strdup(found->e_path); ++ goto found; ++ } ++ + /* Now determine export point for this fsid/domain */ + for (i=0 ; i < MCL_MAXTYPES; i++) { + nfs_export *next_exp; +@@ -511,7 +508,23 @@ void nfsd_fh(FILE *f) + */ + goto out; + } ++ if (!found) { ++ /* ++ * See if this is a pesudo export ++ */ ++ switch(fsidtype) { ++ case FSID_UUID4_INUM: ++ case FSID_UUID8: ++ case FSID_UUID16: ++ case FSID_UUID16_INUM: ++ found = v4root_export(fhuuid, uuidlen); ++ break; ++ } ++ if (found) ++ found_path = strdup(found->e_path); ++ } + ++found: + if (found) + if (cache_export_ent(dom, found, found_path) < 0) + found = 0; +@@ -629,6 +642,7 @@ void nfsd_export(FILE *f) + int found_type = 0; + struct in_addr addr; + struct hostent *he = NULL; ++ struct exportent *v4root = NULL; + + + if (readline(fileno(f), &lbuf, &lbuflen) != 1) +@@ -663,10 +677,18 @@ void nfsd_export(FILE *f) + path[l] == '/' && + is_mountpoint(path))) + /* ok */; +- else ++ else { ++ /* See if the path is part of the psuedo root */ ++ if (v4root_needed && !v4root) ++ v4root = v4root_lookup(path, exp); + continue; +- } else if (strcmp(path, exp->m_export.e_path) != 0) ++ } ++ } else if (strcmp(path, exp->m_export.e_path) != 0) { ++ /* See if the path is part of the psuedo root */ ++ if (v4root_needed && !v4root) ++ v4root = v4root_lookup(path, exp); + continue; ++ } + if (use_ipaddr) { + if (he == NULL) { + if (!inet_aton(dom, &addr)) +@@ -705,17 +727,28 @@ void nfsd_export(FILE *f) + } + + if (found) { ++ xlog(D_CALL, "nfsd_export: found: path %s", path); + if (dump_to_cache(f, dom, path, &found->m_export) < 0) { + xlog(L_WARNING, + "Cannot export %s, possibly unsupported filesystem" + " or fsid= required", path); + dump_to_cache(f, dom, path, NULL); + } +- } else { ++ } else if (v4root) { ++ xlog(D_CALL, "nfsd_export: vroot: path %s", path); ++ dump_to_cache(f, dom, path, v4root); ++ found = (nfs_export *)v4root; ++ } else { + dump_to_cache(f, dom, path, NULL); + } + out: +- xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL); ++ /* ++ * If a psuedo export was create and its not needed ++ * free it up. ++ */ ++ if (v4root && found != (nfs_export *)v4root) ++ v4root_free(v4root); ++ + if (dom) free(dom); + if (path) free(path); + if (he) free(he); +@@ -743,7 +776,9 @@ void cache_open(void) + if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid) + continue; + sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name); +- cachelist[i].f = fopen(path, "r+"); ++ if ((cachelist[i].f = fopen(path, "r+")) == NULL) ++ xlog(L_ERROR, "cache_open: Unable to open '%s': errno %d (%s)", ++ path, errno, strerror(errno)); + } + } + +diff -up nfs-utils-1.2.0/utils/mountd/Makefile.am.save nfs-utils-1.2.0/utils/mountd/Makefile.am +--- nfs-utils-1.2.0/utils/mountd/Makefile.am.save 2009-10-20 08:46:50.000000000 -0400 ++++ nfs-utils-1.2.0/utils/mountd/Makefile.am 2009-10-20 08:47:16.000000000 -0400 +@@ -8,7 +8,7 @@ KPREFIX = @kprefix@ + sbin_PROGRAMS = mountd + + mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \ +- svc_run.c fsloc.c mountd.h ++ svc_run.c fsloc.c v4root.c mountd.h + mountd_LDADD = ../../support/export/libexport.a \ + ../../support/nfs/libnfs.a \ + ../../support/misc/libmisc.a \ +diff -up /dev/null nfs-utils-1.2.0/utils/mountd/v4root.c +--- /dev/null 2009-10-15 16:13:05.251004788 -0400 ++++ nfs-utils-1.2.0/utils/mountd/v4root.c 2009-10-20 08:47:33.000000000 -0400 +@@ -0,0 +1,414 @@ ++/* ++ * Copyright (C) 2009 Red Hat ++ * ++ * support/export/v4root.c ++ * ++ * Routines used to support NFSv4 pseudo roots ++ * ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "xlog.h" ++#include "exportfs.h" ++#include "nfslib.h" ++#include "misc.h" ++#include "v4root.h" ++ ++#ifndef _PATH_PSEUDO_ROOT ++#define _PATH_PSEUDO_ROOT "/" ++#endif ++ ++#ifndef _PSEUDO_ROOT_FSID ++#define _PSEUDO_ROOT_FSID 0 ++#endif ++ ++extern int get_uuid(char *path, char *uuid, int uuidlen, char *u); ++ ++#define HASH_TABLE_SIZE 1021 ++typedef struct _hash_head { ++ TAILQ_HEAD(export_list, _exports_t) h_head; ++} hash_head; ++hash_head exports_tbl[HASH_TABLE_SIZE]; ++ ++typedef struct _exports_t { ++ TAILQ_ENTRY(_exports_t) list; ++ char *path; ++ hash_head *head; ++ char uuid_len; ++ char uuid[sizeof(uuid_t)]; ++ struct exportent p_export; ++} exports_t; ++ ++ ++ ++static exports_t *hash_export_lookup(char *, unsigned int); ++static void hash_export_add(struct _exports_t *, int); ++static void hash_mount_free(void); ++ ++static inline unsigned int strtoint(char *str, int len) ++{ ++ unsigned int n = 0; ++ int i; ++ ++ for (i=0; i < len; i++) ++ n+=((int)str[i])*i; ++ return n; ++} ++static inline int hashint(unsigned int num) ++{ ++ return num % HASH_TABLE_SIZE; ++} ++#define HASH(_s, _l) hashint(strtoint((_s), (_l))) ++void v4root_set(void); ++void v4root_unset(void); ++static int v4root_support(void); ++ ++static struct exportent *v4root_create(char *, nfs_export *); ++ ++int v4root_needed; ++ ++static nfs_export pr_export = { ++ .m_next = NULL, ++ .m_client = NULL, ++ .m_export = { ++ .e_hostname = "*", ++ .e_path = _PATH_PSEUDO_ROOT, ++ .e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH ++ | NFSEXP_NOSUBTREECHECK | NFSEXP_FSID ++ | NFSEXP_CROSSMOUNT | NFSEXP_V4ROOT, ++ .e_anonuid = 65534, ++ .e_anongid = 65534, ++ .e_squids = NULL, ++ .e_nsquids = 0, ++ .e_sqgids = NULL, ++ .e_nsqgids = 0, ++ .e_fsid = 0, ++ .e_mountpoint = NULL, ++ }, ++ .m_exported = 0, ++ .m_xtabent = 1, ++ .m_mayexport = 1, ++ .m_changed = 0, ++ .m_warned = 0, ++}; ++static nfs_export *pseudo_root; ++ ++/* ++ * Return the number '/' in the path ++ */ ++inline static int slash_count(char *path) ++{ ++ int i, slashs=0; ++ ++ for (i=0; i < strlen(path); i++) { ++ if (path[i] == '/') ++ slashs++; ++ } ++ return slashs; ++} ++/* ++ * Make sure the kernel has pseudo root support. ++ */ ++static int ++v4root_support() ++{ ++ static int kernel_support = -1; ++ char *ptr, version[64]; ++ int major, minor; ++ FILE *fp; ++ ++ if (kernel_support != -1) ++ return kernel_support; ++ ++ kernel_support = 0; ++ fp = fopen("/proc/fs/nfsd/exports", "r"); ++ if (fp == NULL) ++ goto out; ++ ++ ptr = fgets(version, 64, fp); ++ fclose(fp); ++ if (ptr == NULL) ++ goto out; ++ ++ while(*ptr && isdigit(*ptr) == 0) ++ ptr++; ++ if (*ptr == '\0') ++ goto out; ++ ++ major = minor = 0; ++ sscanf(ptr, " %d.%d",&major, &minor); ++ if (major >= 1 && minor >= 2) ++ kernel_support = 1; ++out: ++ if (!kernel_support) { ++ xlog(L_WARNING, "Kernel does not have pseudo root support."); ++ xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0"); ++ xlog(L_WARNING, "is specfied in /etc/exports file."); ++ } ++ ++ return kernel_support; ++} ++/* ++ * Build a table of pseudo exports by running through ++ * the real export looking at the components of the path ++ * that make up the export. Those path components, if ++ * not exported, will become pseudo exports allowing them ++ * to be found when the kernel does an upcall looking for ++ * components of the v4 mount. ++ */ ++void ++v4root_set() ++{ ++ nfs_export *exp, *nxt; ++ int i; ++ char *path, *ptr; ++ char *hostname; ++ ++ if (!v4root_needed) ++ return; ++ ++ if (!v4root_support()) ++ return; ++ ++ pseudo_root = &pr_export; ++ ++ for (i = 0; i < MCL_MAXTYPES; i++) { ++ for (exp = exportlist[i].p_head; exp; exp = nxt) { ++ nxt = exp->m_next; ++ hostname = exp->m_export.e_hostname; ++ ++ path = strdup(exp->m_export.e_path); ++ ptr = path + 1; ++ while ((ptr = strchr(ptr, '/')) != NULL) { ++ *ptr = '\0'; ++ if (export_lookup(hostname, path, 0) == NULL) ++ if (v4root_create(path, exp) == NULL) { ++ xlog(L_WARNING, "v4root_set: Unable to create" ++ "pseudo export for '%s'", path); ++ break; ++ } ++ *ptr = '/'; ++ ptr++; ++ } ++ ++ free(path); ++ } ++ } ++} ++ ++/* ++ * Unset the pseudo root export ++ */ ++void ++v4root_unset() ++{ ++ pseudo_root = NULL; ++ hash_mount_free(); ++} ++ ++/* ++ * The kernel will do an upcall looking for the pseudo ++ * root via its fsid. When the wanted fsid equals ++ * PSEUDO_ROOT_FSID return the pseudo root export. ++ */ ++struct exportent * ++v4root_chkroot(int fsidtype, unsigned int fsidnum, char *fhuuid) ++{ ++ if (pseudo_root == NULL) ++ return NULL; ++ ++ if (fsidtype != FSID_NUM) ++ return NULL; ++ ++ if (fsidnum != _PSEUDO_ROOT_FSID) ++ return NULL; ++ ++ return &pseudo_root->m_export; ++} ++ ++/* ++ * Create a pseudo export, if one does not ++ * already exist. ++ */ ++static struct exportent * ++v4root_create(char *path, nfs_export *exp) ++{ ++ static struct exportent *p_export = NULL; ++ exports_t *pexp; ++ char uuid_len = sizeof(uuid_t); ++ char uuid[sizeof(uuid_t)]; ++ ++ if (pseudo_root == NULL) ++ return NULL; ++ ++ /* Check to see if the export already exists */ ++ get_uuid(path, NULL, uuid_len, uuid); ++ if ((p_export = v4root_export(uuid, uuid_len)) != NULL) ++ return p_export; ++ ++ pexp = (exports_t *)malloc(sizeof(exports_t)); ++ if (pexp == NULL) { ++ xlog(L_WARNING, "v4root_create: No memory for pseudo export"); ++ return NULL; ++ } ++ p_export = &pexp->p_export; ++ pexp->path = strdup(path); ++ if (pexp->path == 0) { ++ xlog(L_WARNING, "v4root_create: No memory for pseudo path"); ++ free(pexp); ++ return NULL; ++ } ++ pexp->uuid_len = uuid_len; ++ memcpy(pexp->uuid, uuid, uuid_len); ++ ++ dupexportent(&pexp->p_export, &pr_export.m_export); ++ strcpy(p_export->e_path, path); ++ p_export->e_flags &= ~NFSEXP_FSID; ++ p_export->e_v4root = (void *)pexp; ++ ++ hash_export_add(pexp, HASH(pexp->uuid, sizeof(uuid_t))); ++ ++ xlog(D_CALL, "v4root_create: path '%s'", p_export->e_path); ++ ++ return p_export; ++} ++ ++/* ++ * See if the pseudo export exists ++ */ ++struct exportent * ++v4root_lookup(char *path, nfs_export *exp) ++{ ++ static struct exportent *p_export = NULL; ++ char *epath = exp->m_export.e_path; ++ int elen, plen; ++ char uuid_len = sizeof(uuid_t); ++ char uuid[sizeof(uuid_t)]; ++ ++ if (pseudo_root == NULL) ++ return NULL; ++ ++ /* Path needs to be a subset of e_path */ ++ elen = strlen(epath); ++ plen = strlen(path); ++ if (plen >= elen) ++ return NULL; ++ ++ if (memcmp(path, epath, plen) != 0) ++ return NULL; ++ ++ /* Now to see if the export exists */ ++ get_uuid(path, NULL, uuid_len, uuid); ++ p_export = v4root_export(uuid, uuid_len); ++ ++ return p_export; ++} ++ ++/* ++ * Free a pseudo export ++ */ ++void ++v4root_free(struct exportent *p_export) ++{ ++ exports_t *pexp = (exports_t *)p_export->e_v4root; ++ hash_head *head = (hash_head *)pexp->head; ++ ++ free(pexp->path); ++ TAILQ_REMOVE(&head->h_head, pexp, list); ++} ++ ++/* ++ * Return a pseudo export that match the given uuid ++ */ ++struct exportent * ++v4root_export(char *fhuuid, int uuidlen) ++{ ++ struct exportent *p_export = NULL; ++ exports_t *pexp; ++ int len = MIN(uuidlen, sizeof(uuid_t)); ++ ++ if (pseudo_root == NULL) ++ return NULL; ++ ++ pexp = hash_export_lookup(fhuuid, len); ++ if (pexp) { ++ p_export = &pexp->p_export; ++ xlog(D_CALL, "v4root_export: path %s", p_export->e_path); ++ } ++ return p_export; ++} ++ ++/* ++ * Add pseudo export to export table ++ */ ++static void hash_export_add(struct _exports_t *exp, int hash) ++{ ++ hash_head *head; ++ ++ head = &(exports_tbl[hash]); ++ exp->head = head; ++ ++ if (TAILQ_EMPTY(&head->h_head)) ++ TAILQ_INSERT_HEAD(&head->h_head, exp, list); ++ else ++ TAILQ_INSERT_TAIL(&head->h_head, exp, list); ++} ++ ++/* ++ * Lookup a pseudo export using the uuid and inode number ++ */ ++static exports_t * ++hash_export_lookup(char *uuid, unsigned int uuidlen) ++{ ++ exports_t *pexp; ++ hash_head *head; ++ int hash = HASH(uuid, uuidlen); ++ ++ head = &(exports_tbl[hash]); ++ ++ TAILQ_FOREACH(pexp, &head->h_head, list) { ++ if (memcmp(pexp->uuid, uuid, uuidlen) == 0) ++ return pexp; ++ } ++ return NULL; ++ ++} ++ ++/* ++ * Free up pseudo export table ++ */ ++static void hash_mount_free() ++{ ++ hash_head *head; ++ exports_t *e1, *e2; ++ int hash; ++ ++ for (hash=0; hash < HASH_TABLE_SIZE; hash++) { ++ head = &(exports_tbl[hash]); ++ if (head == NULL) ++ continue; ++ e1 = TAILQ_FIRST(&head->h_head); ++ while (e1 != NULL) { ++ free(e1->path); ++ e2 = TAILQ_NEXT(e1, list); ++ TAILQ_REMOVE(&head->h_head, e1, list); ++ free(e1); ++ e1 = e2; ++ } ++ TAILQ_INIT(&head->h_head); ++ } ++} diff --git a/nfs-utils-1.2.1-rc7.patch b/nfs-utils-1.2.1-rc7.patch new file mode 100644 index 0000000..4d59118 --- /dev/null +++ b/nfs-utils-1.2.1-rc7.patch @@ -0,0 +1,261 @@ +diff --git a/support/include/conffile.h b/support/include/conffile.h +index 672020a..fe23ec2 100644 +--- a/support/include/conffile.h ++++ b/support/include/conffile.h +@@ -75,4 +75,11 @@ static inline void upper2lower(char *str) + while ((c = tolower(*str))) + *str++ = c; + } ++ ++/* ++ * Default Mount options ++ */ ++extern unsigned long config_default_vers; ++extern unsigned long config_default_proto; ++ + #endif /* _CONFFILE_H_ */ +diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c +index e347b0e..28b722c 100644 +--- a/utils/mount/configfile.c ++++ b/utils/mount/configfile.c +@@ -20,13 +20,19 @@ + #include + #endif + #include ++#include ++#include + + #include + #include + #include + #include ++#include + + #include "xlog.h" ++#include "mount.h" ++#include "parse_opt.h" ++#include "network.h" + #include "conffile.h" + + #define KBYTES(x) ((x) * (1024)) +@@ -185,6 +191,63 @@ void free_all(void) + free(entry); + } + } ++static char *versions[] = {"v2", "v3", "v4", "vers", "nfsvers", NULL}; ++int inline check_vers(char *mopt, char *field) ++{ ++ int i; ++ ++ if (strncmp("mountvers", field, strlen("mountvers")) != 0) { ++ for (i=0; versions[i]; i++) ++ if (strcasestr(mopt, versions[i]) != NULL) ++ return 1; ++ } ++ return 0; ++} ++ ++unsigned long config_default_vers; ++unsigned long config_default_proto; ++/* ++ * Check to see if a default value is being set. ++ * If so, set the appropriate global value which will ++ * be used as the initial value in the server negation. ++ */ ++int inline default_value(char *mopt) ++{ ++ struct mount_options *options = NULL; ++ int dftlen = strlen("default"); ++ char *field; ++ ++ if (strncasecmp(mopt, "default", dftlen) != 0) ++ return 0; ++ ++ field = mopt + dftlen; ++ if (strncasecmp(field, "proto", strlen("proto")) == 0) { ++ if ((options = po_split(field)) != NULL) { ++ if (!nfs_nfs_protocol(options, &config_default_proto)) { ++ xlog_warn("Unable to set default protocol : %s", ++ strerror(errno)); ++ } ++ } else { ++ xlog_warn("Unable to alloc memory for default protocol"); ++ } ++ } else if (strncasecmp(field, "vers", strlen("vers")) == 0) { ++ if ((options = po_split(field)) != NULL) { ++ if (!nfs_nfs_version(options, &config_default_vers)) { ++ xlog_warn("Unable to set default version: %s", ++ strerror(errno)); ++ ++ } ++ } else { ++ xlog_warn("Unable to alloc memory for default version"); ++ } ++ } else ++ xlog_warn("Invalid default setting: '%s'", mopt); ++ ++ if (options) ++ po_destroy(options); ++ ++ return 1; ++} + /* + * Parse the given section of the configuration + * file to if there are any mount options set. +@@ -207,6 +270,12 @@ conf_parse_mntopts(char *section, char *arg, char *opts) + snprintf(buf, BUFSIZ, "%s=", node->field); + if (opts && strcasestr(opts, buf) != NULL) + continue; ++ /* ++ * Protocol verions can be set in a number of ways ++ */ ++ if (opts && check_vers(opts, node->field)) ++ continue; ++ + if (lookup_entry(node->field) != NULL) + continue; + buf[0] = '\0'; +@@ -302,15 +371,19 @@ char *conf_get_mntopts(char *spec, char *mount_point, + free_all(); + return mount_opts; + } ++ + if (mount_opts) { + strcpy(config_opts, mount_opts); + strcat(config_opts, ","); + } + SLIST_FOREACH(entry, &head, entries) { ++ if (default_value(entry->opt)) ++ continue; + strcat(config_opts, entry->opt); + strcat(config_opts, ","); + } +- *(strrchr(config_opts, ',')) = '\0'; ++ if ((ptr = strrchr(config_opts, ',')) != NULL) ++ *ptr = '\0'; + + free_all(); + if (mount_opts) +diff --git a/utils/mount/network.c b/utils/mount/network.c +index bd621be..e651167 100644 +--- a/utils/mount/network.c ++++ b/utils/mount/network.c +@@ -50,6 +50,7 @@ + #include "nfsrpc.h" + #include "parse_opt.h" + #include "network.h" ++#include "conffile.h" + + #define PMAP_TIMEOUT (10) + #define CONNECT_TIMEOUT (20) +@@ -609,10 +610,19 @@ static int nfs_probe_nfsport(const struct sockaddr *sap, const socklen_t salen, + if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port) + return 1; + +- if (nfs_mount_data_version >= 4) ++ if (nfs_mount_data_version >= 4) { ++ const unsigned int *probe_proto = probe_tcp_first; ++ ++ /* ++ * If the default proto has been set and ++ * its not TCP, start with UDP ++ */ ++ if (config_default_proto && config_default_proto != IPPROTO_TCP) ++ probe_proto = probe_udp_first; ++ + return nfs_probe_port(sap, salen, pmap, +- probe_nfs3_first, probe_tcp_first); +- else ++ probe_nfs3_first, probe_proto); ++ } else + return nfs_probe_port(sap, salen, pmap, + probe_nfs2_only, probe_udp_only); + } +@@ -1261,7 +1271,7 @@ nfs_nfs_version(struct mount_options *options, unsigned long *version) + * Returns TRUE if @protocol contains a valid value for this option, + * or FALSE if the option was specified with an invalid value. + */ +-static int ++int + nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol) + { + char *option; +diff --git a/utils/mount/network.h b/utils/mount/network.h +index 402e0a5..7eb89b0 100644 +--- a/utils/mount/network.h ++++ b/utils/mount/network.h +@@ -57,6 +57,8 @@ int clnt_ping(struct sockaddr_in *, const unsigned long, + struct mount_options; + + int nfs_nfs_version(struct mount_options *options, unsigned long *version); ++int nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol); ++ + int nfs_options2pmap(struct mount_options *, + struct pmap *, struct pmap *); + +diff --git a/utils/mount/nfsmount.conf b/utils/mount/nfsmount.conf +index f9fcfcb..9b8ff4a 100644 +--- a/utils/mount/nfsmount.conf ++++ b/utils/mount/nfsmount.conf +@@ -24,14 +24,29 @@ + # All reads and writes to the 'nfsserver.foo.com' server + # will be done with 32k (32768 bytes) block sizes. + # +-#[ NFSMount_Global_Options ] ++[ NFSMount_Global_Options ] + # This statically named section defines global mount + # options that can be applied on all NFS mount. + # +-# Protocol Version [2,3] +-# Nfsvers=3 +-# Network Transport [Udp,Tcp,Rdma] +-# Proto=Tcp ++# Protocol Version [2,3,4] ++# This defines the default protocol version which will ++# be used to start the negotiation with the server. ++# Defaultvers=4 ++# ++# Setting this option makes it mandatory the server supports the ++# given version. The mount will fail if the given version is ++# not support by the server. ++# Nfsvers=4 ++# ++# Network Protocol [udp,tcp,rdma] (Note: values are case sensitive) ++# This defines the default network protocol which will ++# be used to start the negotiation with the server. ++# Defaultproto=tcp ++# ++# Setting this option makes it mandatory the server supports the ++# given network protocol. The mount will fail if the given network ++# protocol is not supported by the server. ++# Proto=tcp + # + # The number of times a request will be retired before + # generating a timeout +diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c +index 069bdc1..ceefdb0 100644 +--- a/utils/mount/stropts.c ++++ b/utils/mount/stropts.c +@@ -45,6 +45,7 @@ + #include "parse_opt.h" + #include "version.h" + #include "parse_dev.h" ++#include "conffile.h" + + #ifndef NFS_PROGRAM + #define NFS_PROGRAM (100003) +@@ -283,6 +284,14 @@ static int nfs_validate_options(struct nfsmount_info *mi) + if (option && strcmp(option, "rdma") == 0) + mi->version = 3; + } ++ /* ++ * Use the default value set in the config file when ++ * the version has not been explicitly set. ++ */ ++ if (mi->version == 0 && config_default_vers) { ++ if (config_default_vers < 4) ++ mi->version = config_default_vers; ++ } + + if (!nfs_append_sloppy_option(mi->options)) + return 0; diff --git a/nfs-utils.spec b/nfs-utils.spec index 3880810..6e07485 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser Name: nfs-utils URL: http://sourceforge.net/projects/nfs Version: 1.2.0 -Release: 16%{?dist} +Release: 17%{?dist} Epoch: 1 # group all 32bit related archs @@ -28,12 +28,9 @@ Patch102: nfs-utils-1.2.1-rc3.patch Patch103: nfs-utils-1.2.1-rc4.patch Patch104: nfs-utils-1.2.1-rc5.patch Patch105: nfs-utils-1.2.1-rc6.patch -Patch106: nfs-utils-1.2.0-mount-vers4.patch +Patch106: nfs-utils-1.2.1-rc7.patch -Patch200: nfs-utils-1.2.0-v4root-rel6.patch - -Patch300: nfs-utils-1.2.0-mntconf-vers.patch -Patch301: nfs-utils-1.2.0-mntconf-negation.patch +Patch200: nfs-utils-1.2.0-v4root-rel7.patch Group: System Environment/Daemons Provides: exportfs = %{epoch}:%{version}-%{release} @@ -95,9 +92,6 @@ This package also contains the mount.nfs and umount.nfs program. %patch200 -p1 -%patch300 -p1 -%patch301 -p1 - # Remove .orig files find . -name "*.orig" | xargs rm -f @@ -268,6 +262,13 @@ fi %attr(4755,root,root) /sbin/umount.nfs4 %changelog +* Mon Oct 26 09:23:45 EDT 2009 +- Updated to the latest pseudo root release (rel7). +- Added upstream 1.2.1-rc7 patch which fixes: + - Stop ignoring the -o v4 option (bz 529407) + - Allow network protocol roll backs when proto is set + in the config file (bz 529864) + * Mon Oct 5 2009 Steve Dickson 1.2.0-16 - Fixed a whole where '-o v4' was not overriding the version in the conf file.