Updated to latest upstream release: 1.2.0

This commit is contained in:
Steve Dickson 2009-11-04 13:14:46 +00:00
parent 5b1bacb347
commit c1ec542e87
13 changed files with 7 additions and 8866 deletions

View File

@ -1,3 +1,4 @@
nfs.doc.tar.gz nfs.doc.tar.gz
nfs-utils-1.1.6.tar.bz2 nfs-utils-1.1.6.tar.bz2
nfs-utils-1.2.0.tar.bz2 nfs-utils-1.2.0.tar.bz2
nfs-utils-1.2.1.tar.bz2

View File

@ -1,694 +0,0 @@
diff -up nfs-utils-1.2.0/support/export/xtab.c.orig nfs-utils-1.2.0/support/export/xtab.c
--- nfs-utils-1.2.0/support/export/xtab.c.orig 2009-06-02 10:43:05.000000000 -0400
+++ nfs-utils-1.2.0/support/export/xtab.c 2009-08-17 07:33:13.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.orig nfs-utils-1.2.0/support/include/exportfs.h
--- nfs-utils-1.2.0/support/include/exportfs.h.orig 2009-06-02 10:43:05.000000000 -0400
+++ nfs-utils-1.2.0/support/include/exportfs.h 2009-08-17 07:33:13.000000000 -0400
@@ -12,6 +12,17 @@
#include <netdb.h>
#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.orig nfs-utils-1.2.0/support/include/nfs/export.h
--- nfs-utils-1.2.0/support/include/nfs/export.h.orig 2009-06-02 10:43:05.000000000 -0400
+++ nfs-utils-1.2.0/support/include/nfs/export.h 2009-08-17 07:33:13.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.orig nfs-utils-1.2.0/support/include/nfslib.h
--- nfs-utils-1.2.0/support/include/nfslib.h.orig 2009-08-17 07:31:52.000000000 -0400
+++ nfs-utils-1.2.0/support/include/nfslib.h 2009-08-17 07:33:13.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-08-13 17:25:29.612003011 -0400
+++ nfs-utils-1.2.0/support/include/v4root.h 2009-08-17 07:33:13.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
+ * 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 -up nfs-utils-1.2.0/utils/mountd/auth.c.orig nfs-utils-1.2.0/utils/mountd/auth.c
--- nfs-utils-1.2.0/utils/mountd/auth.c.orig 2009-06-02 10:43:05.000000000 -0400
+++ nfs-utils-1.2.0/utils/mountd/auth.c 2009-08-17 07:33:13.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.orig nfs-utils-1.2.0/utils/mountd/cache.c
--- nfs-utils-1.2.0/utils/mountd/cache.c.orig 2009-08-17 07:31:52.000000000 -0400
+++ nfs-utils-1.2.0/utils/mountd/cache.c 2009-08-17 07:33:13.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_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 -up nfs-utils-1.2.0/utils/mountd/Makefile.am.orig nfs-utils-1.2.0/utils/mountd/Makefile.am
--- nfs-utils-1.2.0/utils/mountd/Makefile.am.orig 2009-06-02 10:43:05.000000000 -0400
+++ nfs-utils-1.2.0/utils/mountd/Makefile.am 2009-08-17 07:33:13.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-08-13 17:25:29.612003011 -0400
+++ nfs-utils-1.2.0/utils/mountd/v4root.c 2009-08-17 07:33:13.000000000 -0400
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
+ *
+ * support/export/v4root.c
+ *
+ * Routines used to support NFSv4 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 <uuid/uuid.h>
+#include <unistd.h>
+#include <errno.h>
+
+#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);
+
+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 psuedo 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
+ * not exported, will be come pseudo exports allow 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;
+
+ if ((slcnt = slash_count(e_path)) < 2)
+ continue;
+ slcnt--; /* knock off the leanding '/' */
+
+ path = strdup(e_path);
+ if ((ptr = strrchr(path, '/')) != NULL)
+ *ptr = '\0';
+
+ /*
+ * Run through each component of the path to
+ * see if a pseudo export should be create.
+ */
+ comp = path+1;
+ do {
+ if ((ptr = strchr(comp, '/')) != NULL)
+ *ptr = '\0';
+
+ if (export_lookup(hostname, path, 0) == NULL)
+ v4root_create(path, exp, FALSE);
+
+ if (ptr) {
+ *ptr = '/';
+ comp = ptr+1;
+ }
+ } while (--slcnt > 0);
+ }
+ }
+}
+
+/*
+ * 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 psuedo 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;
+ char *hostname = exp->m_export.e_hostname;
+ int elen, plen, i;
+ char uuid_len = sizeof(uuid_t);
+ char uuid[sizeof(uuid_t)];
+
+ if (pseudo_root == NULL)
+ return NULL;
+
+ if (docheck) {
+
+ /* Path needs to be an subset of e_path */
+ elen = strlen(epath);
+ plen = strlen(path);
+ if (plen >= elen)
+ return NULL;
+
+ for (i=0; i < plen; i++) {
+ if (path[i] != epath[i])
+ 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 psuedo export");
+ return NULL;
+ }
+ p_export = &pexp->p_export;
+ pexp->path = strdup(path);
+
+ pexp->uuid_len = uuid_len;
+ memcpy(pexp->uuid, uuid, uuid_len);
+
+ memcpy(&pexp->p_export, &pr_export.m_export,
+ sizeof(struct exportent));
+ 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 psuedo 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 psuedo 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 psuedo 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 psuedo 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 psuedo 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);
+ }
+}

View File

@ -1,32 +0,0 @@
Author: Steve Dickson <steved@redhat.com>
Date: Tue Oct 20 10:25:34 EDT 2009
Retry v4 mounts with a v3 mount when the version
is not explicitly specified and the mount fails
with ENOENT. The will help deal with Linux servers
that do not automatically export a pseudo root
Signed-off-by: Steve Dickson <steved@redhat.com>
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-10-20 10:11:03.000000000 -0400
+++ nfs-utils-1.2.0/utils/mount/stropts.c 2009-10-20 10:24:41.000000000 -0400
@@ -613,8 +613,15 @@ static int nfs_try_mount(struct nfsmount
if (linux_version_code() > MAKE_VERSION(2, 6, 31)) {
errno = 0;
result = nfs_try_mount_v4(mi);
- if (errno != EPROTONOSUPPORT)
- break;
+ if (errno != EPROTONOSUPPORT) {
+ /*
+ * To deal with legacy Linux servers that don't
+ * automatically export a pseudo root, retry
+ * ENOENT errors using version 3
+ */
+ if (errno != ENOENT)
+ break;
+ }
}
case 2:
case 3:

View File

@ -1,64 +0,0 @@
commit 1aa4121ba599de836702d7b2d38cad63e6a09044
Author: Steve Dickson <steved@redhat.com>
Date: Mon Jun 29 10:44:20 2009 -0400
mydaemon: remove closeall() calls from mydaemon()
idmapd and svcgssd have a mydaemon() routine that uses closeall() to
close file descriptors. Unfortunately, they aren't using it correctly
and it ends up closing the pipe that the child process uses to talk to
its parent.
Fix this by not using closeall() in this routine and instead, just close
the file descriptors that we know need to be closed. If /dev/null can't
be opened for some reason, then just have the child exit with a non-zero
error.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
diff --git a/utils/gssd/svcgssd.c b/utils/gssd/svcgssd.c
index 69d2a69..729b6a6 100644
--- a/utils/gssd/svcgssd.c
+++ b/utils/gssd/svcgssd.c
@@ -117,10 +117,16 @@ mydaemon(int nochdir, int noclose)
if (noclose == 0) {
tempfd = open("/dev/null", O_RDWR);
- dup2(tempfd, 0);
- dup2(tempfd, 1);
- dup2(tempfd, 2);
- closeall(3);
+ if (tempfd >= 0) {
+ dup2(tempfd, 0);
+ dup2(tempfd, 1);
+ dup2(tempfd, 2);
+ close(tempfd);
+ } else {
+ printerr(1, "mydaemon: can't open /dev/null: errno %d "
+ "(%s)\n", errno, strerror(errno));
+ exit(1);
+ }
}
return;
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
index b690e21..9cbe96c 100644
--- a/utils/idmapd/idmapd.c
+++ b/utils/idmapd/idmapd.c
@@ -978,9 +978,12 @@ mydaemon(int nochdir, int noclose)
dup2(tempfd, 0);
dup2(tempfd, 1);
dup2(tempfd, 2);
- closeall(3);
- } else
- closeall(0);
+ close(tempfd);
+ } else {
+ err(1, "mydaemon: can't open /dev/null: errno %d",
+ errno);
+ exit(1);
+ }
}
return;

View File

@ -1,173 +0,0 @@
diff --git a/aclocal/ipv6.m4 b/aclocal/ipv6.m4
index ba9dcc2..2490f3d 100644
--- a/aclocal/ipv6.m4
+++ b/aclocal/ipv6.m4
@@ -11,7 +11,7 @@ AC_DEFUN([AC_IPV6], [
dnl TI-RPC required for IPv6
if test "$enable_tirpc" = no; then
- AC_MSG_ERROR(['--enable-ipv6' requires '--enable-tirpc'.])
+ AC_MSG_ERROR(['--enable-ipv6' requires TIRPC support.])
fi
dnl IPv6-enabled networking functions required for IPv6
diff --git a/aclocal/libtirpc.m4 b/aclocal/libtirpc.m4
index af4c7d3..9f0fde0 100644
--- a/aclocal/libtirpc.m4
+++ b/aclocal/libtirpc.m4
@@ -11,17 +11,29 @@ AC_DEFUN([AC_LIBTIRPC], [
dnl if --enable-tirpc was specifed, the following components
dnl must be present, and we set up HAVE_ macros for them.
- if test "$enable_tirpc" = yes; then
+ if test "$enable_tirpc" != "no"; then
dnl look for the library; add to LIBS if found
AC_CHECK_LIB([tirpc], [clnt_tli_create], ,
- [AC_MSG_ERROR([libtirpc not found.])])
+ [if test "$enable_tirpc" = "yes"; then
+ AC_MSG_ERROR([libtirpc not found.])
+ else
+ AC_MSG_WARN([libtirpc not found. TIRPC disabled!])
+ enable_tirpc="no"
+ fi])
+ fi
+ if test "$enable_tirpc" != "no"; then
dnl also must have the headers installed where we expect
dnl look for headers; add -I compiler option if found
- AC_CHECK_HEADERS([${tirpc_header_dir}/netconfig.h], ,
- [AC_MSG_ERROR([libtirpc headers not found.])])
- AC_SUBST([AM_CPPFLAGS], ["-I${tirpc_header_dir}"])
+ AC_CHECK_HEADERS([${tirpc_header_dir}/netconfig.h],
+ AC_SUBST([AM_CPPFLAGS], ["-I${tirpc_header_dir}"]),
+ [if test "$enable_tirpc" = "yes"; then
+ AC_MSG_ERROR([libtirpc headers not found.])
+ else
+ AC_MSG_WARN([libtirpc headers not found. TIRPC disabled!])
+ enable_tirpc="no"
+ fi])
fi
diff --git a/configure.ac b/configure.ac
index e09e1d9..e0ca70e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
dnl
-AC_INIT([linux nfs-utils],[1.1.6],[linux-nfs@vger.kernel.org],[nfs-utils])
+AC_INIT([linux nfs-utils],[1.2.0],[linux-nfs@vger.kernel.org],[nfs-utils])
AC_CANONICAL_BUILD([])
AC_CANONICAL_HOST([])
AC_CONFIG_MACRO_DIR(aclocal)
@@ -120,9 +120,9 @@ AC_ARG_ENABLE(mount,
AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"])
AC_ARG_ENABLE(tirpc,
[AC_HELP_STRING([--enable-tirpc],
- [enable use of TI-RPC @<:@default=no@:>@])],
+ [enable use of TI-RPC @<:@default=yes@:>@])],
enable_tirpc=$enableval,
- enable_tirpc=no)
+ enable_tirpc='yes')
AC_ARG_ENABLE(ipv6,
[AC_HELP_STRING([--enable-ipv6],
[enable support for IPv6 @<:@default=no@:>@])],
diff --git a/support/nfs/closeall.c b/support/nfs/closeall.c
index cc7fb3b..38fb162 100644
--- a/support/nfs/closeall.c
+++ b/support/nfs/closeall.c
@@ -7,19 +7,24 @@
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
+#include <errno.h>
void
closeall(int min)
{
+ char *endp;
+ long n;
DIR *dir = opendir("/proc/self/fd");
+
if (dir != NULL) {
int dfd = dirfd(dir);
struct dirent *d;
while ((d = readdir(dir)) != NULL) {
- char *endp;
- long n = strtol(d->d_name, &endp, 10);
- if (*endp != '\0' && n >= min && n != dfd)
+ errno = 0;
+ n = strtol(d->d_name, &endp, 10);
+ if (!errno && *endp == '\0' && endp != d->d_name &&
+ n >= min && n != dfd)
(void) close(n);
}
closedir(dir);
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
index f6949db..40a2b4d 100644
--- a/utils/gssd/gssd.c
+++ b/utils/gssd/gssd.c
@@ -171,6 +171,8 @@ main(int argc, char *argv[])
initerr(progname, verbosity, fg);
#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
+ if (verbosity && rpc_verbosity == 0)
+ rpc_verbosity = verbosity;
authgss_set_debug_level(rpc_verbosity);
#else
if (rpc_verbosity > 0)
diff --git a/utils/gssd/svcgssd.c b/utils/gssd/svcgssd.c
index 6ca0e8d..69d2a69 100644
--- a/utils/gssd/svcgssd.c
+++ b/utils/gssd/svcgssd.c
@@ -208,6 +208,8 @@ main(int argc, char *argv[])
initerr(progname, verbosity, fg);
#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
+ if (verbosity && rpc_verbosity == 0)
+ rpc_verbosity = verbosity;
authgss_set_debug_level(rpc_verbosity);
#else
if (rpc_verbosity > 0)
@@ -215,6 +217,8 @@ main(int argc, char *argv[])
"support setting debug level\n");
#endif
#ifdef HAVE_NFS4_SET_DEBUG
+ if (verbosity && idmap_verbosity == 0)
+ idmap_verbosity = verbosity;
nfs4_set_debug(idmap_verbosity, NULL);
#else
if (idmap_verbosity > 0)
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index 25d292b..b59f939 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -467,8 +467,12 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret,
return NULL;
}
} else {
- if (exp->m_exported<1)
+ int did_export = 0;
+ retry:
+ if (exp->m_exported<1) {
export_export(exp);
+ did_export = 1;
+ }
if (!exp->m_xtabent)
xtab_append(exp);
@@ -482,6 +486,11 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret,
fh = getfh_old ((struct sockaddr *) sin,
stb.st_dev, stb.st_ino);
}
+ if (fh == NULL && !did_export) {
+ exp->m_exported = 0;
+ goto retry;
+ }
+
if (fh == NULL) {
xlog(L_WARNING, "getfh failed: %s", strerror(errno));
*error = NFSERR_ACCES;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,744 +0,0 @@
diff --git a/support/include/conffile.h b/support/include/conffile.h
index 132a149..672020a 100644
--- a/support/include/conffile.h
+++ b/support/include/conffile.h
@@ -34,6 +34,7 @@
#define _CONFFILE_H_
#include <sys/queue.h>
+#include <ctype.h>
struct conf_list_node {
TAILQ_ENTRY(conf_list_node) link;
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
index 9626d42..2d0b143 100644
--- a/tools/nfs-iostat/nfs-iostat.py
+++ b/tools/nfs-iostat/nfs-iostat.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
# -*- python-mode -*-
"""Emulate iostat for NFS mount points using /proc/self/mountstats
"""
@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
import sys, os, time
+from optparse import OptionParser, OptionGroup
Iostats_version = '0.2'
@@ -353,6 +354,12 @@ class DeviceData:
print '\t%7.3f' % rtt_per_op,
print '\t%7.3f' % exe_per_op
+ def ops(self, sample_time):
+ sends = float(self.__rpc_data['rpcsends'])
+ if sample_time == 0:
+ sample_time = float(self.__nfs_data['age'])
+ return (sends / sample_time)
+
def display_iostats(self, sample_time, which):
"""Display NFS and RPC stats in an iostat-like way
"""
@@ -395,33 +402,6 @@ class DeviceData:
# Functions
#
-def print_iostat_help(name):
- print 'usage: %s [ <interval> [ <count> ] ] [ <options> ] [ <mount point> ] ' % name
- print
- print ' Version %s' % Iostats_version
- print
- print ' Sample iostat-like program to display NFS client per-mount statistics.'
- print
- print ' The <interval> parameter specifies the amount of time in seconds between'
- print ' each report. The first report contains statistics for the time since each'
- print ' file system was mounted. Each subsequent report contains statistics'
- print ' collected during the interval since the previous report.'
- print
- print ' If the <count> parameter is specified, the value of <count> determines the'
- print ' number of reports generated at <interval> seconds apart. If the interval'
- print ' parameter is specified without the <count> parameter, the command generates'
- print ' reports continuously.'
- print
- print ' Options include "--attr", which displays statistics related to the attribute'
- print ' cache, "--dir", which displays statistics related to directory operations,'
- print ' and "--page", which displays statistics related to the page cache.'
- print ' By default, if no option is specified, statistics related to file I/O are'
- print ' displayed.'
- print
- print ' If one or more <mount point> names are specified, statistics for only these'
- print ' mount points will be displayed. Otherwise, all NFS mount points on the'
- print ' client are listed.'
-
def parse_stats_file(filename):
"""pop the contents of a mountstats file into a dictionary,
keyed by mount point. each value object is a list of the
@@ -446,109 +426,198 @@ def parse_stats_file(filename):
return ms_dict
-def print_iostat_summary(old, new, devices, time, ac):
- for device in devices:
- stats = DeviceData()
- stats.parse_stats(new[device])
- if not old:
- stats.display_iostats(time, ac)
- else:
+def print_iostat_summary(old, new, devices, time, options):
+ stats = {}
+ diff_stats = {}
+
+ if old:
+ # Trim device list to only include intersection of old and new data,
+ # this addresses umounts due to autofs mountpoints
+ devicelist = filter(lambda x:x in devices,old)
+ else:
+ devicelist = devices
+
+ for device in devicelist:
+ stats[device] = DeviceData()
+ stats[device].parse_stats(new[device])
+ if old:
old_stats = DeviceData()
old_stats.parse_stats(old[device])
- diff_stats = stats.compare_iostats(old_stats)
- diff_stats.display_iostats(time, ac)
+ diff_stats[device] = stats[device].compare_iostats(old_stats)
+
+ if options.sort:
+ if old:
+ # We now have compared data and can print a comparison
+ # ordered by mountpoint ops per second
+ devicelist.sort(key=lambda x: diff_stats[x].ops(time), reverse=True)
+ else:
+ # First iteration, just sort by newly parsed ops/s
+ devicelist.sort(key=lambda x: stats[x].ops(time), reverse=True)
+
+ count = 1
+ for device in devicelist:
+ if old:
+ diff_stats[device].display_iostats(time, options.which)
+ else:
+ stats[device].display_iostats(time, options.which)
+
+ count += 1
+ if (count > options.list):
+ return
+
+
+def list_nfs_mounts(givenlist, mountstats):
+ """return a list of NFS mounts given a list to validate or
+ return a full list if the given list is empty -
+ may return an empty list if none found
+ """
+ list = []
+ if len(givenlist) > 0:
+ for device in givenlist:
+ stats = DeviceData()
+ stats.parse_stats(mountstats[device])
+ if stats.is_nfs_mountpoint():
+ list += [device]
+ else:
+ for device, descr in mountstats.iteritems():
+ stats = DeviceData()
+ stats.parse_stats(descr)
+ if stats.is_nfs_mountpoint():
+ list += [device]
+ return list
def iostat_command(name):
"""iostat-like command for NFS mount points
"""
mountstats = parse_stats_file('/proc/self/mountstats')
devices = []
- which = 0
+ origdevices = []
interval_seen = False
count_seen = False
- for arg in sys.argv:
- if arg in ['-h', '--help', 'help', 'usage']:
- print_iostat_help(name)
- return
-
- if arg in ['-v', '--version', 'version']:
- print '%s version %s' % (name, Iostats_version)
- return
-
- if arg in ['-a', '--attr']:
- which = 1
- continue
-
- if arg in ['-d', '--dir']:
- which = 2
- continue
-
- if arg in ['-p', '--page']:
- which = 3
- continue
+ mydescription= """
+Sample iostat-like program to display NFS client per-mount'
+statistics. The <interval> parameter specifies the amount of time in seconds
+between each report. The first report contains statistics for the time since
+each file system was mounted. Each subsequent report contains statistics
+collected during the interval since the previous report. If the <count>
+parameter is specified, the value of <count> determines the number of reports
+generated at <interval> seconds apart. If the interval parameter is specified
+without the <count> parameter, the command generates reports continuously.
+If one or more <mount point> names are specified, statistics for only these
+mount points will be displayed. Otherwise, all NFS mount points on the
+client are listed.
+"""
+ parser = OptionParser(
+ usage="usage: %prog [ <interval> [ <count> ] ] [ <options> ] [ <mount point> ]",
+ description=mydescription,
+ version='version %s' % Iostats_version)
+ parser.set_defaults(which=0, sort=False, list=sys.maxint)
+
+ statgroup = OptionGroup(parser, "Statistics Options",
+ 'File I/O is displayed unless one of the following is specified:')
+ statgroup.add_option('-a', '--attr',
+ action="store_const",
+ dest="which",
+ const=1,
+ help='displays statistics related to the attribute cache')
+ statgroup.add_option('-d', '--dir',
+ action="store_const",
+ dest="which",
+ const=2,
+ help='displays statistics related to directory operations')
+ statgroup.add_option('-p', '--page',
+ action="store_const",
+ dest="which",
+ const=3,
+ help='displays statistics related to the page cache')
+ parser.add_option_group(statgroup)
+ displaygroup = OptionGroup(parser, "Display Options",
+ 'Options affecting display format:')
+ displaygroup.add_option('-s', '--sort',
+ action="store_true",
+ dest="sort",
+ help="Sort NFS mount points by ops/second")
+ displaygroup.add_option('-l','--list',
+ action="store",
+ type="int",
+ dest="list",
+ help="only print stats for first LIST mount points")
+ parser.add_option_group(displaygroup)
+
+ (options, args) = parser.parse_args(sys.argv)
+
+ for arg in args:
if arg == sys.argv[0]:
continue
if arg in mountstats:
- devices += [arg]
+ origdevices += [arg]
elif not interval_seen:
- interval = int(arg)
+ try:
+ interval = int(arg)
+ except:
+ print 'Illegal <interval> value %s' % arg
+ return
if interval > 0:
interval_seen = True
else:
- print 'Illegal <interval> value'
+ print 'Illegal <interval> value %s' % arg
return
elif not count_seen:
- count = int(arg)
+ try:
+ count = int(arg)
+ except:
+ print 'Ilegal <count> value %s' % arg
+ return
if count > 0:
count_seen = True
else:
- print 'Illegal <count> value'
+ print 'Illegal <count> value %s' % arg
return
# make certain devices contains only NFS mount points
- if len(devices) > 0:
- check = []
- for device in devices:
- stats = DeviceData()
- stats.parse_stats(mountstats[device])
- if stats.is_nfs_mountpoint():
- check += [device]
- devices = check
- else:
- for device, descr in mountstats.iteritems():
- stats = DeviceData()
- stats.parse_stats(descr)
- if stats.is_nfs_mountpoint():
- devices += [device]
+ devices = list_nfs_mounts(origdevices, mountstats)
if len(devices) == 0:
print 'No NFS mount points were found'
return
+
old_mountstats = None
sample_time = 0.0
if not interval_seen:
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time, which)
+ print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
return
if count_seen:
while count != 0:
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time, which)
+ print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
old_mountstats = mountstats
time.sleep(interval)
sample_time = interval
mountstats = parse_stats_file('/proc/self/mountstats')
+ # automount mountpoints add and drop, if automount is involved
+ # we need to recheck the devices list when reparsing
+ devices = list_nfs_mounts(origdevices,mountstats)
+ if len(devices) == 0:
+ print 'No NFS mount points were found'
+ return
count -= 1
else:
while True:
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time, which)
+ print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
old_mountstats = mountstats
time.sleep(interval)
sample_time = interval
mountstats = parse_stats_file('/proc/self/mountstats')
+ # automount mountpoints add and drop, if automount is involved
+ # we need to recheck the devices list when reparsing
+ devices = list_nfs_mounts(origdevices,mountstats)
+ if len(devices) == 0:
+ print 'No NFS mount points were found'
+ return
#
# Main
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 02239d2..37e2aa5 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -840,42 +840,48 @@ handle_krb5_upcall(struct clnt_info *clp)
}
if (create_resp != 0) {
if (uid == 0 && root_uses_machine_creds == 1) {
+ int nocache = 0;
int success = 0;
-
- gssd_refresh_krb5_machine_credential(clp->servername,
- NULL);
- /*
- * Get a list of credential cache names and try each
- * of them until one works or we've tried them all
- */
- if (gssd_get_krb5_machine_cred_list(&credlist)) {
- printerr(0, "ERROR: No credentials found "
- "for connection to server %s\n",
- clp->servername);
- goto out_return_error;
- }
- for (ccname = credlist; ccname && *ccname; ccname++) {
- gssd_setup_krb5_machine_gss_ccache(*ccname);
- if ((create_auth_rpc_client(clp, &rpc_clnt,
- &auth, uid,
- AUTHTYPE_KRB5)) == 0) {
- /* Success! */
- success++;
- break;
+ do {
+ gssd_refresh_krb5_machine_credential(clp->servername,
+ NULL, nocache);
+ /*
+ * Get a list of credential cache names and try each
+ * of them until one works or we've tried them all
+ */
+ if (gssd_get_krb5_machine_cred_list(&credlist)) {
+ printerr(0, "ERROR: No credentials found "
+ "for connection to server %s\n",
+ clp->servername);
+ goto out_return_error;
}
- printerr(2, "WARNING: Failed to create krb5 context "
- "for user with uid %d with credentials "
- "cache %s for server %s\n",
- uid, *ccname, clp->servername);
- }
- gssd_free_krb5_machine_cred_list(credlist);
- if (!success) {
- printerr(1, "WARNING: Failed to create krb5 context "
- "for user with uid %d with any "
- "credentials cache for server %s\n",
- uid, clp->servername);
- goto out_return_error;
- }
+ for (ccname = credlist; ccname && *ccname; ccname++) {
+ gssd_setup_krb5_machine_gss_ccache(*ccname);
+ if ((create_auth_rpc_client(clp, &rpc_clnt,
+ &auth, uid,
+ AUTHTYPE_KRB5)) == 0) {
+ /* Success! */
+ success++;
+ break;
+ }
+ printerr(2, "WARNING: Failed to create machine krb5 context "
+ "with credentials cache %s for server %s\n",
+ *ccname, clp->servername);
+ }
+ gssd_free_krb5_machine_cred_list(credlist);
+ if (!success) {
+ if(nocache == 0) {
+ nocache++;
+ printerr(2, "WARNING: Machine cache is prematurely expired or corrupted "
+ "trying to recreate cache for server %s\n", clp->servername);
+ } else {
+ printerr(1, "WARNING: Failed to create machine krb5 context "
+ "with any credentials cache for server %s\n",
+ clp->servername);
+ goto out_return_error;
+ }
+ }
+ } while(!success);
} else {
printerr(1, "WARNING: Failed to create krb5 context "
"for user with uid %d for server %s\n",
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 3009cc5..78e9775 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -137,7 +137,7 @@ static int select_krb5_ccache(const struct dirent *d);
static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
struct dirent **d);
static int gssd_get_single_krb5_cred(krb5_context context,
- krb5_keytab kt, struct gssd_k5_kt_princ *ple);
+ krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache);
static int query_krb5_ccache(const char* cred_cache, char **ret_princname,
char **ret_realm);
@@ -359,7 +359,8 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
static int
gssd_get_single_krb5_cred(krb5_context context,
krb5_keytab kt,
- struct gssd_k5_kt_princ *ple)
+ struct gssd_k5_kt_princ *ple,
+ int nocache)
{
#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
krb5_get_init_creds_opt *init_opts = NULL;
@@ -379,7 +380,7 @@ gssd_get_single_krb5_cred(krb5_context context,
memset(&my_creds, 0, sizeof(my_creds));
- if (ple->ccname && ple->endtime > now) {
+ if (ple->ccname && ple->endtime > now && !nocache) {
printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
ple->ccname, ple->endtime);
code = 0;
@@ -1095,7 +1096,7 @@ gssd_get_krb5_machine_cred_list(char ***list)
for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
if (ple->ccname) {
/* Make sure cred is up-to-date before returning it */
- retval = gssd_refresh_krb5_machine_credential(NULL, ple);
+ retval = gssd_refresh_krb5_machine_credential(NULL, ple, 0);
if (retval)
continue;
if (i + 1 > listsize) {
@@ -1185,7 +1186,7 @@ gssd_destroy_krb5_machine_creds(void)
*/
int
gssd_refresh_krb5_machine_credential(char *hostname,
- struct gssd_k5_kt_princ *ple)
+ struct gssd_k5_kt_princ *ple, int nocache)
{
krb5_error_code code = 0;
krb5_context context;
@@ -1240,7 +1241,7 @@ gssd_refresh_krb5_machine_credential(char *hostname,
goto out;
}
}
- retval = gssd_get_single_krb5_cred(context, kt, ple);
+ retval = gssd_get_single_krb5_cred(context, kt, ple, nocache);
out:
if (kt)
krb5_kt_close(context, kt);
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
index 3d39300..4b6b281 100644
--- a/utils/gssd/krb5_util.h
+++ b/utils/gssd/krb5_util.h
@@ -30,7 +30,7 @@ void gssd_free_krb5_machine_cred_list(char **list);
void gssd_setup_krb5_machine_gss_ccache(char *servername);
void gssd_destroy_krb5_machine_creds(void);
int gssd_refresh_krb5_machine_credential(char *hostname,
- struct gssd_k5_kt_princ *ple);
+ struct gssd_k5_kt_princ *ple, int nocache);
char *gssd_k5_err_msg(krb5_context context, krb5_error_code code);
void gssd_k5_get_default_realm(char **def_realm);
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
index 65a6a2a..573abaa 100644
--- a/utils/idmapd/idmapd.c
+++ b/utils/idmapd/idmapd.c
@@ -139,6 +139,7 @@ static void nametoidres(struct idmap_msg *);
static int nfsdopen(void);
static int nfsdopenone(struct idmap_client *);
+static void nfsdreopen_one(struct idmap_client *);
static void nfsdreopen(void);
size_t strlcat(char *, const char *, size_t);
@@ -502,7 +503,8 @@ nfsdcb(int fd, short which, void *data)
xlog_warn("nfsdcb: read(%s) failed: errno %d (%s)",
ic->ic_path, len?errno:0,
len?strerror(errno):"End of File");
- goto out;
+ nfsdreopen_one(ic);
+ return;
}
/* Get rid of newline and terminate buffer*/
@@ -514,11 +516,11 @@ nfsdcb(int fd, short which, void *data)
/* Authentication name -- ignored for now*/
if (getfield(&bp, authbuf, sizeof(authbuf)) == -1) {
xlog_warn("nfsdcb: bad authentication name in upcall\n");
- return;
+ goto out;
}
if (getfield(&bp, typebuf, sizeof(typebuf)) == -1) {
xlog_warn("nfsdcb: bad type in upcall\n");
- return;
+ goto out;
}
if (verbose > 0)
xlog_warn("nfsdcb: authbuf=%s authtype=%s",
@@ -532,26 +534,26 @@ nfsdcb(int fd, short which, void *data)
im.im_conv = IDMAP_CONV_NAMETOID;
if (getfield(&bp, im.im_name, sizeof(im.im_name)) == -1) {
xlog_warn("nfsdcb: bad name in upcall\n");
- return;
+ goto out;
}
break;
case IC_IDNAME:
im.im_conv = IDMAP_CONV_IDTONAME;
if (getfield(&bp, buf1, sizeof(buf1)) == -1) {
xlog_warn("nfsdcb: bad id in upcall\n");
- return;
+ goto out;
}
tmp = strtoul(buf1, (char **)NULL, 10);
im.im_id = (u_int32_t)tmp;
if ((tmp == ULONG_MAX && errno == ERANGE)
|| (unsigned long)im.im_id != tmp) {
xlog_warn("nfsdcb: id '%s' too big!\n", buf1);
- return;
+ goto out;
}
break;
default:
xlog_warn("nfsdcb: Unknown which type %d", ic->ic_which);
- return;
+ goto out;
}
imconv(ic, &im);
@@ -612,7 +614,7 @@ nfsdcb(int fd, short which, void *data)
break;
default:
xlog_warn("nfsdcb: Unknown which type %d", ic->ic_which);
- return;
+ goto out;
}
bsiz = sizeof(buf) - bsiz;
diff --git a/utils/mount/mount_config.h b/utils/mount/mount_config.h
index 9a885a9..3023306 100644
--- a/utils/mount/mount_config.h
+++ b/utils/mount/mount_config.h
@@ -20,6 +20,8 @@ inline void mount_config_init(char *);
#ifdef MOUNT_CONFIG
#include "conffile.h"
+#include "xlog.h"
+
extern char *conf_get_mntopts(char *, char *, char *);
inline void mount_config_init(char *program)
diff --git a/utils/mount/network.c b/utils/mount/network.c
index f6fa5fd..bd621be 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -90,6 +90,7 @@ static const char *nfs_transport_opttbl[] = {
static const char *nfs_version_opttbl[] = {
"v2",
"v3",
+ "v4",
"vers",
"nfsvers",
NULL,
@@ -1203,7 +1204,7 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
* Returns TRUE if @version contains a valid value for this option,
* or FALSE if the option was specified with an invalid value.
*/
-static int
+int
nfs_nfs_version(struct mount_options *options, unsigned long *version)
{
long tmp;
@@ -1215,10 +1216,13 @@ nfs_nfs_version(struct mount_options *options, unsigned long *version)
case 1: /* v3 */
*version = 3;
return 1;
- case 2: /* vers */
+ case 2: /* v4 */
+ *version = 4;
+ return 1;
+ case 3: /* vers */
switch (po_get_numeric(options, "vers", &tmp)) {
case PO_FOUND:
- if (tmp >= 2 && tmp <= 3) {
+ if (tmp >= 2 && tmp <= 4) {
*version = tmp;
return 1;
}
@@ -1229,10 +1233,10 @@ nfs_nfs_version(struct mount_options *options, unsigned long *version)
case PO_BAD_VALUE:
return 0;
}
- case 3: /* nfsvers */
+ case 4: /* nfsvers */
switch (po_get_numeric(options, "nfsvers", &tmp)) {
case PO_FOUND:
- if (tmp >= 2 && tmp <= 3) {
+ if (tmp >= 2 && tmp <= 4) {
*version = tmp;
return 1;
}
diff --git a/utils/mount/network.h b/utils/mount/network.h
index db5134c..402e0a5 100644
--- a/utils/mount/network.h
+++ b/utils/mount/network.h
@@ -56,6 +56,7 @@ 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_options2pmap(struct mount_options *,
struct pmap *, struct pmap *);
diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c
index f81db14..c5505b1 100644
--- a/utils/mount/nfsumount.c
+++ b/utils/mount/nfsumount.c
@@ -179,6 +179,10 @@ static int nfs_umount_do_umnt(struct mount_options *options,
return EX_FAIL;
}
+ /* Skip UMNT call for vers=4 mounts */
+ if (nfs_pmap.pm_vers == 4)
+ return EX_SUCCESS;
+
*hostname = nfs_umount_hostname(options, *hostname);
if (!*hostname) {
nfs_error(_("%s: out of memory"), progname);
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index a12ace7..3eb661e 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -84,6 +84,7 @@ struct nfsmount_info {
struct mount_options *options; /* parsed mount options */
char **extra_opts; /* string for /etc/mtab */
+ unsigned long version; /* NFS version */
int flags, /* MS_ flags */
fake, /* actually do the mount? */
child; /* forked bg child? */
@@ -272,7 +273,12 @@ static int nfs_validate_options(struct nfsmount_info *mi)
if (!nfs_name_to_address(mi->hostname, sap, &salen))
return 0;
- if (strncmp(mi->type, "nfs4", 4) == 0) {
+ if (!nfs_nfs_version(mi->options, &mi->version))
+ return 0;
+ if (strncmp(mi->type, "nfs4", 4) == 0)
+ mi->version = 4;
+
+ if (mi->version == 4) {
if (!nfs_append_clientaddr_option(sap, salen, mi->options))
return 0;
} else {
@@ -488,7 +494,7 @@ static int nfs_try_mount(struct nfsmount_info *mi)
char *options = NULL;
int result;
- if (strncmp(mi->type, "nfs4", 4) != 0) {
+ if (mi->version != 4) {
if (!nfs_rewrite_pmap_mount_options(mi->options))
return 0;
}
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index b59f939..888fd8c 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -359,6 +359,11 @@ static void set_authflavors(struct mountres3_ok *ok, nfs_export *exp)
flavors[i] = s->flav->fnum;
i++;
}
+ if (i == 0) {
+ /* default when there is no sec= option: */
+ i = 1;
+ flavors[0] = AUTH_UNIX;
+ }
ok->auth_flavors.auth_flavors_val = flavors;
ok->auth_flavors.auth_flavors_len = i;
}
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
index 650c593..1cda1e5 100644
--- a/utils/nfsd/nfsd.c
+++ b/utils/nfsd/nfsd.c
@@ -27,6 +27,15 @@
#include "nfssvc.h"
#include "xlog.h"
+/*
+ * IPv6 support for nfsd was finished before some of the other daemons (mountd
+ * and statd in particular). That could be a problem in the future if someone
+ * were to boot a kernel that supports IPv6 serving with an older nfs-utils. For
+ * now, hardcode the IPv6 switch into the off position until the other daemons
+ * are functional.
+ */
+#undef IPV6_SUPPORTED
+
static void usage(const char *);
static struct option longopts[] =
diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c
index ee862b2..12d3253 100644
--- a/utils/nfsd/nfssvc.c
+++ b/utils/nfsd/nfssvc.c
@@ -22,6 +22,15 @@
#include "nfslib.h"
#include "xlog.h"
+/*
+ * IPv6 support for nfsd was finished before some of the other daemons (mountd
+ * and statd in particular). That could be a problem in the future if someone
+ * were to boot a kernel that supports IPv6 serving with an older nfs-utils. For
+ * now, hardcode the IPv6 switch into the off position until the other daemons
+ * are functional.
+ */
+#undef IPV6_SUPPORTED
+
#define NFSD_PORTS_FILE "/proc/fs/nfsd/portlist"
#define NFSD_VERS_FILE "/proc/fs/nfsd/versions"
#define NFSD_THREAD_FILE "/proc/fs/nfsd/threads"

View File

@ -1,307 +0,0 @@
diff --git a/utils/mount/parse_opt.c b/utils/mount/parse_opt.c
index 1dfee8a..f0918f7 100644
--- a/utils/mount/parse_opt.c
+++ b/utils/mount/parse_opt.c
@@ -101,6 +101,37 @@ fail:
return NULL;
}
+static struct mount_option *option_dup(const struct mount_option *option)
+{
+ struct mount_option *new;
+
+ new = malloc(sizeof(*new));
+ if (!new)
+ return NULL;
+
+ new->next = NULL;
+ new->prev = NULL;
+
+ new->keyword = strdup(option->keyword);
+ if (!new->keyword)
+ goto fail;
+
+ new->value = NULL;
+ if (option->value) {
+ new->value = strdup(option->value);
+ if (!new->value) {
+ free(new->keyword);
+ goto fail;
+ }
+ }
+
+ return new;
+
+fail:
+ free(new);
+ return NULL;
+}
+
static void option_destroy(struct mount_option *option)
{
free(option->keyword);
@@ -229,6 +260,40 @@ fail:
}
/**
+ * po_dup - duplicate an existing list of options
+ * @options: pointer to mount options
+ *
+ */
+struct mount_options *po_dup(struct mount_options *source)
+{
+ struct mount_options *target;
+ struct mount_option *current;
+
+ if (!source)
+ return NULL;
+
+ target = options_create();
+ if (options_empty(source) || target == NULL)
+ return target;
+
+ current = source->head;
+ while (target->count < source->count) {
+ struct mount_option *option;
+
+ option = option_dup(current);
+ if (!option) {
+ po_destroy(target);
+ return NULL;
+ }
+
+ options_tail_insert(target, option);
+ current = current->next;
+ }
+
+ return target;
+}
+
+/**
* po_replace - replace mount options in one mount_options object with another
* @target: pointer to previously instantiated object to replace
* @source: pointer to object containing source mount options
diff --git a/utils/mount/parse_opt.h b/utils/mount/parse_opt.h
index f9243c3..2c0b5f4 100644
--- a/utils/mount/parse_opt.h
+++ b/utils/mount/parse_opt.h
@@ -38,6 +38,7 @@ typedef enum {
struct mount_options;
struct mount_options * po_split(char *);
+struct mount_options * po_dup(struct mount_options *);
void po_replace(struct mount_options *,
struct mount_options *);
po_return_t po_join(struct mount_options *, char **);
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 3eb661e..069bdc1 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -80,6 +80,8 @@ struct nfsmount_info {
*node, /* mounted-on dir */
*type; /* "nfs" or "nfs4" */
char *hostname; /* server's hostname */
+ struct sockaddr_storage address; /* server's address */
+ socklen_t salen; /* size of server's address */
struct mount_options *options; /* parsed mount options */
char **extra_opts; /* string for /etc/mtab */
@@ -257,47 +259,35 @@ static int nfs_append_sloppy_option(struct mount_options *options)
}
/*
- * Set up mandatory NFS mount options.
+ * Set up mandatory non-version specific NFS mount options.
*
* Returns 1 if successful; otherwise zero.
*/
static int nfs_validate_options(struct nfsmount_info *mi)
{
- struct sockaddr_storage dummy;
- struct sockaddr *sap = (struct sockaddr *)&dummy;
- socklen_t salen = sizeof(dummy);
+ struct sockaddr *sap = (struct sockaddr *)&mi->address;
if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
return 0;
- if (!nfs_name_to_address(mi->hostname, sap, &salen))
+ mi->salen = sizeof(mi->address);
+ if (!nfs_name_to_address(mi->hostname, sap, &mi->salen))
return 0;
if (!nfs_nfs_version(mi->options, &mi->version))
return 0;
if (strncmp(mi->type, "nfs4", 4) == 0)
mi->version = 4;
-
- if (mi->version == 4) {
- if (!nfs_append_clientaddr_option(sap, salen, mi->options))
- return 0;
- } else {
- if (!nfs_fix_mounthost_option(mi->options))
- return 0;
- if (!mi->fake && !nfs_verify_lock_option(mi->options))
- return 0;
+ else {
+ char *option = po_get(mi->options, "proto");
+ if (option && strcmp(option, "rdma") == 0)
+ mi->version = 3;
}
if (!nfs_append_sloppy_option(mi->options))
return 0;
- if (!nfs_append_addr_option(sap, salen, mi->options))
- return 0;
-
- /*
- * Update option string to be recorded in /etc/mnttab
- */
- if (po_join(mi->options, mi->extra_opts) == PO_FAILED)
+ if (!nfs_append_addr_option(sap, mi->salen, mi->options))
return 0;
return 1;
@@ -489,17 +479,12 @@ out:
* Returns TRUE if successful, otherwise FALSE.
* "errno" is set to reflect the individual error.
*/
-static int nfs_try_mount(struct nfsmount_info *mi)
+static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts)
{
char *options = NULL;
int result;
- if (mi->version != 4) {
- if (!nfs_rewrite_pmap_mount_options(mi->options))
- return 0;
- }
-
- if (po_join(mi->options, &options) == PO_FAILED) {
+ if (po_join(opts, &options) == PO_FAILED) {
errno = EIO;
return 0;
}
@@ -522,6 +507,121 @@ static int nfs_try_mount(struct nfsmount_info *mi)
}
/*
+ * For "-t nfs vers=2" or "-t nfs vers=3" mounts.
+ */
+static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
+{
+ struct mount_options *options = po_dup(mi->options);
+ int result = 0;
+
+ if (!options) {
+ errno = ENOMEM;
+ return result;
+ }
+
+ if (!nfs_fix_mounthost_option(options)) {
+ errno = EINVAL;
+ goto out_fail;
+ }
+ if (!mi->fake && !nfs_verify_lock_option(options)) {
+ errno = EINVAL;
+ goto out_fail;
+ }
+
+ /*
+ * Options we negotiate below may be stale by the time this
+ * file system is unmounted. In order to force umount.nfs
+ * to renegotiate with the server, only write the user-
+ * specified options, and not negotiated options, to /etc/mtab.
+ */
+ if (po_join(options, mi->extra_opts) == PO_FAILED) {
+ errno = ENOMEM;
+ goto out_fail;
+ }
+
+ if (!nfs_rewrite_pmap_mount_options(options))
+ goto out_fail;
+
+ result = nfs_sys_mount(mi, options);
+
+out_fail:
+ po_destroy(options);
+ return result;
+}
+
+/*
+ * For "-t nfs -o vers=4" or "-t nfs4" mounts.
+ */
+static int nfs_try_mount_v4(struct nfsmount_info *mi)
+{
+ struct sockaddr *sap = (struct sockaddr *)&mi->address;
+ struct mount_options *options = po_dup(mi->options);
+ int result = 0;
+
+ if (!options) {
+ errno = ENOMEM;
+ return result;
+ }
+
+ if (mi->version == 0) {
+ if (po_append(options, "vers=4") == PO_FAILED) {
+ errno = EINVAL;
+ goto out_fail;
+ }
+ }
+
+ if (!nfs_append_clientaddr_option(sap, mi->salen, options)) {
+ errno = EINVAL;
+ goto out_fail;
+ }
+ /*
+ * Update option string to be recorded in /etc/mtab.
+ */
+ if (po_join(options, mi->extra_opts) == PO_FAILED) {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ result = nfs_sys_mount(mi, options);
+
+out_fail:
+ po_destroy(options);
+ return result;
+}
+
+/*
+ * This is a single pass through the fg/bg loop.
+ *
+ * Returns TRUE if successful, otherwise FALSE.
+ * "errno" is set to reflect the individual error.
+ */
+static int nfs_try_mount(struct nfsmount_info *mi)
+{
+ int result = 0;
+
+ switch (mi->version) {
+ case 0:
+ if (linux_version_code() > MAKE_VERSION(2, 6, 31)) {
+ errno = 0;
+ result = nfs_try_mount_v4(mi);
+ if (errno != EPROTONOSUPPORT)
+ break;
+ }
+ case 2:
+ case 3:
+ result = nfs_try_mount_v3v2(mi);
+ break;
+ case 4:
+ result = nfs_try_mount_v4(mi);
+ break;
+ default:
+ errno = EIO;
+ }
+
+ return result;
+}
+
+/*
* Distinguish between permanent and temporary errors.
*
* Basically, we retry if communication with the server has

View File

@ -1,261 +0,0 @@
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 <config.h>
#endif
#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <errno.h>
#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;

View File

@ -1,8 +1,8 @@
Summary: NFS utilities and supporting clients and daemons for the kernel NFS server Summary: NFS utilities and supporting clients and daemons for the kernel NFS server
Name: nfs-utils Name: nfs-utils
URL: http://sourceforge.net/projects/nfs URL: http://sourceforge.net/projects/nfs
Version: 1.2.0 Version: 1.2.1
Release: 18%{?dist} Release: 1%{?dist}
Epoch: 1 Epoch: 1
# group all 32bit related archs # group all 32bit related archs
@ -22,16 +22,7 @@ Patch00: nfs-utils-1.0.5-statdpath.patch
Patch01: nfs-utils-1.1.0-smnotify-path.patch Patch01: nfs-utils-1.1.0-smnotify-path.patch
Patch02: nfs-utils-1.1.0-exp-subtree-warn-off.patch Patch02: nfs-utils-1.1.0-exp-subtree-warn-off.patch
Patch100: nfs-utils-1.2.1-rc1.patch
Patch101: nfs-utils-1.2.1-rc2.patch
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.1-rc7.patch
Patch200: nfs-utils-1.2.0-v4root-rel7.patch Patch200: nfs-utils-1.2.0-v4root-rel7.patch
Patch201: nfs-utils-1.2.0-v4-enoent.patch
Group: System Environment/Daemons Group: System Environment/Daemons
Provides: exportfs = %{epoch}:%{version}-%{release} Provides: exportfs = %{epoch}:%{version}-%{release}
@ -83,16 +74,7 @@ This package also contains the mount.nfs and umount.nfs program.
%patch01 -p1 %patch01 -p1
%patch02 -p1 %patch02 -p1
%patch100 -p1
%patch101 -p1
%patch102 -p1
%patch103 -p1
%patch104 -p1
%patch105 -p1
%patch106 -p1
%patch200 -p1 %patch200 -p1
%patch201 -p1
# Remove .orig files # Remove .orig files
find . -name "*.orig" | xargs rm -f find . -name "*.orig" | xargs rm -f
@ -264,6 +246,9 @@ fi
%attr(4755,root,root) /sbin/umount.nfs4 %attr(4755,root,root) /sbin/umount.nfs4
%changelog %changelog
* Wed Nov 4 2009 Steve Dickson <steved@redhat.com> 1.2.1-1
- Updated to latest upstream release: 1.2.0
* Tue Nov 3 2009 Steve Dickson <steved@redhat.com> 1.2.0-18 * Tue Nov 3 2009 Steve Dickson <steved@redhat.com> 1.2.0-18
- Reworked and remove some of the Default-Start/Stop stanzas - Reworked and remove some of the Default-Start/Stop stanzas
in the init scripts (bz 531425) in the init scripts (bz 531425)

View File

@ -1,2 +1,2 @@
ae7db9c61c5ad04f83bb99e5caed73da nfs.doc.tar.gz ae7db9c61c5ad04f83bb99e5caed73da nfs.doc.tar.gz
779cf81044e92cb51ad590960e7b3671 nfs-utils-1.2.0.tar.bz2 c3ccd16c147befd49fe4541a506dd177 nfs-utils-1.2.1.tar.bz2