b4bc034399
Signed-off-by: Steve Dickson <steved@redhat.com>
3600 lines
99 KiB
Diff
3600 lines
99 KiB
Diff
diff --git a/.gitignore b/.gitignore
|
|
index 126d12c..941aca0 100644
|
|
--- a/.gitignore
|
|
+++ b/.gitignore
|
|
@@ -70,6 +70,7 @@ tests/nsm_client/nlm_sm_inter_svc.c
|
|
tests/nsm_client/nlm_sm_inter_xdr.c
|
|
utils/nfsidmap/nfsidmap
|
|
systemd/nfs-server-generator
|
|
+systemd/rpc-pipefs-generator
|
|
systemd/nfs-config.service
|
|
systemd/rpc-gssd.service
|
|
# cscope database files
|
|
diff --git a/nfs.conf b/nfs.conf
|
|
index 81ece06..0d0ec9b 100644
|
|
--- a/nfs.conf
|
|
+++ b/nfs.conf
|
|
@@ -1,7 +1,10 @@
|
|
#
|
|
-# This is a general conifguration for the
|
|
+# This is a general configuration for the
|
|
# NFS daemons and tools
|
|
#
|
|
+#[general]
|
|
+# pipefs-directory=/var/lib/nfs/rpc_pipefs
|
|
+#
|
|
#[exportfs]
|
|
# debug=0
|
|
#
|
|
@@ -12,7 +15,6 @@
|
|
# limit-to-legacy-enctypes=0
|
|
# context-timeout=0
|
|
# rpc-timeout=5
|
|
-# pipefs-directory=/var/lib/nfs/rpc_pipefs
|
|
# keytab-file=/etc/krb5.keytab
|
|
# cred-cache-directory=
|
|
# preferred-realm=
|
|
@@ -42,7 +44,7 @@
|
|
# port=0
|
|
# grace-time=90
|
|
# lease-time=90
|
|
-# udp=y
|
|
+# udp=n
|
|
# tcp=y
|
|
# vers2=n
|
|
# vers3=y
|
|
@@ -65,6 +67,7 @@
|
|
# retry-time=900
|
|
# outgoing-port=
|
|
# outgoing-addr=
|
|
+# lift-grace=y
|
|
#
|
|
#[svcgssd]
|
|
# principal=
|
|
diff --git a/support/export/xtab.c b/support/export/xtab.c
|
|
index 22cf539..d42eeef 100644
|
|
--- a/support/export/xtab.c
|
|
+++ b/support/export/xtab.c
|
|
@@ -14,12 +14,20 @@
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <errno.h>
|
|
+#include <libgen.h>
|
|
|
|
#include "nfslib.h"
|
|
#include "exportfs.h"
|
|
#include "xio.h"
|
|
#include "xlog.h"
|
|
#include "v4root.h"
|
|
+#include "misc.h"
|
|
+
|
|
+static char state_base_dirname[PATH_MAX] = NFS_STATEDIR;
|
|
+extern struct state_paths etab;
|
|
|
|
int v4root_needed;
|
|
static void cond_rename(char *newfile, char *oldfile);
|
|
@@ -65,7 +73,7 @@ xtab_read(char *xtab, char *lockfn, int is_export)
|
|
int
|
|
xtab_export_read(void)
|
|
{
|
|
- return xtab_read(_PATH_ETAB, _PATH_ETABLCK, 1);
|
|
+ return xtab_read(etab.statefn, etab.lockfn, 1);
|
|
}
|
|
|
|
/*
|
|
@@ -112,7 +120,7 @@ xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export)
|
|
int
|
|
xtab_export_write()
|
|
{
|
|
- return xtab_write(_PATH_ETAB, _PATH_ETABTMP, _PATH_ETABLCK, 1);
|
|
+ return xtab_write(etab.statefn, etab.tmpfn, etab.lockfn, 1);
|
|
}
|
|
|
|
/*
|
|
@@ -158,3 +166,74 @@ static void cond_rename(char *newfile, char *oldfile)
|
|
rename(newfile, oldfile);
|
|
return;
|
|
}
|
|
+
|
|
+/*
|
|
+ * Returns a dynamically allocated, '\0'-terminated buffer
|
|
+ * containing an appropriate pathname, or NULL if an error
|
|
+ * occurs. Caller must free the returned result with free(3).
|
|
+ */
|
|
+static char *
|
|
+state_make_pathname(const char *tabname)
|
|
+{
|
|
+ return generic_make_pathname(state_base_dirname, tabname);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * state_setup_basedir - set up basedir
|
|
+ * @progname: C string containing name of program, for error messages
|
|
+ * @parentdir: C string containing pathname to on-disk state, or NULL
|
|
+ *
|
|
+ * This runs before logging is set up, so error messages are directed
|
|
+ * to stderr.
|
|
+ *
|
|
+ * Returns true and sets up our basedir, if @parentdir was valid
|
|
+ * and usable; otherwise false is returned.
|
|
+ */
|
|
+_Bool
|
|
+state_setup_basedir(const char *progname, const char *parentdir)
|
|
+{
|
|
+ return generic_setup_basedir(progname, parentdir, state_base_dirname,
|
|
+ PATH_MAX);
|
|
+}
|
|
+
|
|
+int
|
|
+setup_state_path_names(const char *progname, const char *statefn,
|
|
+ const char *tmpfn, const char *lockfn,
|
|
+ struct state_paths *paths)
|
|
+{
|
|
+ paths->statefn = state_make_pathname(statefn);
|
|
+ if (!paths->statefn) {
|
|
+ fprintf(stderr, "%s: state_make_pathname(%s) failed\n",
|
|
+ progname, statefn);
|
|
+ goto out_err;
|
|
+ }
|
|
+ paths->tmpfn = state_make_pathname(tmpfn);
|
|
+ if (!paths->tmpfn) {
|
|
+ fprintf(stderr, "%s: state_make_pathname(%s) failed\n",
|
|
+ progname, tmpfn);
|
|
+ goto out_free_statefn;
|
|
+ }
|
|
+ paths->lockfn = state_make_pathname(lockfn);
|
|
+ if (!paths->lockfn) {
|
|
+ fprintf(stderr, "%s: state_make_pathname(%s) failed\n",
|
|
+ progname, lockfn);
|
|
+ goto out_free_tmpfn;
|
|
+ }
|
|
+ return 1;
|
|
+
|
|
+out_free_tmpfn:
|
|
+ free(paths->tmpfn);
|
|
+out_free_statefn:
|
|
+ free(paths->statefn);
|
|
+out_err:
|
|
+ return 0;
|
|
+
|
|
+}
|
|
+
|
|
+void
|
|
+free_state_path_names(struct state_paths *paths)
|
|
+{
|
|
+ free(paths->statefn);
|
|
+ free(paths->tmpfn);
|
|
+ free(paths->lockfn);
|
|
+}
|
|
diff --git a/support/include/conffile.h b/support/include/conffile.h
|
|
index 3fe3a78..2d11a52 100644
|
|
--- a/support/include/conffile.h
|
|
+++ b/support/include/conffile.h
|
|
@@ -48,8 +48,6 @@ struct conf_list {
|
|
TAILQ_HEAD(conf_list_fields_head, conf_list_node) fields;
|
|
};
|
|
|
|
-extern char *conf_path;
|
|
-
|
|
extern int conf_begin(void);
|
|
extern int conf_decode_base64(uint8_t *, uint32_t *, unsigned char *);
|
|
extern int conf_end(int, int);
|
|
@@ -61,9 +59,9 @@ extern int conf_get_num(char *, char *, int);
|
|
extern _Bool conf_get_bool(char *, char *, _Bool);
|
|
extern char *conf_get_str(char *, char *);
|
|
extern char *conf_get_section(char *, char *, char *);
|
|
-extern void conf_init(void);
|
|
+extern void conf_init(const char *);
|
|
+extern void conf_cleanup(void);
|
|
extern int conf_match_num(char *, char *, int);
|
|
-extern void conf_reinit(void);
|
|
extern int conf_remove(int, char *, char *);
|
|
extern int conf_remove_section(int, char *);
|
|
extern void conf_report(void);
|
|
diff --git a/support/include/misc.h b/support/include/misc.h
|
|
index eedc1fe..06e2a0c 100644
|
|
--- a/support/include/misc.h
|
|
+++ b/support/include/misc.h
|
|
@@ -15,6 +15,9 @@
|
|
int randomkey(unsigned char *keyout, int len);
|
|
int weakrandomkey(unsigned char *keyout, int len);
|
|
|
|
+char *generic_make_pathname(const char *, const char *);
|
|
+_Bool generic_setup_basedir(const char *, const char *, char *, const size_t);
|
|
+
|
|
extern int is_mountpoint(char *path);
|
|
|
|
/* size of the file pointer buffers for rpc procfs files */
|
|
diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h
|
|
index 15ecc6b..7933ff5 100644
|
|
--- a/support/include/nfs/nfs.h
|
|
+++ b/support/include/nfs/nfs.h
|
|
@@ -16,8 +16,8 @@
|
|
#define NFSD_MINVERS 2
|
|
#define NFSD_MAXVERS 4
|
|
|
|
-#define NFS4_MINMINOR 1
|
|
-#define NFS4_MAXMINOR WORD_BIT
|
|
+#define NFS4_MINMINOR 0
|
|
+#define NFS4_MAXMINOR (WORD_BIT-1)
|
|
|
|
struct nfs_fh_len {
|
|
int fh_size;
|
|
@@ -27,21 +27,24 @@ struct nfs_fh_len {
|
|
|
|
#define NFSCTL_UDPBIT (1 << (17 - 1))
|
|
#define NFSCTL_TCPBIT (1 << (18 - 1))
|
|
+#define NFSCTL_PROTODEFAULT (NFSCTL_TCPBIT)
|
|
|
|
#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << ((_v) - 1)))
|
|
+#define NFSCTL_MINORUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v)))
|
|
#define NFSCTL_UDPUNSET(_cltbits) ((_cltbits) &= ~NFSCTL_UDPBIT)
|
|
#define NFSCTL_TCPUNSET(_cltbits) ((_cltbits) &= ~NFSCTL_TCPBIT)
|
|
|
|
#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << ((_v) - 1)))
|
|
+#define NFSCTL_MINORISSET(_cltbits, _v) ((_cltbits) & (1 << (_v)))
|
|
#define NFSCTL_UDPISSET(_cltbits) ((_cltbits) & NFSCTL_UDPBIT)
|
|
#define NFSCTL_TCPISSET(_cltbits) ((_cltbits) & NFSCTL_TCPBIT)
|
|
|
|
#define NFSCTL_VERDEFAULT (0xc) /* versions 3 and 4 */
|
|
#define NFSCTL_VERSET(_cltbits, _v) ((_cltbits) |= (1 << ((_v) - 1)))
|
|
+#define NFSCTL_MINORSET(_cltbits, _v) ((_cltbits) |= (1 << (_v)))
|
|
#define NFSCTL_UDPSET(_cltbits) ((_cltbits) |= NFSCTL_UDPBIT)
|
|
#define NFSCTL_TCPSET(_cltbits) ((_cltbits) |= NFSCTL_TCPBIT)
|
|
|
|
#define NFSCTL_ANYPROTO(_cltbits) ((_cltbits) & (NFSCTL_UDPBIT | NFSCTL_TCPBIT))
|
|
-#define NFSCTL_ALLBITS (~0)
|
|
|
|
#endif /* _NFS_NFS_H */
|
|
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
|
|
index 1498977..ab8b2bf 100644
|
|
--- a/support/include/nfslib.h
|
|
+++ b/support/include/nfslib.h
|
|
@@ -35,29 +35,24 @@
|
|
#ifndef _PATH_IDMAPDCONF
|
|
#define _PATH_IDMAPDCONF "/etc/idmapd.conf"
|
|
#endif
|
|
-#ifndef _PATH_ETAB
|
|
-#define _PATH_ETAB NFS_STATEDIR "/etab"
|
|
-#endif
|
|
-#ifndef _PATH_ETABTMP
|
|
-#define _PATH_ETABTMP NFS_STATEDIR "/etab.tmp"
|
|
-#endif
|
|
-#ifndef _PATH_ETABLCK
|
|
-#define _PATH_ETABLCK NFS_STATEDIR "/.etab.lock"
|
|
-#endif
|
|
-#ifndef _PATH_RMTAB
|
|
-#define _PATH_RMTAB NFS_STATEDIR "/rmtab"
|
|
-#endif
|
|
-#ifndef _PATH_RMTABTMP
|
|
-#define _PATH_RMTABTMP _PATH_RMTAB ".tmp"
|
|
-#endif
|
|
-#ifndef _PATH_RMTABLCK
|
|
-#define _PATH_RMTABLCK NFS_STATEDIR "/.rmtab.lock"
|
|
-#endif
|
|
#ifndef _PATH_PROC_EXPORTS
|
|
#define _PATH_PROC_EXPORTS "/proc/fs/nfs/exports"
|
|
#define _PATH_PROC_EXPORTS_ALT "/proc/fs/nfsd/exports"
|
|
#endif
|
|
|
|
+#define ETAB "etab"
|
|
+#define ETABTMP "etab.tmp"
|
|
+#define ETABLCK ".etab.lock"
|
|
+#define RMTAB "rmtab"
|
|
+#define RMTABTMP "rmtab.tmp"
|
|
+#define RMTABLCK ".rmtab.lock"
|
|
+
|
|
+struct state_paths {
|
|
+ char *statefn;
|
|
+ char *tmpfn;
|
|
+ char *lockfn;
|
|
+};
|
|
+
|
|
/* Maximum number of security flavors on an export: */
|
|
#define SECFLAVOR_COUNT 8
|
|
|
|
@@ -120,6 +115,10 @@ void fputrmtabent(FILE *fp, struct rmtabent *xep, long *pos);
|
|
void fendrmtabent(FILE *fp);
|
|
void frewindrmtabent(FILE *fp);
|
|
|
|
+_Bool state_setup_basedir(const char *, const char *);
|
|
+int setup_state_path_names(const char *, const char *, const char *, const char *, struct state_paths *);
|
|
+void free_state_path_names(struct state_paths *);
|
|
+
|
|
/* mydaemon */
|
|
void daemon_init(bool fg);
|
|
void daemon_ready(void);
|
|
diff --git a/support/misc/Makefile.am b/support/misc/Makefile.am
|
|
index 1048580..8936b0d 100644
|
|
--- a/support/misc/Makefile.am
|
|
+++ b/support/misc/Makefile.am
|
|
@@ -1,6 +1,6 @@
|
|
## Process this file with automake to produce Makefile.in
|
|
|
|
noinst_LIBRARIES = libmisc.a
|
|
-libmisc_a_SOURCES = tcpwrapper.c from_local.c mountpoint.c
|
|
+libmisc_a_SOURCES = tcpwrapper.c from_local.c mountpoint.c file.c
|
|
|
|
MAINTAINERCLEANFILES = Makefile.in
|
|
diff --git a/support/misc/file.c b/support/misc/file.c
|
|
new file mode 100644
|
|
index 0000000..63597df
|
|
--- /dev/null
|
|
+++ b/support/misc/file.c
|
|
@@ -0,0 +1,110 @@
|
|
+/*
|
|
+ * Copyright 2009 Oracle. All rights reserved.
|
|
+ * Copyright 2017 Red Hat, Inc. All rights reserved.
|
|
+ *
|
|
+ * This file is part of nfs-utils.
|
|
+ *
|
|
+ * nfs-utils is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * nfs-utils is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with nfs-utils. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include <sys/stat.h>
|
|
+
|
|
+#include <string.h>
|
|
+#include <libgen.h>
|
|
+#include <stdio.h>
|
|
+#include <errno.h>
|
|
+#include <dirent.h>
|
|
+#include <stdlib.h>
|
|
+#include <stdbool.h>
|
|
+
|
|
+#include "xlog.h"
|
|
+#include "misc.h"
|
|
+
|
|
+/*
|
|
+ * Returns a dynamically allocated, '\0'-terminated buffer
|
|
+ * containing an appropriate pathname, or NULL if an error
|
|
+ * occurs. Caller must free the returned result with free(3).
|
|
+ */
|
|
+__attribute__((__malloc__))
|
|
+char *
|
|
+generic_make_pathname(const char *base, const char *leaf)
|
|
+{
|
|
+ size_t size;
|
|
+ char *path;
|
|
+ int len;
|
|
+
|
|
+ size = strlen(base) + strlen(leaf) + 2;
|
|
+ if (size > PATH_MAX)
|
|
+ return NULL;
|
|
+
|
|
+ path = malloc(size);
|
|
+ if (path == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ len = snprintf(path, size, "%s/%s", base, leaf);
|
|
+ if ((len < 0) || ((size_t)len >= size)) {
|
|
+ free(path);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return path;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * generic_setup_basedir - set up basedir
|
|
+ * @progname: C string containing name of program, for error messages
|
|
+ * @parentdir: C string containing pathname to on-disk state, or NULL
|
|
+ * @base: character buffer to contain the basedir that is set up
|
|
+ * @baselen: size of @base in bytes
|
|
+ *
|
|
+ * This runs before logging is set up, so error messages are directed
|
|
+ * to stderr.
|
|
+ *
|
|
+ * Returns true and sets up our basedir, if @parentdir was valid
|
|
+ * and usable; otherwise false is returned.
|
|
+ */
|
|
+_Bool
|
|
+generic_setup_basedir(const char *progname, const char *parentdir, char *base,
|
|
+ const size_t baselen)
|
|
+{
|
|
+ static char buf[PATH_MAX];
|
|
+ struct stat st;
|
|
+ char *path;
|
|
+
|
|
+ /* First: test length of name and whether it exists */
|
|
+ if ((strlen(parentdir) >= baselen) || (strlen(parentdir) >= PATH_MAX)) {
|
|
+ (void)fprintf(stderr, "%s: Directory name too long: %s",
|
|
+ progname, parentdir);
|
|
+ return false;
|
|
+ }
|
|
+ if (lstat(parentdir, &st) == -1) {
|
|
+ (void)fprintf(stderr, "%s: Failed to stat %s: %s",
|
|
+ progname, parentdir, strerror(errno));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /* Ensure we have a clean directory pathname */
|
|
+ strncpy(buf, parentdir, sizeof(buf));
|
|
+ path = dirname(buf);
|
|
+ if (*path == '.') {
|
|
+ (void)fprintf(stderr, "%s: Unusable directory %s",
|
|
+ progname, parentdir);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ xlog(D_CALL, "Using %s as the state directory", parentdir);
|
|
+ strcpy(base, parentdir);
|
|
+ return true;
|
|
+}
|
|
diff --git a/support/misc/tcpwrapper.c b/support/misc/tcpwrapper.c
|
|
index 06b0a46..3128053 100644
|
|
--- a/support/misc/tcpwrapper.c
|
|
+++ b/support/misc/tcpwrapper.c
|
|
@@ -72,6 +72,7 @@ present_address(const struct sockaddr *sap, char *buf, const size_t buflen)
|
|
case AF_INET:
|
|
if (inet_ntop(AF_INET, &sin->sin_addr, buf, len) != 0)
|
|
return;
|
|
+ break;
|
|
case AF_INET6:
|
|
if (inet_ntop(AF_INET6, &sin6->sin6_addr, buf, len) != 0)
|
|
return;
|
|
diff --git a/support/nfs/atomicio.c b/support/nfs/atomicio.c
|
|
index 5e760e6..aa819ca 100644
|
|
--- a/support/nfs/atomicio.c
|
|
+++ b/support/nfs/atomicio.c
|
|
@@ -42,6 +42,7 @@ ssize_t atomicio(ssize_t(*f) (int, void *, size_t), int fd, void *_s, size_t n)
|
|
case -1:
|
|
if (errno == EINTR || errno == EAGAIN)
|
|
continue;
|
|
+ /* FALLTHRU */
|
|
case 0:
|
|
if (pos != 0)
|
|
return pos;
|
|
diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c
|
|
index e5e2579..9912afa 100644
|
|
--- a/support/nfs/cacheio.c
|
|
+++ b/support/nfs/cacheio.c
|
|
@@ -27,6 +27,8 @@
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
|
|
+extern struct state_paths etab;
|
|
+
|
|
void qword_add(char **bpp, int *lp, char *str)
|
|
{
|
|
char *bp = *bpp;
|
|
@@ -199,7 +201,7 @@ int qword_get_uint(char **bpp, unsigned int *anint)
|
|
}
|
|
|
|
/* flush the kNFSd caches.
|
|
- * Set the flush time to the mtime of _PATH_ETAB or
|
|
+ * Set the flush time to the mtime of the etab state file or
|
|
* if force, to now.
|
|
* the caches to flush are:
|
|
* auth.unix.ip nfsd.export nfsd.fh
|
|
@@ -228,7 +230,7 @@ cache_flush(int force)
|
|
};
|
|
now = time(0);
|
|
if (force ||
|
|
- stat(_PATH_ETAB, &stb) != 0 ||
|
|
+ stat(etab.statefn, &stb) != 0 ||
|
|
stb.st_mtime > now)
|
|
stb.st_mtime = time(0);
|
|
|
|
diff --git a/support/nfs/conffile.c b/support/nfs/conffile.c
|
|
index e717c1e..8690218 100644
|
|
--- a/support/nfs/conffile.c
|
|
+++ b/support/nfs/conffile.c
|
|
@@ -30,6 +30,10 @@
|
|
* This code was written under funding by Ericsson Radio Systems.
|
|
*/
|
|
|
|
+#ifdef HAVE_CONFIG_H
|
|
+#include <config.h>
|
|
+#endif
|
|
+
|
|
#include <sys/param.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/socket.h>
|
|
@@ -52,9 +56,11 @@
|
|
#pragma GCC visibility push(hidden)
|
|
|
|
static void conf_load_defaults(void);
|
|
-static int conf_load(int trans, char *path);
|
|
+static char * conf_load(const char *path);
|
|
static int conf_set(int , char *, char *, char *,
|
|
char *, int , int );
|
|
+static void conf_parse(int trans, char *buf,
|
|
+ char **section, char **subsection);
|
|
|
|
struct conf_trans {
|
|
TAILQ_ENTRY (conf_trans) link;
|
|
@@ -73,8 +79,10 @@ TAILQ_HEAD (conf_trans_head, conf_trans) conf_trans_queue;
|
|
/*
|
|
* Radix-64 Encoding.
|
|
*/
|
|
+#if 0
|
|
static const uint8_t bin2asc[]
|
|
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
+#endif
|
|
|
|
static const uint8_t asc2bin[] =
|
|
{
|
|
@@ -105,7 +113,6 @@ struct conf_binding {
|
|
int is_default;
|
|
};
|
|
|
|
-char *conf_path;
|
|
LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256];
|
|
|
|
static __inline__ uint8_t
|
|
@@ -199,7 +206,6 @@ conf_set_now(char *section, char *arg, char *tag,
|
|
node->tag = strdup(tag);
|
|
node->value = strdup(value);
|
|
node->is_default = is_default;
|
|
-
|
|
LIST_INSERT_HEAD(&conf_bindings[conf_hash (section)], node, link);
|
|
return 0;
|
|
}
|
|
@@ -209,17 +215,10 @@ conf_set_now(char *section, char *arg, char *tag,
|
|
* headers and feed tag-value pairs into our configuration database.
|
|
*/
|
|
static void
|
|
-conf_parse_line(int trans, char *line, size_t sz)
|
|
+conf_parse_line(int trans, char *line, int lineno, char **section, char **subsection)
|
|
{
|
|
char *val, *ptr;
|
|
- size_t i;
|
|
- size_t j;
|
|
- static char *section = 0;
|
|
- static char *arg = 0;
|
|
- static int ln = 0;
|
|
|
|
- /* Lines starting with '#' or ';' are comments. */
|
|
- ln++;
|
|
/* Ignore blank lines */
|
|
if (*line == '\0')
|
|
return;
|
|
@@ -228,123 +227,188 @@ conf_parse_line(int trans, char *line, size_t sz)
|
|
while (isblank(*line))
|
|
line++;
|
|
|
|
+ /* Lines starting with '#' or ';' are comments. */
|
|
if (*line == '#' || *line == ';')
|
|
return;
|
|
|
|
/* '[section]' parsing... */
|
|
if (*line == '[') {
|
|
line++;
|
|
+
|
|
+ if (*section) {
|
|
+ free(*section);
|
|
+ *section = NULL;
|
|
+ }
|
|
+ if (*subsection) {
|
|
+ free(*subsection);
|
|
+ *subsection = NULL;
|
|
+ }
|
|
+
|
|
/* Strip off any blanks after '[' */
|
|
while (isblank(*line))
|
|
line++;
|
|
- for (i = 0; i < sz; i++) {
|
|
- if (line[i] == ']') {
|
|
- break;
|
|
- }
|
|
- }
|
|
- if (section)
|
|
- free(section);
|
|
- if (i == sz) {
|
|
+
|
|
+ /* find the closing ] */
|
|
+ ptr = strchr(line, ']');
|
|
+ if (ptr == NULL) {
|
|
xlog_warn("config file error: line %d: "
|
|
- "non-matched ']', ignoring until next section", ln);
|
|
- section = 0;
|
|
+ "non-matched ']', ignoring until next section", lineno);
|
|
return;
|
|
}
|
|
+
|
|
+ /* just ignore everything after the closing ] */
|
|
+ *(ptr--) = '\0';
|
|
+
|
|
/* Strip off any blanks before ']' */
|
|
- val = line;
|
|
- j=0;
|
|
- while (*val && !isblank(*val))
|
|
- val++, j++;
|
|
- if (*val)
|
|
- i = j;
|
|
- section = malloc(i+1);
|
|
- if (!section) {
|
|
- xlog_warn("conf_parse_line: %d: malloc (%lu) failed", ln,
|
|
- (unsigned long)i);
|
|
+ while (ptr >= line && isblank(*ptr))
|
|
+ *(ptr--)='\0';
|
|
+
|
|
+ /* look for an arg to split from the section name */
|
|
+ val = strchr(line, '"');
|
|
+ if (val != NULL) {
|
|
+ ptr = val - 1;
|
|
+ *(val++) = '\0';
|
|
+
|
|
+ /* trim away any whitespace before the " */
|
|
+ while (ptr > line && isblank(*ptr))
|
|
+ *(ptr--)='\0';
|
|
+ }
|
|
+
|
|
+ /* copy the section name */
|
|
+ *section = strdup(line);
|
|
+ if (!*section) {
|
|
+ xlog_warn("conf_parse_line: %d: malloc failed", lineno);
|
|
return;
|
|
}
|
|
- strncpy(section, line, i);
|
|
- section[i] = '\0';
|
|
|
|
- if (arg)
|
|
- free(arg);
|
|
- arg = 0;
|
|
+ /* there is no arg, we are done */
|
|
+ if (val == NULL) return;
|
|
|
|
+ /* check for the closing " */
|
|
ptr = strchr(val, '"');
|
|
- if (ptr == NULL)
|
|
- return;
|
|
- line = ++ptr;
|
|
- while (*ptr && *ptr != '"' && *ptr != ']')
|
|
- ptr++;
|
|
- if (*ptr == '\0' || *ptr == ']') {
|
|
+ if (ptr == NULL) {
|
|
xlog_warn("config file error: line %d: "
|
|
- "non-matched '\"', ignoring until next section", ln);
|
|
- } else {
|
|
- *ptr = '\0';
|
|
- arg = strdup(line);
|
|
- if (!arg)
|
|
- xlog_warn("conf_parse_line: %d: malloc arg failed", ln);
|
|
+ "non-matched '\"', ignoring until next section", lineno);
|
|
+ return;
|
|
}
|
|
+ *ptr = '\0';
|
|
+ *subsection = strdup(val);
|
|
+ if (!*subsection)
|
|
+ xlog_warn("conf_parse_line: %d: malloc arg failed", lineno);
|
|
return;
|
|
}
|
|
|
|
/* Deal with assignments. */
|
|
- for (i = 0; i < sz; i++) {
|
|
- if (line[i] == '=') {
|
|
- /* If no section, we are ignoring the lines. */
|
|
- if (!section) {
|
|
+ ptr = strchr(line, '=');
|
|
+
|
|
+ /* not an assignment line */
|
|
+ if (ptr == NULL) {
|
|
+ /* Other non-empty lines are weird. */
|
|
+ if (line[strspn(line, " \t")])
|
|
xlog_warn("config file error: line %d: "
|
|
- "ignoring line due to no section", ln);
|
|
- return;
|
|
- }
|
|
- line[strcspn (line, " \t=")] = '\0';
|
|
- val = line + i + 1 + strspn (line + i + 1, " \t");
|
|
-
|
|
- if (val[0] == '"') {
|
|
- val ++;
|
|
- j = strcspn(val, "\"");
|
|
- val[j] = 0;
|
|
- } else if (val[0] == '\'') {
|
|
- val ++;
|
|
- j = strcspn(val, "'");
|
|
- val[j] = 0;
|
|
- } else {
|
|
- /* Skip trailing spaces and comments */
|
|
- for (j = 0; val[j]; j++) {
|
|
- if ((val[j] == '#' || val[j] == ';')
|
|
- && (j == 0 || isspace(val[j-1]))) {
|
|
- val[j] = '\0';
|
|
- break;
|
|
- }
|
|
- }
|
|
- while (j && isspace(val[j-1]))
|
|
- val[--j] = '\0';
|
|
- }
|
|
- if (strcasecmp(line, "include") == 0)
|
|
- conf_load(trans, val);
|
|
- else
|
|
- /* XXX Perhaps should we not ignore errors? */
|
|
- conf_set(trans, section, arg, line, val, 0, 0);
|
|
+ "line not empty and not an assignment", lineno);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* If no section, we are ignoring the line. */
|
|
+ if (!*section) {
|
|
+ xlog_warn("config file error: line %d: "
|
|
+ "ignoring line due to no section", lineno);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ val = ptr + 1;
|
|
+ *(ptr--) = '\0';
|
|
+
|
|
+ /* strip spaces before and after the = */
|
|
+ while (ptr >= line && isblank(*ptr))
|
|
+ *(ptr--)='\0';
|
|
+ while (*val != '\0' && isblank(*val))
|
|
+ val++;
|
|
+
|
|
+ if (*val == '"') {
|
|
+ val++;
|
|
+ ptr = strchr(val, '"');
|
|
+ if (ptr == NULL) {
|
|
+ xlog_warn("config file error: line %d: "
|
|
+ "unmatched quotes", lineno);
|
|
+ return;
|
|
+ }
|
|
+ *ptr = '\0';
|
|
+ } else
|
|
+ if (*val == '\'') {
|
|
+ val++;
|
|
+ ptr = strchr(val, '\'');
|
|
+ if (ptr == NULL) {
|
|
+ xlog_warn("config file error: line %d: "
|
|
+ "unmatched quotes", lineno);
|
|
return;
|
|
}
|
|
+ *ptr = '\0';
|
|
+ } else {
|
|
+ /* Trim any trailing spaces and comments */
|
|
+ if ((ptr=strchr(val, '#'))!=NULL)
|
|
+ *ptr = '\0';
|
|
+ if ((ptr=strchr(val, ';'))!=NULL)
|
|
+ *ptr = '\0';
|
|
+
|
|
+ ptr = val + strlen(val) - 1;
|
|
+ while (ptr > val && isspace(*ptr))
|
|
+ *(ptr--) = '\0';
|
|
}
|
|
- /* Other non-empty lines are weird. */
|
|
- i = strspn(line, " \t");
|
|
- if (line[i])
|
|
- xlog_warn("config file error: line %d:", ln);
|
|
|
|
- return;
|
|
+ if (*line == '\0') {
|
|
+ xlog_warn("config file error: line %d: "
|
|
+ "missing tag in assignment", lineno);
|
|
+ return;
|
|
+ }
|
|
+ if (*val == '\0') {
|
|
+ xlog_warn("config file error: line %d: "
|
|
+ "missing value in assignment", lineno);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (strcasecmp(line, "include")==0) {
|
|
+ /* load and parse subordinate config files */
|
|
+ char * subconf = conf_load(val);
|
|
+ if (subconf == NULL) {
|
|
+ xlog_warn("config file error: line %d: "
|
|
+ "error loading included config", lineno);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* copy the section data so the included file can inherit it
|
|
+ * without accidentally changing it for us */
|
|
+ char * inc_section = NULL;
|
|
+ char * inc_subsection = NULL;
|
|
+ if (*section != NULL) {
|
|
+ inc_section = strdup(*section);
|
|
+ if (*subsection != NULL)
|
|
+ inc_subsection = strdup(*subsection);
|
|
+ }
|
|
+
|
|
+ conf_parse(trans, subconf, &inc_section, &inc_subsection);
|
|
+
|
|
+ if (inc_section) free(inc_section);
|
|
+ if (inc_subsection) free(inc_subsection);
|
|
+ free(subconf);
|
|
+ } else {
|
|
+ /* XXX Perhaps should we not ignore errors? */
|
|
+ conf_set(trans, *section, *subsection, line, val, 0, 0);
|
|
+ }
|
|
}
|
|
|
|
/* Parse the mapped configuration file. */
|
|
static void
|
|
-conf_parse(int trans, char *buf, size_t sz)
|
|
+conf_parse(int trans, char *buf, char **section, char **subsection)
|
|
{
|
|
char *cp = buf;
|
|
- char *bufend = buf + sz;
|
|
+ char *bufend = NULL;
|
|
char *line;
|
|
+ int lineno = 0;
|
|
|
|
line = cp;
|
|
+ bufend = buf + strlen(buf);
|
|
while (cp < bufend) {
|
|
if (*cp == '\n') {
|
|
/* Check for escaped newlines. */
|
|
@@ -352,7 +416,8 @@ conf_parse(int trans, char *buf, size_t sz)
|
|
*(cp - 1) = *cp = ' ';
|
|
else {
|
|
*cp = '\0';
|
|
- conf_parse_line(trans, line, cp - line);
|
|
+ lineno++;
|
|
+ conf_parse_line(trans, line, lineno, section, subsection);
|
|
line = cp + 1;
|
|
}
|
|
}
|
|
@@ -369,33 +434,21 @@ conf_load_defaults(void)
|
|
return;
|
|
}
|
|
|
|
-void
|
|
-conf_init (void)
|
|
-{
|
|
- unsigned int i;
|
|
-
|
|
- for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
|
|
- LIST_INIT (&conf_bindings[i]);
|
|
-
|
|
- TAILQ_INIT (&conf_trans_queue);
|
|
- conf_reinit();
|
|
-}
|
|
-
|
|
-static int
|
|
-conf_load(int trans, char *path)
|
|
+static char *
|
|
+conf_load(const char *path)
|
|
{
|
|
struct stat sb;
|
|
if ((stat (path, &sb) == 0) || (errno != ENOENT)) {
|
|
- char *new_conf_addr;
|
|
+ char *new_conf_addr = NULL;
|
|
size_t sz = sb.st_size;
|
|
int fd = open (path, O_RDONLY, 0);
|
|
|
|
if (fd == -1) {
|
|
xlog_warn("conf_reinit: open (\"%s\", O_RDONLY) failed", path);
|
|
- return -1;
|
|
+ return NULL;
|
|
}
|
|
|
|
- new_conf_addr = malloc(sz);
|
|
+ new_conf_addr = malloc(sz+1);
|
|
if (!new_conf_addr) {
|
|
xlog_warn("conf_reinit: malloc (%lu) failed", (unsigned long)sz);
|
|
goto fail;
|
|
@@ -410,42 +463,103 @@ conf_load(int trans, char *path)
|
|
close(fd);
|
|
|
|
/* XXX Should we not care about errors and rollback? */
|
|
- conf_parse(trans, new_conf_addr, sz);
|
|
- free(new_conf_addr);
|
|
- return 0;
|
|
+ new_conf_addr[sz] = '\0';
|
|
+ return new_conf_addr;
|
|
fail:
|
|
close(fd);
|
|
- free(new_conf_addr);
|
|
+ if (new_conf_addr) free(new_conf_addr);
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/* remove and free up any existing config state */
|
|
+static void conf_free_bindings(void)
|
|
+{
|
|
+ unsigned int i;
|
|
+ for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) {
|
|
+ struct conf_binding *cb, *next;
|
|
+
|
|
+ cb = LIST_FIRST(&conf_bindings[i]);
|
|
+ for (; cb; cb = next) {
|
|
+ next = LIST_NEXT(cb, link);
|
|
+ LIST_REMOVE(cb, link);
|
|
+ free(cb->section);
|
|
+ free(cb->arg);
|
|
+ free(cb->tag);
|
|
+ free(cb->value);
|
|
+ free(cb);
|
|
+ }
|
|
+ LIST_INIT(&conf_bindings[i]);
|
|
}
|
|
- return -1;
|
|
}
|
|
|
|
/* Open the config file and map it into our address space, then parse it. */
|
|
-void
|
|
-conf_reinit(void)
|
|
+static void
|
|
+conf_reinit(const char *conf_file)
|
|
{
|
|
- struct conf_binding *cb = 0;
|
|
int trans;
|
|
- unsigned int i;
|
|
+ char * conf_data;
|
|
|
|
trans = conf_begin();
|
|
- if (conf_load(trans, conf_path) < 0)
|
|
+ conf_data = conf_load(conf_file);
|
|
+
|
|
+ if (conf_data == NULL)
|
|
return;
|
|
|
|
/* Load default configuration values. */
|
|
conf_load_defaults();
|
|
|
|
+ /* Parse config contents into the transaction queue */
|
|
+ char *section = NULL;
|
|
+ char *subsection = NULL;
|
|
+ conf_parse(trans, conf_data, §ion, &subsection);
|
|
+ if (section) free(section);
|
|
+ if (subsection) free(subsection);
|
|
+ free(conf_data);
|
|
+
|
|
/* Free potential existing configuration. */
|
|
- for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) {
|
|
- cb = LIST_FIRST (&conf_bindings[i]);
|
|
- for (; cb; cb = LIST_FIRST (&conf_bindings[i]))
|
|
- conf_remove_now(cb->section, cb->tag);
|
|
- }
|
|
+ conf_free_bindings();
|
|
|
|
+ /* Apply the new configuration values */
|
|
conf_end(trans, 1);
|
|
return;
|
|
}
|
|
|
|
+void
|
|
+conf_init (const char *conf_file)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
|
|
+ LIST_INIT (&conf_bindings[i]);
|
|
+
|
|
+ TAILQ_INIT (&conf_trans_queue);
|
|
+
|
|
+ if (conf_file == NULL) conf_file=NFS_CONFFILE;
|
|
+ conf_reinit(conf_file);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Empty the config and free up any used memory
|
|
+ */
|
|
+void
|
|
+conf_cleanup(void)
|
|
+{
|
|
+ conf_free_bindings();
|
|
+
|
|
+ struct conf_trans *node, *next;
|
|
+ for (node = TAILQ_FIRST(&conf_trans_queue); node; node = next) {
|
|
+ next = TAILQ_NEXT(node, link);
|
|
+ TAILQ_REMOVE (&conf_trans_queue, node, link);
|
|
+ if (node->section) free(node->section);
|
|
+ if (node->arg) free(node->arg);
|
|
+ if (node->tag) free(node->tag);
|
|
+ if (node->value) free(node->value);
|
|
+ free (node);
|
|
+ }
|
|
+ TAILQ_INIT(&conf_trans_queue);
|
|
+}
|
|
+
|
|
/*
|
|
* Return the numeric value denoted by TAG in section SECTION or DEF
|
|
* if that tag does not exist.
|
|
@@ -533,7 +647,7 @@ retry:
|
|
* or from environment
|
|
*/
|
|
char *env = getenv(cb->value+1);
|
|
- if (env)
|
|
+ if (env && *env)
|
|
return env;
|
|
section = "environment";
|
|
tag = cb->value + 1;
|
|
diff --git a/support/nfs/rmtab.c b/support/nfs/rmtab.c
|
|
index 59dfbdf..2ecb2cc 100644
|
|
--- a/support/nfs/rmtab.c
|
|
+++ b/support/nfs/rmtab.c
|
|
@@ -33,12 +33,14 @@
|
|
|
|
static FILE *rmfp = NULL;
|
|
|
|
+extern struct state_paths rmtab;
|
|
+
|
|
int
|
|
setrmtabent(char *type)
|
|
{
|
|
if (rmfp)
|
|
fclose(rmfp);
|
|
- rmfp = fsetrmtabent(_PATH_RMTAB, type);
|
|
+ rmfp = fsetrmtabent(rmtab.statefn, type);
|
|
return (rmfp != NULL);
|
|
}
|
|
|
|
diff --git a/support/nsm/file.c b/support/nsm/file.c
|
|
index aafa755..52f5401 100644
|
|
--- a/support/nsm/file.c
|
|
+++ b/support/nsm/file.c
|
|
@@ -88,6 +88,7 @@
|
|
|
|
#include "xlog.h"
|
|
#include "nsm.h"
|
|
+#include "misc.h"
|
|
|
|
#define RPCARGSLEN (4 * (8 + 1))
|
|
#define LINELEN (RPCARGSLEN + SM_PRIV_SIZE * 2 + 1)
|
|
@@ -170,25 +171,7 @@ __attribute__((__malloc__))
|
|
static char *
|
|
nsm_make_pathname(const char *directory)
|
|
{
|
|
- size_t size;
|
|
- char *path;
|
|
- int len;
|
|
-
|
|
- size = strlen(nsm_base_dirname) + strlen(directory) + 2;
|
|
- if (size > PATH_MAX)
|
|
- return NULL;
|
|
-
|
|
- path = malloc(size);
|
|
- if (path == NULL)
|
|
- return NULL;
|
|
-
|
|
- len = snprintf(path, size, "%s/%s", nsm_base_dirname, directory);
|
|
- if (error_check(len, size)) {
|
|
- free(path);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- return path;
|
|
+ return generic_make_pathname(nsm_base_dirname, directory);
|
|
}
|
|
|
|
/*
|
|
@@ -293,29 +276,8 @@ out:
|
|
_Bool
|
|
nsm_setup_pathnames(const char *progname, const char *parentdir)
|
|
{
|
|
- static char buf[PATH_MAX];
|
|
- struct stat st;
|
|
- char *path;
|
|
-
|
|
- /* First: test length of name and whether it exists */
|
|
- if (lstat(parentdir, &st) == -1) {
|
|
- (void)fprintf(stderr, "%s: Failed to stat %s: %s",
|
|
- progname, parentdir, strerror(errno));
|
|
- return false;
|
|
- }
|
|
-
|
|
- /* Ensure we have a clean directory pathname */
|
|
- strncpy(buf, parentdir, sizeof(buf));
|
|
- path = dirname(buf);
|
|
- if (*path == '.') {
|
|
- (void)fprintf(stderr, "%s: Unusable directory %s",
|
|
- progname, parentdir);
|
|
- return false;
|
|
- }
|
|
-
|
|
- xlog(D_CALL, "Using %s as the state directory", parentdir);
|
|
- strncpy(nsm_base_dirname, parentdir, sizeof(nsm_base_dirname));
|
|
- return true;
|
|
+ return generic_setup_basedir(progname, parentdir, nsm_base_dirname,
|
|
+ PATH_MAX);
|
|
}
|
|
|
|
/**
|
|
diff --git a/support/nsm/rpc.c b/support/nsm/rpc.c
|
|
index 4e5f40e..0a8e56f 100644
|
|
--- a/support/nsm/rpc.c
|
|
+++ b/support/nsm/rpc.c
|
|
@@ -38,6 +38,7 @@
|
|
#include <sys/socket.h>
|
|
#include <sys/time.h>
|
|
|
|
+#include <stdint.h>
|
|
#include <time.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
diff --git a/systemd/Makefile.am b/systemd/Makefile.am
|
|
index 0d15b9f..eef53c4 100644
|
|
--- a/systemd/Makefile.am
|
|
+++ b/systemd/Makefile.am
|
|
@@ -4,6 +4,7 @@ MAINTAINERCLEANFILES = Makefile.in
|
|
|
|
unit_files = \
|
|
nfs-client.target \
|
|
+ rpc_pipefs.target \
|
|
\
|
|
nfs-mountd.service \
|
|
nfs-server.service \
|
|
@@ -42,14 +43,23 @@ EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS)
|
|
unit_dir = /usr/lib/systemd/system
|
|
generator_dir = /usr/lib/systemd/system-generators
|
|
|
|
-EXTRA_PROGRAMS = nfs-server-generator
|
|
+EXTRA_PROGRAMS = nfs-server-generator rpc-pipefs-generator
|
|
genexecdir = $(generator_dir)
|
|
+
|
|
+COMMON_SRCS = systemd.c systemd.h
|
|
+
|
|
+nfs_server_generator_SOURCES = $(COMMON_SRCS) nfs-server-generator.c
|
|
+
|
|
+rpc_pipefs_generator_SOURCES = $(COMMON_SRCS) rpc-pipefs-generator.c
|
|
+
|
|
nfs_server_generator_LDADD = ../support/export/libexport.a \
|
|
../support/nfs/libnfs.a \
|
|
../support/misc/libmisc.a
|
|
|
|
+rpc_pipefs_generator_LDADD = ../support/nfs/libnfs.a
|
|
+
|
|
if INSTALL_SYSTEMD
|
|
-genexec_PROGRAMS = nfs-server-generator
|
|
+genexec_PROGRAMS = nfs-server-generator rpc-pipefs-generator
|
|
install-data-hook: $(unit_files)
|
|
mkdir -p $(DESTDIR)/$(unitdir)
|
|
cp $(unit_files) $(DESTDIR)/$(unitdir)
|
|
diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service
|
|
index ddc324e..2bbcee6 100644
|
|
--- a/systemd/nfs-blkmap.service
|
|
+++ b/systemd/nfs-blkmap.service
|
|
@@ -2,8 +2,8 @@
|
|
Description=pNFS block layout mapping daemon
|
|
DefaultDependencies=no
|
|
Conflicts=umount.target
|
|
-After=var-lib-nfs-rpc_pipefs.mount
|
|
-Requires=var-lib-nfs-rpc_pipefs.mount
|
|
+After=rpc_pipefs.target
|
|
+Requires=rpc_pipefs.target
|
|
|
|
PartOf=nfs-utils.service
|
|
|
|
diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service
|
|
index acca86b..f38fe52 100644
|
|
--- a/systemd/nfs-idmapd.service
|
|
+++ b/systemd/nfs-idmapd.service
|
|
@@ -1,8 +1,8 @@
|
|
[Unit]
|
|
Description=NFSv4 ID-name mapping service
|
|
DefaultDependencies=no
|
|
-Requires=var-lib-nfs-rpc_pipefs.mount
|
|
-After=var-lib-nfs-rpc_pipefs.mount local-fs.target
|
|
+Requires=rpc_pipefs.target
|
|
+After=rpc_pipefs.target local-fs.target
|
|
|
|
BindsTo=nfs-server.service
|
|
|
|
diff --git a/systemd/nfs-mountd.service b/systemd/nfs-mountd.service
|
|
index 15e828b..e8ece53 100644
|
|
--- a/systemd/nfs-mountd.service
|
|
+++ b/systemd/nfs-mountd.service
|
|
@@ -2,8 +2,10 @@
|
|
Description=NFS Mount Daemon
|
|
DefaultDependencies=no
|
|
Requires=proc-fs-nfsd.mount
|
|
+Wants=network-online.target
|
|
After=proc-fs-nfsd.mount
|
|
-After=network.target local-fs.target
|
|
+After=network-online.target local-fs.target
|
|
+After=rpcbind.socket
|
|
BindsTo=nfs-server.service
|
|
|
|
[Service]
|
|
diff --git a/systemd/nfs-server-generator.c b/systemd/nfs-server-generator.c
|
|
index cc99969..737f109 100644
|
|
--- a/systemd/nfs-server-generator.c
|
|
+++ b/systemd/nfs-server-generator.c
|
|
@@ -29,6 +29,7 @@
|
|
#include "misc.h"
|
|
#include "nfslib.h"
|
|
#include "exportfs.h"
|
|
+#include "systemd.h"
|
|
|
|
/* A simple "set of strings" to remove duplicates
|
|
* found in /etc/exports
|
|
@@ -55,38 +56,31 @@ static int is_unique(struct list **lp, char *path)
|
|
return 1;
|
|
}
|
|
|
|
-/* We need to convert a path name to a systemd unit
|
|
- * name. This requires some translation ('/' -> '-')
|
|
- * and some escaping.
|
|
- */
|
|
-static void systemd_escape(FILE *f, char *path)
|
|
+static int has_noauto_flag(char *path)
|
|
{
|
|
- while (*path == '/')
|
|
- path++;
|
|
- if (!*path) {
|
|
- /* "/" becomes "-", otherwise leading "/" is ignored */
|
|
- fputs("-", f);
|
|
- return;
|
|
- }
|
|
- while (*path) {
|
|
- char c = *path++;
|
|
-
|
|
- if (c == '/') {
|
|
- /* multiple non-trailing slashes become '-' */
|
|
- while (*path == '/')
|
|
- path++;
|
|
- if (*path)
|
|
- fputs("-", f);
|
|
- } else if (isalnum(c) || c == ':' || c == '.')
|
|
- fputc(c, f);
|
|
- else
|
|
- fprintf(f, "\\x%02x", c & 0xff);
|
|
+ FILE *fstab;
|
|
+ struct mntent *mnt;
|
|
+
|
|
+ fstab = setmntent("/etc/fstab", "r");
|
|
+ if (!fstab)
|
|
+ return 0;
|
|
+
|
|
+ while ((mnt = getmntent(fstab)) != NULL) {
|
|
+ int l = strlen(mnt->mnt_dir);
|
|
+ if (strncmp(mnt->mnt_dir, path, l) != 0)
|
|
+ continue;
|
|
+ if (path[l] && path[l] != '/')
|
|
+ continue;
|
|
+ if (hasmntopt(mnt, "noauto"))
|
|
+ break;
|
|
}
|
|
+ fclose(fstab);
|
|
+ return mnt != NULL;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
- char *path;
|
|
+ char *path, *spath;
|
|
char dirbase[] = "/nfs-server.service.d";
|
|
char filebase[] = "/order-with-mounts.conf";
|
|
nfs_export *exp;
|
|
@@ -124,6 +118,10 @@ int main(int argc, char *argv[])
|
|
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
|
if (!is_unique(&list, exp->m_export.e_path))
|
|
continue;
|
|
+ if (exp->m_export.e_mountpoint)
|
|
+ continue;
|
|
+ if (has_noauto_flag(exp->m_export.e_path))
|
|
+ continue;
|
|
if (strchr(exp->m_export.e_path, ' '))
|
|
fprintf(f, "RequiresMountsFor=\"%s\"\n",
|
|
exp->m_export.e_path);
|
|
@@ -141,9 +139,15 @@ int main(int argc, char *argv[])
|
|
if (strcmp(mnt->mnt_type, "nfs") != 0 &&
|
|
strcmp(mnt->mnt_type, "nfs4") != 0)
|
|
continue;
|
|
- fprintf(f, "Before= ");
|
|
- systemd_escape(f, mnt->mnt_dir);
|
|
- fprintf(f, ".mount\n");
|
|
+
|
|
+ spath = systemd_escape(mnt->mnt_dir, ".mount");
|
|
+ if (!spath) {
|
|
+ fprintf(stderr,
|
|
+ "nfs-server-generator: convert path failed: %s\n",
|
|
+ mnt->mnt_dir);
|
|
+ continue;
|
|
+ }
|
|
+ fprintf(f, "Before=%s\n", spath);
|
|
}
|
|
|
|
fclose(fstab);
|
|
diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
|
|
index 5be5de6..136552b 100644
|
|
--- a/systemd/nfs-server.service
|
|
+++ b/systemd/nfs-server.service
|
|
@@ -3,12 +3,12 @@ Description=NFS server and services
|
|
DefaultDependencies=no
|
|
Requires= network.target proc-fs-nfsd.mount
|
|
Requires= nfs-mountd.service
|
|
-Wants=rpcbind.socket
|
|
+Wants=rpcbind.socket network-online.target
|
|
Wants=rpc-statd.service nfs-idmapd.service
|
|
Wants=rpc-statd-notify.service
|
|
|
|
-After= local-fs.target
|
|
-After= network.target proc-fs-nfsd.mount rpcbind.socket nfs-mountd.service
|
|
+After= network-online.target local-fs.target
|
|
+After= proc-fs-nfsd.mount rpcbind.socket nfs-mountd.service
|
|
After= nfs-idmapd.service rpc-statd.service
|
|
Before= rpc-statd-notify.service
|
|
|
|
diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
|
|
index 91c49a0..189b052 100644
|
|
--- a/systemd/nfs.conf.man
|
|
+++ b/systemd/nfs.conf.man
|
|
@@ -96,6 +96,18 @@ value, which can be one or more from the list
|
|
.BR all .
|
|
When a list is given, the members should be comma-separated.
|
|
.TP
|
|
+.B general
|
|
+Recognized values:
|
|
+.BR pipefs-directory .
|
|
+
|
|
+See
|
|
+.BR blkmapd (8),
|
|
+.BR rpc.idmapd (8),
|
|
+and
|
|
+.BR rpc.gssd (8)
|
|
+for details.
|
|
+
|
|
+.TP
|
|
.B nfsdcltrack
|
|
Recognized values:
|
|
.BR storagedir .
|
|
@@ -154,6 +166,13 @@ section, are used to configure mountd. See
|
|
.BR rpc.mountd (8)
|
|
for details.
|
|
|
|
+The
|
|
+.B state-directory-path
|
|
+value in the
|
|
+.B [mountd]
|
|
+section is also used by
|
|
+.BR exportfs (8).
|
|
+
|
|
.TP
|
|
.B statd
|
|
Recognized values:
|
|
@@ -198,7 +217,6 @@ Recognized values:
|
|
.BR limit-to-legacy-enctypes ,
|
|
.BR context-timeout ,
|
|
.BR rpc-timeout ,
|
|
-.BR pipefs-directory ,
|
|
.BR keytab-file ,
|
|
.BR cred-cache-directory ,
|
|
.BR preferred-realm .
|
|
diff --git a/systemd/nfs.systemd.man b/systemd/nfs.systemd.man
|
|
index 01801eb..46b476a 100644
|
|
--- a/systemd/nfs.systemd.man
|
|
+++ b/systemd/nfs.systemd.man
|
|
@@ -79,7 +79,7 @@ unit should be enabled.
|
|
Several other units which might be considered to be optional, such as
|
|
.I rpc-gssd.service
|
|
are careful to only start if the required configuration file exists.
|
|
-.I rpc-gsdd.service
|
|
+.I rpc-gssd.service
|
|
will not start if the
|
|
.I krb5.keytab
|
|
file does not exist (typically in
|
|
@@ -120,10 +120,11 @@ be needed to reduce system load to an absolute minimum, or to reduce
|
|
attack surface by not running daemons that are not absolutely
|
|
required.
|
|
.PP
|
|
-Two particular services which this can apply to are
|
|
-.I rpcbind
|
|
+Three particular services which this can apply to are
|
|
+.IR rpcbind ,
|
|
+.IR idmapd ,
|
|
and
|
|
-.IR idmapd .
|
|
+.IR rpc-gssd .
|
|
.I rpcbind
|
|
is not part of the
|
|
.I nfs-utils
|
|
@@ -155,6 +156,15 @@ is not needed and not wanted, it can be masked with
|
|
.RS
|
|
.B systemctl mask idmapd
|
|
.RE
|
|
+.I rpc-gssd
|
|
+is assumed to be needed if the
|
|
+.I krb5.keytab
|
|
+file is present. If a site needs this file present but does not want
|
|
+.I rpc-gssd
|
|
+running, it can be masked with
|
|
+.RS
|
|
+.B systemctl mask rpc-gssd
|
|
+.RE
|
|
.SH FILES
|
|
/etc/nfs.conf
|
|
.br
|
|
diff --git a/systemd/rpc-gssd.service.in b/systemd/rpc-gssd.service.in
|
|
index b353027..6807db3 100644
|
|
--- a/systemd/rpc-gssd.service.in
|
|
+++ b/systemd/rpc-gssd.service.in
|
|
@@ -2,8 +2,8 @@
|
|
Description=RPC security service for NFS client and server
|
|
DefaultDependencies=no
|
|
Conflicts=umount.target
|
|
-Requires=var-lib-nfs-rpc_pipefs.mount
|
|
-After=var-lib-nfs-rpc_pipefs.mount
|
|
+Requires=rpc_pipefs.target
|
|
+After=rpc_pipefs.target
|
|
|
|
ConditionPathExists=@_sysconfdir@/krb5.keytab
|
|
|
|
diff --git a/systemd/rpc-pipefs-generator.c b/systemd/rpc-pipefs-generator.c
|
|
new file mode 100644
|
|
index 0000000..59eee87
|
|
--- /dev/null
|
|
+++ b/systemd/rpc-pipefs-generator.c
|
|
@@ -0,0 +1,137 @@
|
|
+/*
|
|
+ * rpc-pipefs-generator:
|
|
+ * systemd generator to create ordering dependencies between
|
|
+ * nfs services and the rpc_pipefs mountpoint
|
|
+ */
|
|
+
|
|
+#ifdef HAVE_CONFIG_H
|
|
+#include <config.h>
|
|
+#endif
|
|
+
|
|
+#include <sys/stat.h>
|
|
+#include <sys/types.h>
|
|
+#include <unistd.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <ctype.h>
|
|
+#include <stdio.h>
|
|
+#include <mntent.h>
|
|
+
|
|
+#include "nfslib.h"
|
|
+#include "conffile.h"
|
|
+#include "systemd.h"
|
|
+
|
|
+#define RPC_PIPEFS_DEFAULT "/var/lib/nfs/rpc_pipefs"
|
|
+
|
|
+static int generate_mount_unit(const char *pipefs_path, const char *pipefs_unit,
|
|
+ const char *dirname)
|
|
+{
|
|
+ char *path;
|
|
+ FILE *f;
|
|
+
|
|
+ path = malloc(strlen(dirname) + 1 + strlen(pipefs_unit));
|
|
+ if (!path)
|
|
+ return 1;
|
|
+ sprintf(path, "%s/%s", dirname, pipefs_unit);
|
|
+ f = fopen(path, "w");
|
|
+ if (!f)
|
|
+ return 1;
|
|
+
|
|
+ fprintf(f, "# Automatically generated by rpc-pipefs-generator\n\n[Unit]\n");
|
|
+ fprintf(f, "Description=RPC Pipe File System\n");
|
|
+ fprintf(f, "DefaultDependencies=no\n");
|
|
+ fprintf(f, "After=systemd-tmpfiles-setup.service\n");
|
|
+ fprintf(f, "Conflicts=umount.target\n");
|
|
+ fprintf(f, "\n[Mount]\n");
|
|
+ fprintf(f, "What=sunrpc\n");
|
|
+ fprintf(f, "Where=%s\n", pipefs_path);
|
|
+ fprintf(f, "Type=rpc_pipefs\n");
|
|
+
|
|
+ fclose(f);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static
|
|
+int generate_target(char *pipefs_path, const char *dirname)
|
|
+{
|
|
+ char *path;
|
|
+ char filebase[] = "/rpc_pipefs.target";
|
|
+ char *pipefs_unit;
|
|
+ FILE *f;
|
|
+ int ret = 0;
|
|
+
|
|
+ pipefs_unit = systemd_escape(pipefs_path, ".mount");
|
|
+ if (!pipefs_unit)
|
|
+ return 1;
|
|
+
|
|
+ ret = generate_mount_unit(pipefs_path, pipefs_unit, dirname);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ path = malloc(strlen(dirname) + 1 + sizeof(filebase));
|
|
+ if (!path)
|
|
+ return 2;
|
|
+ sprintf(path, "%s", dirname);
|
|
+ mkdir(path, 0755);
|
|
+ strcat(path, filebase);
|
|
+ f = fopen(path, "w");
|
|
+ if (!f)
|
|
+ return 1;
|
|
+
|
|
+ fprintf(f, "# Automatically generated by rpc-pipefs-generator\n\n[Unit]\n");
|
|
+ fprintf(f, "Requires=%s\n", pipefs_unit);
|
|
+ fprintf(f, "After=%s\n", pipefs_unit);
|
|
+ fclose(f);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int is_non_pipefs_mountpoint(char *path)
|
|
+{
|
|
+ FILE *mtab;
|
|
+ struct mntent *mnt;
|
|
+
|
|
+ mtab = setmntent("/etc/mtab", "r");
|
|
+ if (!mtab)
|
|
+ return 0;
|
|
+
|
|
+ while ((mnt = getmntent(mtab)) != NULL) {
|
|
+ if (strlen(mnt->mnt_dir) != strlen(path))
|
|
+ continue;
|
|
+ if (strncmp(mnt->mnt_dir, path, strlen(mnt->mnt_dir)))
|
|
+ continue;
|
|
+ if (strncmp(mnt->mnt_type, "rpc_pipefs", strlen(mnt->mnt_type)))
|
|
+ break;
|
|
+ }
|
|
+ fclose(mtab);
|
|
+ return mnt != NULL;
|
|
+}
|
|
+
|
|
+int main(int argc, char *argv[])
|
|
+{
|
|
+ int ret;
|
|
+ char *s;
|
|
+
|
|
+ /* Avoid using any external services */
|
|
+ xlog_syslog(0);
|
|
+
|
|
+ if (argc != 4 || argv[1][0] != '/') {
|
|
+ fprintf(stderr, "rpc-pipefs-generator: create systemd dependencies for nfs services\n");
|
|
+ fprintf(stderr, "Usage: normal-dir early-dir late-dir\n");
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ conf_init(NFS_CONFFILE);
|
|
+ s = conf_get_str("general", "pipefs-directory");
|
|
+ if (!s)
|
|
+ exit(0);
|
|
+ if (strlen(s) == strlen(RPC_PIPEFS_DEFAULT) &&
|
|
+ strcmp(s, RPC_PIPEFS_DEFAULT) == 0)
|
|
+ exit(0);
|
|
+
|
|
+ if (is_non_pipefs_mountpoint(s))
|
|
+ exit(1);
|
|
+
|
|
+ ret = generate_target(s, argv[1]);
|
|
+ exit(ret);
|
|
+}
|
|
diff --git a/systemd/rpc-statd-notify.service b/systemd/rpc-statd-notify.service
|
|
index 7bfc9b1..687fe31 100644
|
|
--- a/systemd/rpc-statd-notify.service
|
|
+++ b/systemd/rpc-statd-notify.service
|
|
@@ -1,8 +1,8 @@
|
|
[Unit]
|
|
Description=Notify NFS peers of a restart
|
|
DefaultDependencies=no
|
|
-Requires=network.target
|
|
-After=local-fs.target network.target nss-lookup.target
|
|
+Wants=network-online.target
|
|
+After=local-fs.target network-online.target nss-lookup.target
|
|
|
|
# if we run an nfs server, it needs to be running before we
|
|
# tell clients that it has restarted.
|
|
diff --git a/systemd/rpc-statd.service b/systemd/rpc-statd.service
|
|
index 60d600f..f41ae20 100644
|
|
--- a/systemd/rpc-statd.service
|
|
+++ b/systemd/rpc-statd.service
|
|
@@ -3,7 +3,8 @@ Description=NFS status monitor for NFSv2/3 locking.
|
|
DefaultDependencies=no
|
|
Conflicts=umount.target
|
|
Requires=nss-lookup.target rpcbind.socket
|
|
-After=network.target nss-lookup.target rpcbind.socket
|
|
+Wants=network-online.target
|
|
+After=network-online.target nss-lookup.target rpcbind.socket
|
|
|
|
PartOf=nfs-utils.service
|
|
|
|
diff --git a/systemd/rpc-svcgssd.service b/systemd/rpc-svcgssd.service
|
|
index 7187e3c..cb2bcd4 100644
|
|
--- a/systemd/rpc-svcgssd.service
|
|
+++ b/systemd/rpc-svcgssd.service
|
|
@@ -1,8 +1,7 @@
|
|
[Unit]
|
|
Description=RPC security service for NFS server
|
|
DefaultDependencies=no
|
|
-Requires=var-lib-nfs-rpc_pipefs.mount
|
|
-After=var-lib-nfs-rpc_pipefs.mount local-fs.target
|
|
+After=local-fs.target
|
|
PartOf=nfs-server.service
|
|
PartOf=nfs-utils.service
|
|
|
|
diff --git a/systemd/rpc_pipefs.target b/systemd/rpc_pipefs.target
|
|
new file mode 100644
|
|
index 0000000..01d4d27
|
|
--- /dev/null
|
|
+++ b/systemd/rpc_pipefs.target
|
|
@@ -0,0 +1,3 @@
|
|
+[Unit]
|
|
+Requires=var-lib-nfs-rpc_pipefs.mount
|
|
+After=var-lib-nfs-rpc_pipefs.mount
|
|
diff --git a/systemd/systemd.c b/systemd/systemd.c
|
|
new file mode 100644
|
|
index 0000000..17820d4
|
|
--- /dev/null
|
|
+++ b/systemd/systemd.c
|
|
@@ -0,0 +1,133 @@
|
|
+/*
|
|
+ * Helper functions for systemd generators in nfs-utils.
|
|
+ *
|
|
+ * Currently just systemd_escape().
|
|
+ */
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <ctype.h>
|
|
+#include <string.h>
|
|
+
|
|
+static const char hex[16] =
|
|
+{
|
|
+ '0', '1', '2', '3', '4', '5', '6', '7',
|
|
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
|
|
+};
|
|
+
|
|
+/*
|
|
+ * determine length of the string that systemd_escape() needs to allocate
|
|
+ */
|
|
+static int systemd_len(char *path)
|
|
+{
|
|
+ char *p;
|
|
+ int len = 0;
|
|
+
|
|
+ p = path;
|
|
+ while (*p == '/')
|
|
+ /* multiple leading "/" are ignored */
|
|
+ p++;
|
|
+
|
|
+ if (!*p)
|
|
+ /* root directory "/" becomes is encoded as a single "-" */
|
|
+ return 1;
|
|
+
|
|
+ if (*p == '.')
|
|
+ /*
|
|
+ * replace "." with "\x2d" escape sequence if
|
|
+ * it's the first character in escaped path
|
|
+ * */
|
|
+ len += 4;
|
|
+
|
|
+ while (*p) {
|
|
+ unsigned char c = *p++;
|
|
+
|
|
+ if (c == '/') {
|
|
+ /* multiple non-trailing slashes become '-' */
|
|
+ while (*p == '/')
|
|
+ p++;
|
|
+ if (*p)
|
|
+ len++;
|
|
+ } else if (isalnum(c) || c == ':' || c == '.' || c == '_')
|
|
+ /* these characters are not replaced */
|
|
+ len++;
|
|
+ else
|
|
+ /* replace with "\x2d" escape sequence */
|
|
+ len += 4;
|
|
+ }
|
|
+
|
|
+ return len;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * convert c to "\x2d" escape sequence and append to string
|
|
+ * at position p, advancing p
|
|
+ */
|
|
+static char *hexify(unsigned char c, char *p)
|
|
+{
|
|
+ *p++ = '\\';
|
|
+ *p++ = 'x';
|
|
+ *p++ = hex[c >> 4];
|
|
+ *p++ = hex[c & 0xf];
|
|
+ return p;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * convert a path to a unit name according to the logic in systemd.unit(5):
|
|
+ *
|
|
+ * Basically, given a path, "/" is replaced by "-", and all other
|
|
+ * characters which are not ASCII alphanumerics are replaced by C-style
|
|
+ * "\x2d" escapes (except that "_" is never replaced and "." is only
|
|
+ * replaced when it would be the first character in the escaped path).
|
|
+ * The root directory "/" is encoded as single dash, while otherwise the
|
|
+ * initial and ending "/" are removed from all paths during
|
|
+ * transformation.
|
|
+ *
|
|
+ * NB: Although the systemd.unit(5) doesn't mention it, the ':' character
|
|
+ * is not escaped.
|
|
+ */
|
|
+char *systemd_escape(char *path, char *suffix)
|
|
+{
|
|
+ char *result;
|
|
+ char *p;
|
|
+ int len;
|
|
+
|
|
+ len = systemd_len(path);
|
|
+ result = malloc(len + strlen(suffix) + 1);
|
|
+ p = result;
|
|
+ while (*path == '/')
|
|
+ /* multiple leading "/" are ignored */
|
|
+ path++;
|
|
+ if (!*path) {
|
|
+ /* root directory "/" becomes is encoded as a single "-" */
|
|
+ *p++ = '-';
|
|
+ goto out;
|
|
+ }
|
|
+ if (*path == '.')
|
|
+ /*
|
|
+ * replace "." with "\x2d" escape sequence if
|
|
+ * it's the first character in escaped path
|
|
+ * */
|
|
+ p = hexify(*path++, p);
|
|
+
|
|
+ while (*path) {
|
|
+ unsigned char c = *path++;
|
|
+
|
|
+ if (c == '/') {
|
|
+ /* multiple non-trailing slashes become '-' */
|
|
+ while (*path == '/')
|
|
+ path++;
|
|
+ if (*path)
|
|
+ *p++ = '-';
|
|
+ } else if (isalnum(c) || c == ':' || c == '.' || c == '_')
|
|
+ /* these characters are not replaced */
|
|
+ *p++ = c;
|
|
+ else
|
|
+ /* replace with "\x2d" escape sequence */
|
|
+ p = hexify(c, p);
|
|
+ }
|
|
+
|
|
+out:
|
|
+ sprintf(p, "%s", suffix);
|
|
+ return result;
|
|
+}
|
|
diff --git a/systemd/systemd.h b/systemd/systemd.h
|
|
new file mode 100644
|
|
index 0000000..25235ec
|
|
--- /dev/null
|
|
+++ b/systemd/systemd.h
|
|
@@ -0,0 +1,6 @@
|
|
+#ifndef SYSTEMD_H
|
|
+#define SYSTEMD_H
|
|
+
|
|
+char *systemd_escape(char *path, char *suffix);
|
|
+
|
|
+#endif /* SYSTEMD_H */
|
|
diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
|
|
index 88ccdae..a68d702 100644
|
|
--- a/tools/mountstats/mountstats.py
|
|
+++ b/tools/mountstats/mountstats.py
|
|
@@ -1,4 +1,4 @@
|
|
-#!/usr/bin/env python
|
|
+#!/usr/bin/python
|
|
# -*- python-mode -*-
|
|
"""Parse /proc/self/mountstats and display it in human readable form
|
|
"""
|
|
diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c
|
|
index 18b1622..68206cc 100644
|
|
--- a/tools/rpcdebug/rpcdebug.c
|
|
+++ b/tools/rpcdebug/rpcdebug.c
|
|
@@ -74,7 +74,8 @@ main(int argc, char **argv)
|
|
opt_c = 1;
|
|
break;
|
|
case 'h':
|
|
- usage(0, module);
|
|
+ usage(0, module); /* usage does not return */
|
|
+ break;
|
|
case 'm':
|
|
module = optarg;
|
|
break;
|
|
diff --git a/utils/blkmapd/blkmapd.man b/utils/blkmapd/blkmapd.man
|
|
index 914b80f..4b3d3f0 100644
|
|
--- a/utils/blkmapd/blkmapd.man
|
|
+++ b/utils/blkmapd/blkmapd.man
|
|
@@ -43,9 +43,24 @@ Performs device discovery only then exits.
|
|
Runs
|
|
.B blkmapd
|
|
in the foreground and sends output to stderr (as opposed to syslogd)
|
|
+.SH CONFIGURATION FILE
|
|
+The
|
|
+.B blkmapd
|
|
+daemon recognizes the following value from the
|
|
+.B [general]
|
|
+section of the
|
|
+.I /etc/nfs.conf
|
|
+configuration file:
|
|
+.TP
|
|
+.B pipefs-directory
|
|
+Tells
|
|
+.B blkmapd
|
|
+where to look for the rpc_pipefs filesystem. The default value is
|
|
+.IR /var/lib/nfs/rpc_pipefs .
|
|
.SH SEE ALSO
|
|
.BR nfs (5),
|
|
-.BR dmsetup (8)
|
|
+.BR dmsetup (8),
|
|
+.BR nfs.conf (5)
|
|
.sp
|
|
RFC 5661 for the NFS version 4.1 specification.
|
|
.br
|
|
diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c
|
|
index 8eb3fd0..29bafb2 100644
|
|
--- a/utils/blkmapd/device-discovery.c
|
|
+++ b/utils/blkmapd/device-discovery.c
|
|
@@ -26,6 +26,7 @@
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
+#include <sys/sysmacros.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
@@ -50,21 +51,36 @@
|
|
#include <errno.h>
|
|
#include <libdevmapper.h>
|
|
|
|
+#ifdef HAVE_CONFIG_H
|
|
+#include "config.h"
|
|
+#endif /* HAVE_CONFIG_H */
|
|
+
|
|
#include "device-discovery.h"
|
|
#include "xcommon.h"
|
|
+#include "nfslib.h"
|
|
+#include "conffile.h"
|
|
|
|
#define EVENT_SIZE (sizeof(struct inotify_event))
|
|
#define EVENT_BUFSIZE (1024 * EVENT_SIZE)
|
|
|
|
-#define BL_PIPE_FILE "/var/lib/nfs/rpc_pipefs/nfs/blocklayout"
|
|
-#define NFSPIPE_DIR "/var/lib/nfs/rpc_pipefs/nfs"
|
|
#define RPCPIPE_DIR "/var/lib/nfs/rpc_pipefs"
|
|
#define PID_FILE "/var/run/blkmapd.pid"
|
|
|
|
+#define CONF_SAVE(w, f) do { \
|
|
+ char *p = f; \
|
|
+ if (p != NULL) \
|
|
+ (w) = p; \
|
|
+} while (0)
|
|
+
|
|
+static char bl_pipe_file[PATH_MAX];
|
|
+static char nfspipe_dir[PATH_MAX];
|
|
+static char rpcpipe_dir[PATH_MAX];
|
|
+
|
|
struct bl_disk *visible_disk_list;
|
|
int bl_watch_fd, bl_pipe_fd, nfs_pipedir_wfd, rpc_pipedir_wfd;
|
|
int pidfd = -1;
|
|
|
|
+
|
|
struct bl_disk_path *bl_get_path(const char *filepath,
|
|
struct bl_disk_path *paths)
|
|
{
|
|
@@ -358,8 +374,8 @@ static void bl_rpcpipe_cb(void)
|
|
continue;
|
|
if (event->mask & IN_CREATE) {
|
|
BL_LOG_WARNING("nfs pipe dir created\n");
|
|
- bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd);
|
|
- bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
|
|
+ bl_watch_dir(nfspipe_dir, &nfs_pipedir_wfd);
|
|
+ bl_pipe_fd = open(bl_pipe_file, O_RDWR);
|
|
} else if (event->mask & IN_DELETE) {
|
|
BL_LOG_WARNING("nfs pipe dir deleted\n");
|
|
inotify_rm_watch(bl_watch_fd, nfs_pipedir_wfd);
|
|
@@ -372,7 +388,7 @@ static void bl_rpcpipe_cb(void)
|
|
continue;
|
|
if (event->mask & IN_CREATE) {
|
|
BL_LOG_WARNING("blocklayout pipe file created\n");
|
|
- bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
|
|
+ bl_pipe_fd = open(bl_pipe_file, O_RDWR);
|
|
if (bl_pipe_fd < 0)
|
|
BL_LOG_ERR("open %s failed: %s\n",
|
|
event->name, strerror(errno));
|
|
@@ -437,6 +453,18 @@ int main(int argc, char **argv)
|
|
{
|
|
int opt, dflag = 0, fg = 0, ret = 1;
|
|
char pidbuf[64];
|
|
+ char *xrpcpipe_dir = NULL;
|
|
+
|
|
+ strncpy(rpcpipe_dir, RPCPIPE_DIR, sizeof(rpcpipe_dir));
|
|
+ conf_init(NFS_CONFFILE);
|
|
+ CONF_SAVE(xrpcpipe_dir, conf_get_str("general", "pipefs-directory"));
|
|
+ if (xrpcpipe_dir != NULL)
|
|
+ strlcpy(rpcpipe_dir, xrpcpipe_dir, sizeof(rpcpipe_dir));
|
|
+
|
|
+ strncpy(nfspipe_dir, rpcpipe_dir, sizeof(nfspipe_dir));
|
|
+ strlcat(nfspipe_dir, "/nfs", sizeof(nfspipe_dir));
|
|
+ strncpy(bl_pipe_file, rpcpipe_dir, sizeof(bl_pipe_file));
|
|
+ strlcat(bl_pipe_file, "/nfs/blocklayout", sizeof(bl_pipe_file));
|
|
|
|
while ((opt = getopt(argc, argv, "hdf")) != -1) {
|
|
switch (opt) {
|
|
@@ -496,12 +524,12 @@ int main(int argc, char **argv)
|
|
}
|
|
|
|
/* open pipe file */
|
|
- bl_watch_dir(RPCPIPE_DIR, &rpc_pipedir_wfd);
|
|
- bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd);
|
|
+ bl_watch_dir(rpcpipe_dir, &rpc_pipedir_wfd);
|
|
+ bl_watch_dir(nfspipe_dir, &nfs_pipedir_wfd);
|
|
|
|
- bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
|
|
+ bl_pipe_fd = open(bl_pipe_file, O_RDWR);
|
|
if (bl_pipe_fd < 0)
|
|
- BL_LOG_ERR("open pipe file %s failed: %s\n", BL_PIPE_FILE, strerror(errno));
|
|
+ BL_LOG_ERR("open pipe file %s failed: %s\n", bl_pipe_file, strerror(errno));
|
|
|
|
while (1) {
|
|
/* discover device when needed */
|
|
diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c
|
|
index 0062a8f..c7952c3 100644
|
|
--- a/utils/blkmapd/device-inq.c
|
|
+++ b/utils/blkmapd/device-inq.c
|
|
@@ -216,6 +216,7 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
|
|
if ((dev_id->len != 8) && (dev_id->len != 12) &&
|
|
(dev_id->len != 16))
|
|
break;
|
|
+ /* FALLTHRU */
|
|
case 3: /* NAA */
|
|
/* TODO: NAA validity judgement too complicated,
|
|
* so just ingore it here.
|
|
@@ -224,6 +225,7 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
|
|
BL_LOG_ERR("Binary code_set expected\n");
|
|
break;
|
|
}
|
|
+ /* FALLTHRU */
|
|
case 0: /* vendor specific */
|
|
case 1: /* T10 vendor identification */
|
|
current_id = dev_id->ids & 0xf;
|
|
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
|
|
index 61dddfb..beed1b3 100644
|
|
--- a/utils/exportfs/exportfs.c
|
|
+++ b/utils/exportfs/exportfs.c
|
|
@@ -50,7 +50,8 @@ static void release_lockfile(void);
|
|
|
|
static const char *lockfile = EXP_LOCKFILE;
|
|
static int _lockfd = -1;
|
|
-char *conf_path = NFS_CONFFILE;
|
|
+
|
|
+struct state_paths etab;
|
|
|
|
/*
|
|
* If we aren't careful, changes made by exportfs can be lost
|
|
@@ -95,6 +96,7 @@ main(int argc, char **argv)
|
|
int f_ignore = 0;
|
|
int i, c;
|
|
int force_flush = 0;
|
|
+ char *s;
|
|
|
|
if ((progname = strrchr(argv[0], '/')) != NULL)
|
|
progname++;
|
|
@@ -105,9 +107,14 @@ main(int argc, char **argv)
|
|
xlog_stderr(1);
|
|
xlog_syslog(0);
|
|
|
|
- conf_init();
|
|
+ conf_init(NFS_CONFFILE);
|
|
xlog_from_conffile("exportfs");
|
|
|
|
+ /* NOTE: following uses "mountd" section of nfs.conf !!!! */
|
|
+ s = conf_get_str("mountd", "state-directory-path");
|
|
+ if (s && !state_setup_basedir(argv[0], s))
|
|
+ exit(1);
|
|
+
|
|
while ((c = getopt(argc, argv, "ad:fhio:ruvs")) != EOF) {
|
|
switch(c) {
|
|
case 'a':
|
|
@@ -159,13 +166,17 @@ main(int argc, char **argv)
|
|
xlog(L_ERROR, "-r and -u are incompatible");
|
|
return 1;
|
|
}
|
|
+ if (!setup_state_path_names(progname, ETAB, ETABTMP, ETABLCK, &etab))
|
|
+ return 1;
|
|
if (optind == argc && ! f_all) {
|
|
if (force_flush) {
|
|
cache_flush(1);
|
|
+ free_state_path_names(&etab);
|
|
return 0;
|
|
} else {
|
|
xtab_export_read();
|
|
dump(f_verbose, f_export_format);
|
|
+ free_state_path_names(&etab);
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -206,6 +217,7 @@ main(int argc, char **argv)
|
|
}
|
|
xtab_export_write();
|
|
cache_flush(force_flush);
|
|
+ free_state_path_names(&etab);
|
|
|
|
return export_errno;
|
|
}
|
|
diff --git a/utils/exportfs/exportfs.man b/utils/exportfs/exportfs.man
|
|
index 45b6d83..91d3589 100644
|
|
--- a/utils/exportfs/exportfs.man
|
|
+++ b/utils/exportfs/exportfs.man
|
|
@@ -148,6 +148,29 @@ options.
|
|
.TP
|
|
.B -s
|
|
Display the current export list suitable for /etc/exports.
|
|
+
|
|
+.SH CONFIGURATION FILE
|
|
+The
|
|
+.B [exportfs]
|
|
+section of the
|
|
+.I /etc/nfs.conf
|
|
+configuration file can contain a
|
|
+.B debug
|
|
+value, which can be one or more from the list
|
|
+.BR general ,
|
|
+.BR call ,
|
|
+.BR auth ,
|
|
+.BR parse ,
|
|
+.BR all .
|
|
+When a list is given, the members should be comma-separated.
|
|
+
|
|
+.B exportfs
|
|
+will also recognize the
|
|
+.B state-directory-path
|
|
+value from the
|
|
+.B [mountd]
|
|
+section.
|
|
+
|
|
.SH DISCUSSION
|
|
.SS Exporting Directories
|
|
The first synopsis shows how to invoke
|
|
diff --git a/utils/exportfs/nfsd.man b/utils/exportfs/nfsd.man
|
|
index 0c516fa..9efa29f 100644
|
|
--- a/utils/exportfs/nfsd.man
|
|
+++ b/utils/exportfs/nfsd.man
|
|
@@ -105,11 +105,6 @@ clients have for different filesystems.
|
|
The caches are:
|
|
|
|
.TP
|
|
-.B auth.domain
|
|
-This cache maps the name of a client (or domain) to an internal data
|
|
-structure. The only access that is possible is to flush the cache.
|
|
-
|
|
-.TP
|
|
.B auth.unix.ip
|
|
This cache contains a mapping from IP address to the name of the
|
|
authentication domain that the ipaddress should be treated as part of.
|
|
@@ -133,7 +128,8 @@ are:
|
|
.B flush
|
|
When a number of seconds since epoch (1 Jan 1970) is written to this
|
|
file, all entries in the cache that were last updated before that file
|
|
-become invalidated and will be flushed out. Writing 1 will flush
|
|
+become invalidated and will be flushed out. Writing a time in the
|
|
+future (in seconds since epoch) will flush
|
|
everything. This is the only file that will always be present.
|
|
|
|
.TP
|
|
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
|
|
index 4d18d35..053a223 100644
|
|
--- a/utils/gssd/gssd.c
|
|
+++ b/utils/gssd/gssd.c
|
|
@@ -79,7 +79,6 @@ static int pipefs_fd;
|
|
static int inotify_fd;
|
|
struct event inotify_ev;
|
|
|
|
-char *conf_path = NFS_CONFFILE;
|
|
char *keytabfile = GSSD_DEFAULT_KEYTAB_FILE;
|
|
char **ccachesearch;
|
|
int use_memcache = 0;
|
|
@@ -87,6 +86,7 @@ int root_uses_machine_creds = 1;
|
|
unsigned int context_timeout = 0;
|
|
unsigned int rpc_timeout = 5;
|
|
char *preferred_realm = NULL;
|
|
+char *ccachedir = NULL;
|
|
/* Avoid DNS reverse lookups on server names */
|
|
static bool avoid_dns = true;
|
|
int thread_started = false;
|
|
@@ -837,21 +837,12 @@ usage(char *progname)
|
|
exit(1);
|
|
}
|
|
|
|
-int
|
|
-main(int argc, char *argv[])
|
|
+inline static void
|
|
+read_gss_conf(void)
|
|
{
|
|
- int fg = 0;
|
|
- int verbosity = 0;
|
|
- int rpc_verbosity = 0;
|
|
- int opt;
|
|
- int i;
|
|
- extern char *optarg;
|
|
- char *progname;
|
|
- char *ccachedir = NULL;
|
|
- struct event sighup_ev;
|
|
char *s;
|
|
|
|
- conf_init();
|
|
+ conf_init(NFS_CONFFILE);
|
|
use_memcache = conf_get_bool("gssd", "use-memcache", use_memcache);
|
|
root_uses_machine_creds = conf_get_bool("gssd", "use-machine-creds",
|
|
root_uses_machine_creds);
|
|
@@ -865,6 +856,10 @@ main(int argc, char *argv[])
|
|
s = conf_get_str("gssd", "pipefs-directory");
|
|
if (!s)
|
|
s = conf_get_str("general", "pipefs-directory");
|
|
+ else
|
|
+ printerr(0, "WARNING: Specifying pipefs-directory in the [gssd] "
|
|
+ "section of %s is deprecated. Use the [general] "
|
|
+ "section instead.", NFS_CONFFILE);
|
|
if (s)
|
|
pipefs_path = s;
|
|
s = conf_get_str("gssd", "keytab-file");
|
|
@@ -877,6 +872,22 @@ main(int argc, char *argv[])
|
|
if (s)
|
|
preferred_realm = s;
|
|
|
|
+}
|
|
+
|
|
+int
|
|
+main(int argc, char *argv[])
|
|
+{
|
|
+ int fg = 0;
|
|
+ int verbosity = 0;
|
|
+ int rpc_verbosity = 0;
|
|
+ int opt;
|
|
+ int i;
|
|
+ extern char *optarg;
|
|
+ char *progname;
|
|
+ struct event sighup_ev;
|
|
+
|
|
+ read_gss_conf();
|
|
+
|
|
while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
|
|
switch (opt) {
|
|
case 'f':
|
|
diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
|
|
index 87eef02..e620f0d 100644
|
|
--- a/utils/gssd/gssd.man
|
|
+++ b/utils/gssd/gssd.man
|
|
@@ -335,10 +335,6 @@ Equivalent to
|
|
Equivalent to
|
|
.BR -t .
|
|
.TP
|
|
-.B pipefs-directory
|
|
-Equivalent to
|
|
-.BR -p .
|
|
-.TP
|
|
.B keytab-file
|
|
Equivalent to
|
|
.BR -k .
|
|
@@ -350,6 +346,14 @@ Equivalent to
|
|
.B preferred-realm
|
|
Equivalent to
|
|
.BR -R .
|
|
+.P
|
|
+In addtion, the following value is recognized from the
|
|
+.B [general]
|
|
+section:
|
|
+.TP
|
|
+.B pipefs-directory
|
|
+Equivalent to
|
|
+.BR -p .
|
|
|
|
.SH SEE ALSO
|
|
.BR rpc.svcgssd (8),
|
|
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
|
|
index d74d372..4fc81c3 100644
|
|
--- a/utils/gssd/gssd_proc.c
|
|
+++ b/utils/gssd/gssd_proc.c
|
|
@@ -729,10 +729,18 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
|
|
char *target = NULL;
|
|
char *service = NULL;
|
|
char *enctypes = NULL;
|
|
+ char *upcall_str;
|
|
+ char *pbuf = info->lbuf;
|
|
|
|
printerr(2, "\n%s: '%s' (%s)\n", __func__, info->lbuf, clp->relpath);
|
|
|
|
- for (p = strtok(info->lbuf, " "); p; p = strtok(NULL, " ")) {
|
|
+ upcall_str = strdup(info->lbuf);
|
|
+ if (upcall_str == NULL) {
|
|
+ printerr(0, "ERROR: malloc failure\n");
|
|
+ goto out_nomem;
|
|
+ }
|
|
+
|
|
+ while ((p = strsep(&pbuf, " "))) {
|
|
if (!strncmp(p, "mech=", strlen("mech=")))
|
|
mech = p + strlen("mech=");
|
|
else if (!strncmp(p, "uid=", strlen("uid=")))
|
|
@@ -748,7 +756,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
|
|
if (!mech || strlen(mech) < 1) {
|
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
|
"failed to find gss mechanism name "
|
|
- "in upcall string '%s'\n", info->lbuf);
|
|
+ "in upcall string '%s'\n", upcall_str);
|
|
goto out;
|
|
}
|
|
|
|
@@ -761,7 +769,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
|
|
if (!uidstr) {
|
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
|
"failed to find uid "
|
|
- "in upcall string '%s'\n", info->lbuf);
|
|
+ "in upcall string '%s'\n", upcall_str);
|
|
goto out;
|
|
}
|
|
|
|
@@ -774,7 +782,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
|
|
if (target && strlen(target) < 1) {
|
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
|
"failed to parse target name "
|
|
- "in upcall string '%s'\n", info->lbuf);
|
|
+ "in upcall string '%s'\n", upcall_str);
|
|
goto out;
|
|
}
|
|
|
|
@@ -789,7 +797,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
|
|
if (service && strlen(service) < 1) {
|
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
|
"failed to parse service type "
|
|
- "in upcall string '%s'\n", info->lbuf);
|
|
+ "in upcall string '%s'\n", upcall_str);
|
|
goto out;
|
|
}
|
|
|
|
@@ -802,6 +810,8 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
|
|
do_error_downcall(clp->gssd_fd, uid, -EACCES);
|
|
}
|
|
out:
|
|
+ free(upcall_str);
|
|
+out_nomem:
|
|
free(info);
|
|
return;
|
|
}
|
|
diff --git a/utils/gssd/svcgssd.c b/utils/gssd/svcgssd.c
|
|
index 1fb579a..3514ae1 100644
|
|
--- a/utils/gssd/svcgssd.c
|
|
+++ b/utils/gssd/svcgssd.c
|
|
@@ -63,8 +63,6 @@
|
|
#include "err_util.h"
|
|
#include "conffile.h"
|
|
|
|
-char *conf_path = NFS_CONFFILE;
|
|
-
|
|
void
|
|
sig_die(int signal)
|
|
{
|
|
@@ -103,7 +101,7 @@ main(int argc, char *argv[])
|
|
char *principal = NULL;
|
|
char *s;
|
|
|
|
- conf_init();
|
|
+ conf_init(NFS_CONFFILE);
|
|
|
|
s = conf_get_str("svcgssd", "principal");
|
|
if (!s)
|
|
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
|
|
index f4e083a..c12e878 100644
|
|
--- a/utils/idmapd/idmapd.c
|
|
+++ b/utils/idmapd/idmapd.c
|
|
@@ -165,9 +165,6 @@ static char *nobodyuser, *nobodygroup;
|
|
static uid_t nobodyuid;
|
|
static gid_t nobodygid;
|
|
|
|
-/* Used by conffile.c in libnfs.a */
|
|
-char *conf_path;
|
|
-
|
|
static int
|
|
flush_nfsd_cache(char *path, time_t now)
|
|
{
|
|
@@ -219,8 +216,8 @@ main(int argc, char **argv)
|
|
int serverstart = 1, clientstart = 1;
|
|
int ret;
|
|
char *progname;
|
|
+ char *conf_path = NULL;
|
|
|
|
- conf_path = _PATH_IDMAPDCONF;
|
|
nobodyuser = NFS4NOBODY_USER;
|
|
nobodygroup = NFS4NOBODY_GROUP;
|
|
strlcpy(pipefsdir, PIPEFS_DIR, sizeof(pipefsdir));
|
|
@@ -234,8 +231,11 @@ main(int argc, char **argv)
|
|
#define GETOPTSTR "hvfd:p:U:G:c:CS"
|
|
opterr=0; /* Turn off error messages */
|
|
while ((opt = getopt(argc, argv, GETOPTSTR)) != -1) {
|
|
- if (opt == 'c')
|
|
+ if (opt == 'c') {
|
|
+ warnx("-c is deprecated and may be removed in the "
|
|
+ "future. See idmapd(8).");
|
|
conf_path = optarg;
|
|
+ }
|
|
if (opt == '?') {
|
|
if (strchr(GETOPTSTR, optopt))
|
|
warnx("'-%c' option requires an argument.", optopt);
|
|
@@ -247,17 +247,33 @@ main(int argc, char **argv)
|
|
}
|
|
optind = 1;
|
|
|
|
- if (stat(conf_path, &sb) == -1 && (errno == ENOENT || errno == EACCES)) {
|
|
- warn("Skipping configuration file \"%s\"", conf_path);
|
|
- conf_path = NULL;
|
|
+ if (conf_path) { /* deprecated -c option was specified */
|
|
+ if (stat(conf_path, &sb) == -1 && (errno == ENOENT || errno == EACCES)) {
|
|
+ warn("Skipping configuration file \"%s\"", conf_path);
|
|
+ conf_path = NULL;
|
|
+ } else {
|
|
+ conf_init(conf_path);
|
|
+ verbose = conf_get_num("General", "Verbosity", 0);
|
|
+ cache_entry_expiration = conf_get_num("General",
|
|
+ "Cache-Expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
|
|
+ CONF_SAVE(xpipefsdir, conf_get_str("General", "Pipefs-Directory"));
|
|
+ if (xpipefsdir != NULL)
|
|
+ strlcpy(pipefsdir, xpipefsdir, sizeof(pipefsdir));
|
|
+ CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
|
|
+ CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
|
|
+ }
|
|
} else {
|
|
- conf_init();
|
|
- verbose = conf_get_num("General", "Verbosity", 0);
|
|
- cache_entry_expiration = conf_get_num("General",
|
|
- "Cache-Expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
|
|
+ conf_path = NFS_CONFFILE;
|
|
+ conf_init(conf_path);
|
|
CONF_SAVE(xpipefsdir, conf_get_str("General", "Pipefs-Directory"));
|
|
if (xpipefsdir != NULL)
|
|
strlcpy(pipefsdir, xpipefsdir, sizeof(pipefsdir));
|
|
+
|
|
+ conf_path = _PATH_IDMAPDCONF;
|
|
+ conf_init(conf_path);
|
|
+ verbose = conf_get_num("General", "Verbosity", 0);
|
|
+ cache_entry_expiration = conf_get_num("General",
|
|
+ "cache-expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
|
|
CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
|
|
CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
|
|
}
|
|
diff --git a/utils/idmapd/idmapd.man b/utils/idmapd/idmapd.man
|
|
index d4ab894..5f34d2b 100644
|
|
--- a/utils/idmapd/idmapd.man
|
|
+++ b/utils/idmapd/idmapd.man
|
|
@@ -73,11 +73,28 @@ The default value is \&"/var/lib/nfs/rpc_pipefs\&".
|
|
.It Fl c Ar path
|
|
Use configuration file
|
|
.Ar path .
|
|
+This option is deprecated.
|
|
.It Fl C
|
|
Client-only: perform no idmapping for any NFS server, even if one is detected.
|
|
.It Fl S
|
|
Server-only: perform no idmapping for any NFS client, even if one is detected.
|
|
.El
|
|
+.Sh CONFIGURATION FILES
|
|
+.Nm
|
|
+recognizes the following value from the
|
|
+.Sy [general]
|
|
+section of the
|
|
+.Pa /etc/nfs.conf
|
|
+configuration file:
|
|
+.Bl -tag -width Ds_imagedir
|
|
+.It Sy pipefs-directory
|
|
+Equivalent to
|
|
+.Sy -p .
|
|
+.El
|
|
+.Pp
|
|
+All other settings related to id mapping are found in the
|
|
+.Pa /etc/idmapd.conf
|
|
+configuration file.
|
|
.Sh EXAMPLES
|
|
.Cm rpc.idmapd -f -vvv
|
|
.Pp
|
|
@@ -94,9 +111,11 @@ messages to console, and with a verbosity level of 3.
|
|
.\" This next request is for sections 1, 6, 7 & 8 only.
|
|
.\" .Sh ENVIRONMENT
|
|
.Sh FILES
|
|
-.Pa /etc/idmapd.conf
|
|
+.Pa /etc/idmapd.conf ,
|
|
+.Pa /etc/nfs.conf
|
|
.Sh SEE ALSO
|
|
.Xr idmapd.conf 5 ,
|
|
+.Xr nfs.conf 5 ,
|
|
.Xr nfsidmap 8
|
|
.\".Sh SEE ALSO
|
|
.\".Xr nylon.conf 4
|
|
diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c
|
|
index 0a4cc04..e4b39ef 100644
|
|
--- a/utils/mount/configfile.c
|
|
+++ b/utils/mount/configfile.c
|
|
@@ -51,10 +51,6 @@
|
|
#define NFSMOUNT_SERVER "Server"
|
|
#endif
|
|
|
|
-#ifndef MOUNTOPTS_CONFFILE
|
|
-#define MOUNTOPTS_CONFFILE "/etc/nfsmount.conf"
|
|
-#endif
|
|
-char *conf_path = MOUNTOPTS_CONFFILE;
|
|
enum {
|
|
MNT_NOARG=0,
|
|
MNT_INTARG,
|
|
@@ -264,7 +260,7 @@ default_value(char *mopt)
|
|
}
|
|
} else if (strncasecmp(field, "vers", strlen("vers")) == 0) {
|
|
if ((options = po_split(field)) != NULL) {
|
|
- if (!nfs_nfs_version(options, &config_default_vers)) {
|
|
+ if (!nfs_nfs_version("nfs", options, &config_default_vers)) {
|
|
xlog_warn("Unable to set default version: %s",
|
|
strerror(errno));
|
|
|
|
diff --git a/utils/mount/mount_config.h b/utils/mount/mount_config.h
|
|
index 69ffd1e..e4f8511 100644
|
|
--- a/utils/mount/mount_config.h
|
|
+++ b/utils/mount/mount_config.h
|
|
@@ -20,6 +20,10 @@
|
|
#include "conffile.h"
|
|
#include "xlog.h"
|
|
|
|
+#ifndef MOUNTOPTS_CONFFILE
|
|
+#define MOUNTOPTS_CONFFILE "/etc/nfsmount.conf"
|
|
+#endif
|
|
+
|
|
extern char *conf_get_mntopts(char *, char *, char *);
|
|
|
|
static inline void mount_config_init(char *program)
|
|
@@ -28,7 +32,7 @@ static inline void mount_config_init(char *program)
|
|
/*
|
|
* Read the the default mount options
|
|
*/
|
|
- conf_init();
|
|
+ conf_init(MOUNTOPTS_CONFFILE);
|
|
}
|
|
|
|
static inline char *mount_config_opts(char *spec,
|
|
diff --git a/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c
|
|
index 1f01f7f..2d40657 100644
|
|
--- a/utils/mount/mount_libmount.c
|
|
+++ b/utils/mount/mount_libmount.c
|
|
@@ -188,6 +188,7 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv)
|
|
};
|
|
|
|
mnt_context_init_helper(cxt, MNT_ACT_UMOUNT, 0);
|
|
+ mnt_context_disable_canonicalize(cxt, 1);
|
|
|
|
while ((c = getopt_long (argc, argv, "fvnrlh", longopts, NULL)) != -1) {
|
|
|
|
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
|
index 7dceb2d..8ab5be8 100644
|
|
--- a/utils/mount/network.c
|
|
+++ b/utils/mount/network.c
|
|
@@ -33,12 +33,19 @@
|
|
#include <errno.h>
|
|
#include <netdb.h>
|
|
#include <time.h>
|
|
+#include <grp.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/stat.h>
|
|
-#include <linux/in6.h>
|
|
+#if defined(__GLIBC__) && (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)
|
|
+/* Cannot safely include linux/in6.h in old glibc, so hardcode the needed values */
|
|
+# define IPV6_PREFER_SRC_PUBLIC 2
|
|
+# define IPV6_ADDR_PREFERENCES 72
|
|
+#else
|
|
+# include <linux/in6.h>
|
|
+#endif
|
|
#include <netinet/in.h>
|
|
#include <rpc/rpc.h>
|
|
#include <rpc/pmap_prot.h>
|
|
@@ -93,7 +100,6 @@ static const char *nfs_version_opttbl[] = {
|
|
"v4",
|
|
"vers",
|
|
"nfsvers",
|
|
- "minorversion",
|
|
NULL,
|
|
};
|
|
|
|
@@ -804,6 +810,7 @@ int start_statd(void)
|
|
pid_t pid = fork();
|
|
switch (pid) {
|
|
case 0: /* child */
|
|
+ setgroups(0, NULL);
|
|
setgid(0);
|
|
setuid(0);
|
|
execle(START_STATD, START_STATD, NULL, envp);
|
|
@@ -1233,6 +1240,7 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
|
|
*program = tmp;
|
|
return 1;
|
|
}
|
|
+ /* FALLTHRU */
|
|
case PO_BAD_VALUE:
|
|
nfs_error(_("%s: invalid value for 'nfsprog=' option"),
|
|
progname);
|
|
@@ -1252,7 +1260,7 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
|
|
* or FALSE if the option was specified with an invalid value.
|
|
*/
|
|
int
|
|
-nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
|
|
+nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *version)
|
|
{
|
|
char *version_key, *version_val, *cptr;
|
|
int i, found = 0;
|
|
@@ -1267,10 +1275,11 @@ nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
|
|
}
|
|
}
|
|
|
|
- if (!found)
|
|
+ if (!found && strcmp(type, "nfs4") == 0)
|
|
+ version_val = type + 3;
|
|
+ else if (!found)
|
|
return 1;
|
|
-
|
|
- if (i <= 2 ) {
|
|
+ else if (i <= 2 ) {
|
|
/* v2, v3, v4 */
|
|
version_val = version_key + 1;
|
|
version->v_mode = V_SPECIFIC;
|
|
@@ -1282,17 +1291,19 @@ nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
|
|
if (!version_val)
|
|
goto ret_error;
|
|
|
|
- if (!(version->major = strtol(version_val, &cptr, 10)))
|
|
+ version->major = strtol(version_val, &cptr, 10);
|
|
+ if (cptr == version_val || (*cptr && *cptr != '.'))
|
|
goto ret_error;
|
|
-
|
|
- if (strcmp(nfs_version_opttbl[i], "minorversion") == 0) {
|
|
+ if (version->major == 4 && *cptr != '.' &&
|
|
+ (version_val = po_get(options, "minorversion")) != NULL) {
|
|
+ version->minor = strtol(version_val, &cptr, 10);
|
|
+ i = -1;
|
|
+ if (*cptr)
|
|
+ goto ret_error;
|
|
version->v_mode = V_SPECIFIC;
|
|
- version->minor = version->major;
|
|
- version->major = 4;
|
|
} else if (version->major < 4)
|
|
version->v_mode = V_SPECIFIC;
|
|
-
|
|
- if (*cptr == '.') {
|
|
+ else if (*cptr == '.') {
|
|
version_val = ++cptr;
|
|
if (!(version->minor = strtol(version_val, &cptr, 10)) && cptr == version_val)
|
|
goto ret_error;
|
|
@@ -1306,7 +1317,10 @@ nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
|
|
return 1;
|
|
|
|
ret_error:
|
|
- if (i <= 2 ) {
|
|
+ if (i < 0) {
|
|
+ nfs_error(_("%s: parsing error on 'minorversion=' option"),
|
|
+ progname);
|
|
+ } else if (i <= 2 ) {
|
|
nfs_error(_("%s: parsing error on 'v' option"),
|
|
progname);
|
|
} else if (i == 3 ) {
|
|
@@ -1381,6 +1395,7 @@ nfs_nfs_port(struct mount_options *options, unsigned long *port)
|
|
*port = tmp;
|
|
return 1;
|
|
}
|
|
+ /* FALLTHRU */
|
|
case PO_BAD_VALUE:
|
|
nfs_error(_("%s: invalid value for 'port=' option"),
|
|
progname);
|
|
@@ -1476,6 +1491,7 @@ nfs_mount_program(struct mount_options *options, unsigned long *program)
|
|
*program = tmp;
|
|
return 1;
|
|
}
|
|
+ /* FALLTHRU */
|
|
case PO_BAD_VALUE:
|
|
nfs_error(_("%s: invalid value for 'mountprog=' option"),
|
|
progname);
|
|
@@ -1507,6 +1523,7 @@ nfs_mount_version(struct mount_options *options, unsigned long *version)
|
|
*version = tmp;
|
|
return 1;
|
|
}
|
|
+ /* FALLTHRU */
|
|
case PO_BAD_VALUE:
|
|
nfs_error(_("%s: invalid value for 'mountvers=' option"),
|
|
progname);
|
|
@@ -1573,6 +1590,7 @@ nfs_mount_port(struct mount_options *options, unsigned long *port)
|
|
*port = tmp;
|
|
return 1;
|
|
}
|
|
+ /* FALLTHRU */
|
|
case PO_BAD_VALUE:
|
|
nfs_error(_("%s: invalid value for 'mountport=' option"),
|
|
progname);
|
|
@@ -1638,10 +1656,11 @@ int nfs_options2pmap(struct mount_options *options,
|
|
struct pmap *nfs_pmap, struct pmap *mnt_pmap)
|
|
{
|
|
struct nfs_version version;
|
|
+ memset(&version, 0, sizeof(version));
|
|
|
|
if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
|
|
return 0;
|
|
- if (!nfs_nfs_version(options, &version))
|
|
+ if (!nfs_nfs_version("nfs", options, &version))
|
|
return 0;
|
|
if (version.v_mode == V_DEFAULT)
|
|
nfs_pmap->pm_vers = 0;
|
|
diff --git a/utils/mount/network.h b/utils/mount/network.h
|
|
index 9cc5dec..ecaac33 100644
|
|
--- a/utils/mount/network.h
|
|
+++ b/utils/mount/network.h
|
|
@@ -72,7 +72,7 @@ struct nfs_version {
|
|
|
|
int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
|
|
int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
|
|
-int nfs_nfs_version(struct mount_options *options, struct nfs_version *version);
|
|
+int nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *version);
|
|
int nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);
|
|
|
|
int nfs_options2pmap(struct mount_options *,
|
|
diff --git a/utils/mount/nfs4mount.c b/utils/mount/nfs4mount.c
|
|
index 028e7cd..89629ed 100644
|
|
--- a/utils/mount/nfs4mount.c
|
|
+++ b/utils/mount/nfs4mount.c
|
|
@@ -444,6 +444,7 @@ int nfs4mount(const char *spec, const char *node, int flags,
|
|
case RPC_SYSTEMERROR:
|
|
if (errno == ETIMEDOUT)
|
|
break;
|
|
+ /* FALLTHRU */
|
|
default:
|
|
rpc_mount_errors(hostname, 0, bg);
|
|
goto fail;
|
|
diff --git a/utils/mount/nfsmount.c b/utils/mount/nfsmount.c
|
|
index 930622d..ae4a3da 100644
|
|
--- a/utils/mount/nfsmount.c
|
|
+++ b/utils/mount/nfsmount.c
|
|
@@ -683,6 +683,7 @@ nfsmount(const char *spec, const char *node, int flags,
|
|
case RPC_SYSTEMERROR:
|
|
if (errno == ETIMEDOUT)
|
|
break;
|
|
+ /* FALLTHRU */
|
|
default:
|
|
rpc_mount_errors(*nfs_server.hostname, 0, bg);
|
|
goto fail;
|
|
diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c
|
|
index de284f2..e16fb6a 100644
|
|
--- a/utils/mount/nfsumount.c
|
|
+++ b/utils/mount/nfsumount.c
|
|
@@ -180,7 +180,7 @@ static int nfs_umount_is_vers4(const struct mntentchn *mc)
|
|
options = po_split(pmc->m.mnt_opts);
|
|
if (options != NULL) {
|
|
struct nfs_version version;
|
|
- int rc = nfs_nfs_version(options, &version);
|
|
+ int rc = nfs_nfs_version("nfs", options, &version);
|
|
po_destroy(options);
|
|
if (rc && version.major == 4)
|
|
goto out_nfs4;
|
|
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
|
|
index 387d734..1d30d34 100644
|
|
--- a/utils/mount/stropts.c
|
|
+++ b/utils/mount/stropts.c
|
|
@@ -73,6 +73,13 @@
|
|
#define NFS_DEF_BG_TIMEOUT_MINUTES (10000u)
|
|
#endif
|
|
|
|
+#ifndef NFS_DEFAULT_MAJOR
|
|
+#define NFS_DEFAULT_MAJOR 4
|
|
+#endif
|
|
+#ifndef NFS_DEFAULT_MINOR
|
|
+#define NFS_DEFAULT_MINOR 2
|
|
+#endif
|
|
+
|
|
extern int nfs_mount_data_version;
|
|
extern char *progname;
|
|
extern int verbose;
|
|
@@ -80,8 +87,8 @@ extern int sloppy;
|
|
|
|
struct nfsmount_info {
|
|
const char *spec, /* server:/path */
|
|
- *node, /* mounted-on dir */
|
|
- *type; /* "nfs" or "nfs4" */
|
|
+ *node; /* mounted-on dir */
|
|
+ char *type; /* "nfs" or "nfs4" */
|
|
char *hostname; /* server's hostname */
|
|
struct addrinfo *address; /* server's addresses */
|
|
sa_family_t family; /* Address family */
|
|
@@ -112,20 +119,28 @@ static void nfs_default_version(struct nfsmount_info *mi)
|
|
if (mi->version.v_mode == V_DEFAULT &&
|
|
config_default_vers.v_mode != V_DEFAULT) {
|
|
mi->version.major = config_default_vers.major;
|
|
- mi->version.minor = config_default_vers.minor;
|
|
+ if (config_default_vers.v_mode == V_SPECIFIC)
|
|
+ mi->version.minor = config_default_vers.minor;
|
|
+ else
|
|
+ mi->version.minor = NFS_DEFAULT_MINOR;
|
|
return;
|
|
}
|
|
|
|
if (mi->version.v_mode == V_GENERAL) {
|
|
if (config_default_vers.v_mode != V_DEFAULT &&
|
|
- mi->version.major == config_default_vers.major)
|
|
- mi->version.minor = config_default_vers.minor;
|
|
+ mi->version.major == config_default_vers.major) {
|
|
+ if (config_default_vers.v_mode == V_SPECIFIC)
|
|
+ mi->version.minor = config_default_vers.minor;
|
|
+ else
|
|
+ mi->version.minor = NFS_DEFAULT_MINOR;
|
|
+ } else
|
|
+ mi->version.minor = NFS_DEFAULT_MINOR;
|
|
return;
|
|
}
|
|
|
|
#endif /* MOUNT_CONFIG */
|
|
- mi->version.major = 4;
|
|
- mi->version.minor = 2;
|
|
+ mi->version.major = NFS_DEFAULT_MAJOR;
|
|
+ mi->version.minor = NFS_DEFAULT_MINOR;
|
|
}
|
|
|
|
/*
|
|
@@ -312,12 +327,9 @@ static int nfs_append_sloppy_option(struct mount_options *options)
|
|
|
|
static int nfs_set_version(struct nfsmount_info *mi)
|
|
{
|
|
- if (!nfs_nfs_version(mi->options, &mi->version))
|
|
+ if (!nfs_nfs_version(mi->type, mi->options, &mi->version))
|
|
return 0;
|
|
|
|
- if (strncmp(mi->type, "nfs4", 4) == 0)
|
|
- mi->version.major = 4;
|
|
-
|
|
/*
|
|
* Before 2.6.32, the kernel NFS client didn't
|
|
* support "-t nfs vers=4" mounts, so NFS version
|
|
@@ -517,6 +529,10 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options, int checkv4)
|
|
unsigned long protocol;
|
|
struct pmap mnt_pmap;
|
|
|
|
+ /* initialize structs */
|
|
+ memset(&nfs_pmap, 0, sizeof(struct pmap));
|
|
+ memset(&mnt_pmap, 0, sizeof(struct pmap));
|
|
+
|
|
/*
|
|
* Version and transport negotiation is not required
|
|
* and does not work for RDMA mounts.
|
|
@@ -705,7 +721,7 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
|
|
{
|
|
struct mount_options *options = po_dup(mi->options);
|
|
int result = 0;
|
|
- char version_opt[16];
|
|
+ char version_opt[32];
|
|
char *extra_opts = NULL;
|
|
|
|
if (!options) {
|
|
@@ -727,13 +743,25 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
|
|
}
|
|
|
|
if (mi->version.v_mode != V_SPECIFIC) {
|
|
- if (mi->version.v_mode == V_GENERAL)
|
|
- snprintf(version_opt, sizeof(version_opt) - 1,
|
|
- "vers=%lu", mi->version.major);
|
|
- else
|
|
- snprintf(version_opt, sizeof(version_opt) - 1,
|
|
- "vers=%lu.%lu", mi->version.major,
|
|
- mi->version.minor);
|
|
+ char *fmt;
|
|
+ switch (mi->version.minor) {
|
|
+ /* Old kernels don't support the new "vers=x.y"
|
|
+ * option, but do support old versions of NFS4.
|
|
+ * So use the format that is most widely understood.
|
|
+ */
|
|
+ case 0:
|
|
+ fmt = "vers=%lu";
|
|
+ break;
|
|
+ case 1:
|
|
+ fmt = "vers=%lu,minorversion=%lu";
|
|
+ break;
|
|
+ default:
|
|
+ fmt = "vers=%lu.%lu";
|
|
+ break;
|
|
+ }
|
|
+ snprintf(version_opt, sizeof(version_opt) - 1,
|
|
+ fmt, mi->version.major,
|
|
+ mi->version.minor);
|
|
|
|
if (po_append(options, version_opt) == PO_FAILED) {
|
|
errno = EINVAL;
|
|
@@ -834,9 +862,6 @@ check_result:
|
|
case EINVAL:
|
|
/* A less clear indication that our client
|
|
* does not support NFSv4 minor version. */
|
|
- if (mi->version.v_mode == V_GENERAL &&
|
|
- mi->version.minor == 0)
|
|
- return result;
|
|
if (mi->version.v_mode != V_SPECIFIC) {
|
|
if (mi->version.minor > 0) {
|
|
mi->version.minor--;
|
|
@@ -858,19 +883,28 @@ check_result:
|
|
/* UDP-Only servers won't support v4, but maybe it
|
|
* just isn't ready yet. So try v3, but double-check
|
|
* with rpcbind for v4. */
|
|
+ if (mi->version.v_mode == V_GENERAL)
|
|
+ /* Mustn't try v2,v3 */
|
|
+ return result;
|
|
result = nfs_try_mount_v3v2(mi, TRUE);
|
|
if (result == 0 && errno == EAGAIN) {
|
|
/* v4 server seems to be registered now. */
|
|
result = nfs_try_mount_v4(mi);
|
|
if (result == 0 && errno != ECONNREFUSED)
|
|
goto check_result;
|
|
- }
|
|
+ } else if (result == 0)
|
|
+ /* Restore original errno with v3 failures */
|
|
+ errno = ECONNREFUSED;
|
|
+
|
|
return result;
|
|
default:
|
|
return result;
|
|
}
|
|
|
|
fall_back:
|
|
+ if (mi->version.v_mode == V_GENERAL)
|
|
+ /* v2,3 fallback not allowed */
|
|
+ return result;
|
|
return nfs_try_mount_v3v2(mi, FALSE);
|
|
}
|
|
|
|
@@ -1165,7 +1199,7 @@ static int nfsmount_start(struct nfsmount_info *mi)
|
|
*
|
|
* Returns a valid mount command exit code.
|
|
*/
|
|
-int nfsmount_string(const char *spec, const char *node, const char *type,
|
|
+int nfsmount_string(const char *spec, const char *node, char *type,
|
|
int flags, char **extra_opts, int fake, int child)
|
|
{
|
|
struct nfsmount_info mi = {
|
|
diff --git a/utils/mount/stropts.h b/utils/mount/stropts.h
|
|
index 37316eb..6acd2ac 100644
|
|
--- a/utils/mount/stropts.h
|
|
+++ b/utils/mount/stropts.h
|
|
@@ -24,7 +24,7 @@
|
|
#ifndef _NFS_UTILS_MOUNT_STROPTS_H
|
|
#define _NFS_UTILS_MOUNT_STROPTS_H
|
|
|
|
-int nfsmount_string(const char *, const char *, const char *, int,
|
|
+int nfsmount_string(const char *, const char *, char *, int,
|
|
char **, int, int);
|
|
|
|
#endif /* _NFS_UTILS_MOUNT_STROPTS_H */
|
|
diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c
|
|
index d065830..8299256 100644
|
|
--- a/utils/mountd/auth.c
|
|
+++ b/utils/mountd/auth.c
|
|
@@ -41,6 +41,8 @@ static nfs_client my_client;
|
|
|
|
extern int use_ipaddr;
|
|
|
|
+extern struct state_paths etab;
|
|
+
|
|
void
|
|
auth_init(void)
|
|
{
|
|
@@ -84,10 +86,10 @@ auth_reload()
|
|
static unsigned int counter;
|
|
int fd;
|
|
|
|
- if ((fd = open(_PATH_ETAB, O_RDONLY)) < 0) {
|
|
- xlog(L_FATAL, "couldn't open %s", _PATH_ETAB);
|
|
+ if ((fd = open(etab.statefn, O_RDONLY)) < 0) {
|
|
+ xlog(L_FATAL, "couldn't open %s", etab.statefn);
|
|
} else if (fstat(fd, &stb) < 0) {
|
|
- xlog(L_FATAL, "couldn't stat %s", _PATH_ETAB);
|
|
+ xlog(L_FATAL, "couldn't stat %s", etab.statefn);
|
|
close(fd);
|
|
} else if (last_fd != -1 && stb.st_ino == last_inode) {
|
|
/* We opened the etab file before, and its inode
|
|
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
|
|
index ca6c84f..e49300d 100644
|
|
--- a/utils/mountd/cache.c
|
|
+++ b/utils/mountd/cache.c
|
|
@@ -11,6 +11,7 @@
|
|
#include <config.h>
|
|
#endif
|
|
|
|
+#include <sys/sysmacros.h>
|
|
#include <sys/types.h>
|
|
#include <sys/select.h>
|
|
#include <sys/stat.h>
|
|
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
|
|
index 61699e6..829f803 100644
|
|
--- a/utils/mountd/mountd.c
|
|
+++ b/utils/mountd/mountd.c
|
|
@@ -29,6 +29,7 @@
|
|
#include "mountd.h"
|
|
#include "rpcmisc.h"
|
|
#include "pseudoflavors.h"
|
|
+#include "nfslib.h"
|
|
|
|
extern void my_svc_run(void);
|
|
|
|
@@ -40,7 +41,8 @@ int reverse_resolve = 0;
|
|
int manage_gids;
|
|
int use_ipaddr = -1;
|
|
|
|
-char *conf_path = NFS_CONFFILE;
|
|
+struct state_paths etab;
|
|
+struct state_paths rmtab;
|
|
|
|
/* PRC: a high-availability callout program can be specified with -H
|
|
* When this is done, the program will receive callouts whenever clients
|
|
@@ -110,8 +112,8 @@ unregister_services (void)
|
|
static void
|
|
cleanup_lockfiles (void)
|
|
{
|
|
- unlink(_PATH_ETABLCK);
|
|
- unlink(_PATH_RMTABLCK);
|
|
+ unlink(etab.lockfn);
|
|
+ unlink(rmtab.lockfn);
|
|
}
|
|
|
|
/* Wait for all worker child processes to exit and reap them */
|
|
@@ -181,6 +183,8 @@ fork_workers(void)
|
|
wait_for_workers();
|
|
unregister_services();
|
|
cleanup_lockfiles();
|
|
+ free_state_path_names(&etab);
|
|
+ free_state_path_names(&rmtab);
|
|
xlog(L_NOTICE, "mountd: no more workers, exiting\n");
|
|
exit(0);
|
|
}
|
|
@@ -198,6 +202,8 @@ killer (int sig)
|
|
wait_for_workers();
|
|
}
|
|
cleanup_lockfiles();
|
|
+ free_state_path_names(&etab);
|
|
+ free_state_path_names(&rmtab);
|
|
xlog (L_NOTICE, "Caught signal %d, un-registering and exiting.", sig);
|
|
exit(0);
|
|
}
|
|
@@ -656,7 +662,6 @@ get_exportlist(void)
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
- char *state_dir = NFS_STATEDIR;
|
|
char *progname;
|
|
char *s;
|
|
unsigned int listeners = 0;
|
|
@@ -674,7 +679,7 @@ main(int argc, char **argv)
|
|
else
|
|
progname = argv[0];
|
|
|
|
- conf_init();
|
|
+ conf_init(NFS_CONFFILE);
|
|
xlog_from_conffile("mountd");
|
|
manage_gids = conf_get_bool("mountd", "manage-gids", manage_gids);
|
|
descriptors = conf_get_num("mountd", "descriptors", descriptors);
|
|
@@ -684,8 +689,8 @@ main(int argc, char **argv)
|
|
ha_callout_prog = conf_get_str("mountd", "ha-callout");
|
|
|
|
s = conf_get_str("mountd", "state-directory-path");
|
|
- if (s)
|
|
- state_dir = s;
|
|
+ if (s && !state_setup_basedir(argv[0], s))
|
|
+ exit(1);
|
|
|
|
/* NOTE: following uses "nfsd" section of nfs.conf !!!! */
|
|
if (conf_get_bool("nfsd", "udp", NFSCTL_UDPISSET(_rpcprotobits)))
|
|
@@ -758,7 +763,8 @@ main(int argc, char **argv)
|
|
reverse_resolve = 1;
|
|
break;
|
|
case 's':
|
|
- state_dir = xstrdup(optarg);
|
|
+ if (!state_setup_basedir(argv[0], optarg))
|
|
+ exit(1);
|
|
break;
|
|
case 't':
|
|
num_threads = atoi (optarg);
|
|
@@ -790,11 +796,10 @@ main(int argc, char **argv)
|
|
fprintf(stderr, "%s: No protocol versions specified!\n", progname);
|
|
usage(progname, 1);
|
|
}
|
|
- if (chdir(state_dir)) {
|
|
- fprintf(stderr, "%s: chdir(%s) failed: %s\n",
|
|
- progname, state_dir, strerror(errno));
|
|
- exit(1);
|
|
- }
|
|
+ if (!setup_state_path_names(progname, ETAB, ETABTMP, ETABLCK, &etab))
|
|
+ return 1;
|
|
+ if (!setup_state_path_names(progname, RMTAB, RMTABTMP, RMTABLCK, &rmtab))
|
|
+ return 1;
|
|
|
|
if (getrlimit (RLIMIT_NOFILE, &rlim) != 0)
|
|
fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n",
|
|
@@ -888,6 +893,8 @@ main(int argc, char **argv)
|
|
|
|
xlog(L_ERROR, "RPC service loop terminated unexpectedly. Exiting...\n");
|
|
unregister_services();
|
|
+ free_state_path_names(&etab);
|
|
+ free_state_path_names(&rmtab);
|
|
exit(1);
|
|
}
|
|
|
|
diff --git a/utils/mountd/mountd.man b/utils/mountd/mountd.man
|
|
index 9f0a51f..9978afc 100644
|
|
--- a/utils/mountd/mountd.man
|
|
+++ b/utils/mountd/mountd.man
|
|
@@ -144,7 +144,7 @@ Instead, mount the nfsd filesystem on
|
|
.IR /proc/fs/nfsd .
|
|
.TP
|
|
.BI "\-s," "" " \-\-state\-directory\-path " directory
|
|
-Specify a directory in which to place statd state information.
|
|
+Specify a directory in which to place state information (etab and rmtab).
|
|
If this option is not specified the default of
|
|
.I /var/lib/nfs
|
|
is used.
|
|
diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c
|
|
index 527377f..3ae0dbb 100644
|
|
--- a/utils/mountd/rmtab.c
|
|
+++ b/utils/mountd/rmtab.c
|
|
@@ -28,6 +28,8 @@
|
|
|
|
extern int reverse_resolve;
|
|
|
|
+extern struct state_paths rmtab;
|
|
+
|
|
/* If new path is a link do not destroy it but place the
|
|
* file where the link points.
|
|
*/
|
|
@@ -59,7 +61,7 @@ mountlist_add(char *host, const char *path)
|
|
int lockid;
|
|
long pos;
|
|
|
|
- if ((lockid = xflock(_PATH_RMTABLCK, "a")) < 0)
|
|
+ if ((lockid = xflock(rmtab.lockfn, "a")) < 0)
|
|
return;
|
|
setrmtabent("r+");
|
|
while ((rep = getrmtabent(1, &pos)) != NULL) {
|
|
@@ -99,13 +101,13 @@ mountlist_del(char *hname, const char *path)
|
|
int lockid;
|
|
int match;
|
|
|
|
- if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0)
|
|
+ if ((lockid = xflock(rmtab.lockfn, "w")) < 0)
|
|
return;
|
|
if (!setrmtabent("r")) {
|
|
xfunlock(lockid);
|
|
return;
|
|
}
|
|
- if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) {
|
|
+ if (!(fp = fsetrmtabent(rmtab.tmpfn, "w"))) {
|
|
endrmtabent();
|
|
xfunlock(lockid);
|
|
return;
|
|
@@ -121,9 +123,9 @@ mountlist_del(char *hname, const char *path)
|
|
if (!match || rep->r_count)
|
|
fputrmtabent(fp, rep, NULL);
|
|
}
|
|
- if (slink_safe_rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
|
|
+ if (slink_safe_rename(rmtab.tmpfn, rmtab.statefn) < 0) {
|
|
xlog(L_ERROR, "couldn't rename %s to %s",
|
|
- _PATH_RMTABTMP, _PATH_RMTAB);
|
|
+ rmtab.tmpfn, rmtab.statefn);
|
|
}
|
|
endrmtabent(); /* close & unlink */
|
|
fendrmtabent(fp);
|
|
@@ -138,7 +140,7 @@ mountlist_del_all(const struct sockaddr *sap)
|
|
FILE *fp;
|
|
int lockid;
|
|
|
|
- if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0)
|
|
+ if ((lockid = xflock(rmtab.lockfn, "w")) < 0)
|
|
return;
|
|
hostname = host_canonname(sap);
|
|
if (hostname == NULL) {
|
|
@@ -151,7 +153,7 @@ mountlist_del_all(const struct sockaddr *sap)
|
|
if (!setrmtabent("r"))
|
|
goto out_free;
|
|
|
|
- if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w")))
|
|
+ if (!(fp = fsetrmtabent(rmtab.tmpfn, "w")))
|
|
goto out_close;
|
|
|
|
while ((rep = getrmtabent(1, NULL)) != NULL) {
|
|
@@ -160,9 +162,9 @@ mountlist_del_all(const struct sockaddr *sap)
|
|
continue;
|
|
fputrmtabent(fp, rep, NULL);
|
|
}
|
|
- if (slink_safe_rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
|
|
+ if (slink_safe_rename(rmtab.tmpfn, rmtab.statefn) < 0) {
|
|
xlog(L_ERROR, "couldn't rename %s to %s",
|
|
- _PATH_RMTABTMP, _PATH_RMTAB);
|
|
+ rmtab.tmpfn, rmtab.statefn);
|
|
}
|
|
fendrmtabent(fp);
|
|
out_close:
|
|
@@ -195,11 +197,11 @@ mountlist_list(void)
|
|
struct stat stb;
|
|
int lockid;
|
|
|
|
- if ((lockid = xflock(_PATH_RMTABLCK, "r")) < 0)
|
|
+ if ((lockid = xflock(rmtab.lockfn, "r")) < 0)
|
|
return NULL;
|
|
- if (stat(_PATH_RMTAB, &stb) < 0) {
|
|
+ if (stat(rmtab.statefn, &stb) < 0) {
|
|
xlog(L_ERROR, "can't stat %s: %s",
|
|
- _PATH_RMTAB, strerror(errno));
|
|
+ rmtab.statefn, strerror(errno));
|
|
xfunlock(lockid);
|
|
return NULL;
|
|
}
|
|
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
|
|
index 20f4b79..f973203 100644
|
|
--- a/utils/nfsd/nfsd.c
|
|
+++ b/utils/nfsd/nfsd.c
|
|
@@ -34,8 +34,6 @@
|
|
#define NFSD_NPROC 8
|
|
#endif
|
|
|
|
-char *conf_path = NFS_CONFFILE;
|
|
-
|
|
static void usage(const char *);
|
|
|
|
static struct option longopts[] =
|
|
@@ -44,7 +42,9 @@ static struct option longopts[] =
|
|
{ "help", 0, 0, 'h' },
|
|
{ "no-nfs-version", 1, 0, 'N' },
|
|
{ "nfs-version", 1, 0, 'V' },
|
|
+ { "tcp", 0, 0, 't' },
|
|
{ "no-tcp", 0, 0, 'T' },
|
|
+ { "udp", 0, 0, 'u' },
|
|
{ "no-udp", 0, 0, 'U' },
|
|
{ "port", 1, 0, 'P' },
|
|
{ "port", 1, 0, 'p' },
|
|
@@ -67,8 +67,9 @@ main(int argc, char **argv)
|
|
int socket_up = 0;
|
|
unsigned int minorvers = 0;
|
|
unsigned int minorversset = 0;
|
|
+ unsigned int minormask = 0;
|
|
unsigned int versbits = NFSCTL_VERDEFAULT;
|
|
- unsigned int protobits = NFSCTL_ALLBITS;
|
|
+ unsigned int protobits = NFSCTL_PROTODEFAULT;
|
|
int grace = -1;
|
|
int lease = -1;
|
|
|
|
@@ -79,7 +80,7 @@ main(int argc, char **argv)
|
|
xlog_syslog(0);
|
|
xlog_stderr(1);
|
|
|
|
- conf_init();
|
|
+ conf_init(NFS_CONFFILE);
|
|
xlog_from_conffile("nfsd");
|
|
count = conf_get_num("nfsd", "threads", count);
|
|
grace = conf_get_num("nfsd", "grace-time", grace);
|
|
@@ -104,10 +105,16 @@ main(int argc, char **argv)
|
|
else
|
|
NFSCTL_VERUNSET(versbits, i);
|
|
}
|
|
+
|
|
+ nfssvc_get_minormask(&minormask);
|
|
/* We assume the kernel will default all minor versions to 'on',
|
|
* and allow the config file to disable some.
|
|
*/
|
|
- for (i = NFS4_MINMINOR; i <= NFS4_MAXMINOR; i++) {
|
|
+ if (NFSCTL_VERISSET(versbits, 4)) {
|
|
+ NFSCTL_MINORSET(minorversset, 0);
|
|
+ NFSCTL_MINORSET(minorvers, 0);
|
|
+ }
|
|
+ for (i = 1; i <= NFS4_MAXMINOR; i++) {
|
|
char tag[20];
|
|
sprintf(tag, "vers4.%d", i);
|
|
/* The default for minor version support is to let the
|
|
@@ -119,12 +126,12 @@ main(int argc, char **argv)
|
|
* (i.e. don't set the bit in minorversset).
|
|
*/
|
|
if (!conf_get_bool("nfsd", tag, 1)) {
|
|
- NFSCTL_VERSET(minorversset, i);
|
|
- NFSCTL_VERUNSET(minorvers, i);
|
|
+ NFSCTL_MINORSET(minorversset, i);
|
|
+ NFSCTL_MINORUNSET(minorvers, i);
|
|
}
|
|
if (conf_get_bool("nfsd", tag, 0)) {
|
|
- NFSCTL_VERSET(minorversset, i);
|
|
- NFSCTL_VERSET(minorvers, i);
|
|
+ NFSCTL_MINORSET(minorversset, i);
|
|
+ NFSCTL_MINORSET(minorvers, i);
|
|
}
|
|
}
|
|
|
|
@@ -138,7 +145,7 @@ main(int argc, char **argv)
|
|
}
|
|
}
|
|
|
|
- while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:sTUrG:L:", longopts, NULL)) != EOF) {
|
|
+ while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:stTituUrG:L:", longopts, NULL)) != EOF) {
|
|
switch(c) {
|
|
case 'd':
|
|
xlog_config(D_ALL, 1);
|
|
@@ -179,14 +186,19 @@ main(int argc, char **argv)
|
|
case 4:
|
|
if (*p == '.') {
|
|
int i = atoi(p+1);
|
|
- if (i < NFS4_MINMINOR || i > NFS4_MAXMINOR) {
|
|
+ if (i < 0 || i > NFS4_MAXMINOR) {
|
|
fprintf(stderr, "%s: unsupported minor version\n", optarg);
|
|
exit(1);
|
|
}
|
|
- NFSCTL_VERSET(minorversset, i);
|
|
- NFSCTL_VERUNSET(minorvers, i);
|
|
- break;
|
|
+ NFSCTL_MINORSET(minorversset, i);
|
|
+ NFSCTL_MINORUNSET(minorvers, i);
|
|
+ if (minorvers != 0)
|
|
+ break;
|
|
+ } else {
|
|
+ minorvers = 0;
|
|
+ minorversset = minormask;
|
|
}
|
|
+ /* FALLTHRU */
|
|
case 3:
|
|
case 2:
|
|
NFSCTL_VERUNSET(versbits, c);
|
|
@@ -201,14 +213,15 @@ main(int argc, char **argv)
|
|
case 4:
|
|
if (*p == '.') {
|
|
int i = atoi(p+1);
|
|
- if (i < NFS4_MINMINOR || i > NFS4_MAXMINOR) {
|
|
+ if (i < 0 || i > NFS4_MAXMINOR) {
|
|
fprintf(stderr, "%s: unsupported minor version\n", optarg);
|
|
exit(1);
|
|
}
|
|
- NFSCTL_VERSET(minorversset, i);
|
|
- NFSCTL_VERSET(minorvers, i);
|
|
- break;
|
|
- }
|
|
+ NFSCTL_MINORSET(minorversset, i);
|
|
+ NFSCTL_MINORSET(minorvers, i);
|
|
+ } else
|
|
+ minorvers = minorversset = minormask;
|
|
+ /* FALLTHRU */
|
|
case 3:
|
|
case 2:
|
|
NFSCTL_VERSET(versbits, c);
|
|
@@ -222,9 +235,15 @@ main(int argc, char **argv)
|
|
xlog_syslog(1);
|
|
xlog_stderr(0);
|
|
break;
|
|
+ case 't':
|
|
+ NFSCTL_TCPSET(protobits);
|
|
+ break;
|
|
case 'T':
|
|
NFSCTL_TCPUNSET(protobits);
|
|
break;
|
|
+ case 'u':
|
|
+ NFSCTL_UDPSET(protobits);
|
|
+ break;
|
|
case 'U':
|
|
NFSCTL_UDPUNSET(protobits);
|
|
break;
|
|
@@ -244,6 +263,7 @@ main(int argc, char **argv)
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Invalid argument: '%c'\n", c);
|
|
+ /* FALLTHRU */
|
|
case 'h':
|
|
usage(progname);
|
|
}
|
|
@@ -372,9 +392,9 @@ usage(const char *prog)
|
|
{
|
|
fprintf(stderr, "Usage:\n"
|
|
"%s [-d|--debug] [-H hostname] [-p|-P|--port port]\n"
|
|
- " [-N|--no-nfs-version version] [-V|--nfs-version version]\n"
|
|
- " [-s|--syslog] [-T|--no-tcp] [-U|--no-udp] [-r|--rdma=]\n"
|
|
- " [-G|--grace-time secs] [-L|--leasetime secs] nrservs\n",
|
|
+ " [-N|--no-nfs-version version] [-V|--nfs-version version]\n"
|
|
+ " [-s|--syslog] [-t|--tcp] [-T|--no-tcp] [-u|--udp] [-U|--no-udp]\n"
|
|
+ " [-r|--rdma=] [-G|--grace-time secs] [-L|--leasetime secs] nrservs\n",
|
|
prog);
|
|
exit(2);
|
|
}
|
|
diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man
|
|
index 8901fb6..d83ef86 100644
|
|
--- a/utils/nfsd/nfsd.man
|
|
+++ b/utils/nfsd/nfsd.man
|
|
@@ -57,7 +57,7 @@ This option can be used to request that
|
|
.B rpc.nfsd
|
|
does not offer certain versions of NFS. The current version of
|
|
.B rpc.nfsd
|
|
-can support major NFS versions 2,3,4 and the minor versions 4.1 and 4.2.
|
|
+can support major NFS versions 2,3,4 and the minor versions 4.0, 4.1 and 4.2.
|
|
.TP
|
|
.B \-s " or " \-\-syslog
|
|
By default,
|
|
@@ -67,22 +67,24 @@ logs error messages (and debug messages, if enabled) to stderr. This option make
|
|
log these messages to syslog instead. Note that errors encountered during
|
|
option processing will still be logged to stderr regardless of this option.
|
|
.TP
|
|
+.B \-t " or " \-\-tcp
|
|
+Instruct the kernel nfs server to open and listen on a TCP socket. This is the default.
|
|
+.TP
|
|
.B \-T " or " \-\-no-tcp
|
|
-Disable
|
|
-.B rpc.nfsd
|
|
-from accepting TCP connections from clients.
|
|
+Instruct the kernel nfs server not to open and listen on a TCP socket.
|
|
+.TP
|
|
+.B \-u " or " \-\-udp
|
|
+Instruct the kernel nfs server to open and listen on a UDP socket.
|
|
.TP
|
|
.B \-U " or " \-\-no-udp
|
|
-Disable
|
|
-.B rpc.nfsd
|
|
-from accepting UDP connections from clients.
|
|
+Instruct the kernel nfs server not to open and listen on a UDP socket. This is the default.
|
|
.TP
|
|
.B \-V " or " \-\-nfs-version vers
|
|
This option can be used to request that
|
|
.B rpc.nfsd
|
|
offer certain versions of NFS. The current version of
|
|
.B rpc.nfsd
|
|
-can support major NFS versions 2,3,4 and the minor versions 4.1 and 4.2.
|
|
+can support major NFS versions 2,3,4 and the minor versions 4.0, 4.1 and 4.2.
|
|
.TP
|
|
.B \-L " or " \-\-lease-time seconds
|
|
Set the lease-time used for NFSv4. This corresponds to how often
|
|
diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c
|
|
index 07f6ff1..e8609c1 100644
|
|
--- a/utils/nfsd/nfssvc.c
|
|
+++ b/utils/nfsd/nfssvc.c
|
|
@@ -330,36 +330,78 @@ nfssvc_set_time(const char *type, const int seconds)
|
|
}
|
|
|
|
void
|
|
+nfssvc_get_minormask(unsigned int *mask)
|
|
+{
|
|
+ int fd;
|
|
+ char *ptr = buf;
|
|
+ ssize_t size;
|
|
+
|
|
+ fd = open(NFSD_VERS_FILE, O_RDONLY);
|
|
+ if (fd < 0)
|
|
+ return;
|
|
+
|
|
+ size = read(fd, buf, sizeof(buf));
|
|
+ if (size < 0) {
|
|
+ xlog(L_ERROR, "Getting versions failed: errno %d (%m)", errno);
|
|
+ goto out;
|
|
+ }
|
|
+ ptr[size] = '\0';
|
|
+ for (;;) {
|
|
+ unsigned vers, minor = 0;
|
|
+ char *token = strtok(ptr, " ");
|
|
+
|
|
+ if (!token)
|
|
+ break;
|
|
+ ptr = NULL;
|
|
+ if (*token != '+' && *token != '-')
|
|
+ continue;
|
|
+ if (sscanf(++token, "%u.%u", &vers, &minor) > 0 &&
|
|
+ vers == 4 && minor <= NFS4_MAXMINOR)
|
|
+ NFSCTL_MINORSET(*mask, minor);
|
|
+ }
|
|
+out:
|
|
+ close(fd);
|
|
+ return;
|
|
+}
|
|
+
|
|
+static int
|
|
+nfssvc_print_vers(char *ptr, unsigned size, unsigned vers, unsigned minorvers,
|
|
+ int isset)
|
|
+{
|
|
+ char sign = isset ? '+' : '-';
|
|
+ if (minorvers == 0)
|
|
+ return snprintf(ptr, size, "%c%u ", sign, vers);
|
|
+ return snprintf(ptr, size, "%c%u.%u ", sign, vers, minorvers);
|
|
+}
|
|
+
|
|
+void
|
|
nfssvc_setvers(unsigned int ctlbits, unsigned int minorvers, unsigned int minorversset)
|
|
{
|
|
int fd, n, off;
|
|
- char *ptr;
|
|
|
|
- ptr = buf;
|
|
off = 0;
|
|
fd = open(NFSD_VERS_FILE, O_WRONLY);
|
|
if (fd < 0)
|
|
return;
|
|
|
|
- for (n = NFS4_MINMINOR; n <= NFS4_MAXMINOR; n++) {
|
|
- if (NFSCTL_VERISSET(minorversset, n)) {
|
|
- if (NFSCTL_VERISSET(minorvers, n))
|
|
- off += snprintf(ptr+off, sizeof(buf) - off, "+4.%d ", n);
|
|
- else
|
|
- off += snprintf(ptr+off, sizeof(buf) - off, "-4.%d ", n);
|
|
- }
|
|
- }
|
|
- for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) {
|
|
- if (NFSCTL_VERISSET(ctlbits, n))
|
|
- off += snprintf(ptr+off, sizeof(buf) - off, "+%d ", n);
|
|
- else
|
|
- off += snprintf(ptr+off, sizeof(buf) - off, "-%d ", n);
|
|
+ for (n = NFSD_MINVERS; n <= ((NFSD_MAXVERS < 3) ? NFSD_MAXVERS : 3); n++)
|
|
+ off += nfssvc_print_vers(&buf[off], sizeof(buf) - off,
|
|
+ n, 0, NFSCTL_VERISSET(ctlbits, n));
|
|
+
|
|
+ for (n = 0; n <= NFS4_MAXMINOR; n++) {
|
|
+ if (!NFSCTL_MINORISSET(minorversset, n))
|
|
+ continue;
|
|
+ off += nfssvc_print_vers(&buf[off], sizeof(buf) - off,
|
|
+ 4, n, NFSCTL_MINORISSET(minorvers, n));
|
|
}
|
|
+ if (!off--)
|
|
+ goto out;
|
|
+ buf[off] = '\0';
|
|
xlog(D_GENERAL, "Writing version string to kernel: %s", buf);
|
|
- snprintf(ptr+off, sizeof(buf) - off, "\n");
|
|
+ snprintf(&buf[off], sizeof(buf) - off, "\n");
|
|
if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf))
|
|
xlog(L_ERROR, "Setting version failed: errno %d (%m)", errno);
|
|
-
|
|
+out:
|
|
close(fd);
|
|
|
|
return;
|
|
diff --git a/utils/nfsd/nfssvc.h b/utils/nfsd/nfssvc.h
|
|
index cd5a7e8..39ebf37 100644
|
|
--- a/utils/nfsd/nfssvc.h
|
|
+++ b/utils/nfsd/nfssvc.h
|
|
@@ -28,3 +28,4 @@ void nfssvc_set_time(const char *type, const int seconds);
|
|
int nfssvc_set_rdmaport(const char *port);
|
|
void nfssvc_setvers(unsigned int ctlbits, unsigned int minorvers4, unsigned int minorvers4set);
|
|
int nfssvc_threads(int nrservs);
|
|
+void nfssvc_get_minormask(unsigned int *mask);
|
|
diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
|
|
index 7af9efb..0baaa3e 100644
|
|
--- a/utils/nfsdcltrack/nfsdcltrack.c
|
|
+++ b/utils/nfsdcltrack/nfsdcltrack.c
|
|
@@ -56,8 +56,6 @@
|
|
/* defined by RFC 3530 */
|
|
#define NFS4_OPAQUE_LIMIT 1024
|
|
|
|
-char *conf_path = NFS_CONFFILE;
|
|
-
|
|
/* private data structures */
|
|
struct cltrack_cmd {
|
|
char *name;
|
|
@@ -566,7 +564,7 @@ main(int argc, char **argv)
|
|
xlog_syslog(1);
|
|
xlog_stderr(0);
|
|
|
|
- conf_init();
|
|
+ conf_init(NFS_CONFFILE);
|
|
xlog_from_conffile("nfsdcltrack");
|
|
val = conf_get_str("nfsdcltrack", "storagedir");
|
|
if (val)
|
|
@@ -581,6 +579,7 @@ main(int argc, char **argv)
|
|
switch (arg) {
|
|
case 'd':
|
|
xlog_config(D_ALL, 1);
|
|
+ break;
|
|
case 'f':
|
|
xlog_syslog(0);
|
|
xlog_stderr(1);
|
|
diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
|
|
index 54cd748..1552eba 100644
|
|
--- a/utils/nfsdcltrack/sqlite.c
|
|
+++ b/utils/nfsdcltrack/sqlite.c
|
|
@@ -101,7 +101,7 @@ sqlite_query_schema_version(void)
|
|
"SELECT value FROM parameters WHERE key == \"version\";",
|
|
-1, &stmt, NULL);
|
|
if (ret != SQLITE_OK) {
|
|
- xlog(L_ERROR, "Unable to prepare select statement: %s",
|
|
+ xlog(D_GENERAL, "Unable to prepare select statement: %s",
|
|
sqlite3_errmsg(dbh));
|
|
ret = 0;
|
|
goto out;
|
|
@@ -110,7 +110,7 @@ sqlite_query_schema_version(void)
|
|
/* query schema version */
|
|
ret = sqlite3_step(stmt);
|
|
if (ret != SQLITE_ROW) {
|
|
- xlog(L_ERROR, "Select statement execution failed: %s",
|
|
+ xlog(D_GENERAL, "Select statement execution failed: %s",
|
|
sqlite3_errmsg(dbh));
|
|
ret = 0;
|
|
goto out;
|
|
diff --git a/utils/statd/Makefile.am b/utils/statd/Makefile.am
|
|
index 152b680..ea32075 100644
|
|
--- a/utils/statd/Makefile.am
|
|
+++ b/utils/statd/Makefile.am
|
|
@@ -18,6 +18,7 @@ statd_LDADD = ../../support/nsm/libnsm.a \
|
|
$(LIBWRAP) $(LIBNSL) $(LIBCAP) $(LIBTIRPC)
|
|
sm_notify_LDADD = ../../support/nsm/libnsm.a \
|
|
../../support/nfs/libnfs.a \
|
|
+ ../../support/misc/libmisc.a \
|
|
$(LIBNSL) $(LIBCAP) $(LIBTIRPC)
|
|
|
|
EXTRA_DIST = sim_sm_inter.x $(man8_MANS) simulate.c
|
|
diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c
|
|
index 623213e..d216ddb 100644
|
|
--- a/utils/statd/sm-notify.c
|
|
+++ b/utils/statd/sm-notify.c
|
|
@@ -45,6 +45,8 @@
|
|
|
|
#define NLM_END_GRACE_FILE "/proc/fs/lockd/nlm_end_grace"
|
|
|
|
+int lift_grace = 1;
|
|
+
|
|
struct nsm_host {
|
|
struct nsm_host * next;
|
|
char * name;
|
|
@@ -67,7 +69,6 @@ static _Bool opt_update_state = true;
|
|
static unsigned int opt_max_retry = 15 * 60;
|
|
static char * opt_srcaddr = NULL;
|
|
static char * opt_srcport = NULL;
|
|
-char * conf_path = NFS_CONFFILE;
|
|
|
|
static void notify(const int sock);
|
|
static int notify_host(int, struct nsm_host *);
|
|
@@ -489,11 +490,12 @@ main(int argc, char **argv)
|
|
else
|
|
progname = argv[0];
|
|
|
|
- conf_init();
|
|
+ conf_init(NFS_CONFFILE);
|
|
xlog_from_conffile("sm-notify");
|
|
opt_max_retry = conf_get_num("sm-notify", "retry-time", opt_max_retry / 60) * 60;
|
|
opt_srcport = conf_get_str("sm-notify", "outgoing-port");
|
|
opt_srcaddr = conf_get_str("sm-notify", "outgoing-addr");
|
|
+ lift_grace = conf_get_bool("sm-notify", "lift-grace", lift_grace);
|
|
s = conf_get_str("statd", "state-directory-path");
|
|
if (s && !nsm_setup_pathnames(argv[0], s))
|
|
exit(1);
|
|
@@ -570,7 +572,8 @@ usage: fprintf(stderr,
|
|
(void)nsm_retire_monitored_hosts();
|
|
if (nsm_load_notify_list(smn_get_host) == 0) {
|
|
xlog(D_GENERAL, "No hosts to notify; exiting");
|
|
- nsm_lift_grace_period();
|
|
+ if (lift_grace)
|
|
+ nsm_lift_grace_period();
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/utils/statd/sm-notify.man b/utils/statd/sm-notify.man
|
|
index bb7f6e0..cfe1e4b 100644
|
|
--- a/utils/statd/sm-notify.man
|
|
+++ b/utils/statd/sm-notify.man
|
|
@@ -241,6 +241,24 @@ These have the same effect as the command line options
|
|
.B v
|
|
respectively.
|
|
|
|
+An additional value recognized in the
|
|
+.B [sm-notify]
|
|
+section is
|
|
+.BR lift-grace .
|
|
+By default,
|
|
+.B sm-notify
|
|
+will lift lockd's grace period early if it has no hosts to notify.
|
|
+Some high availability configurations will run one
|
|
+.B sm-notify
|
|
+per floating IP address. In these configurations, lifting the
|
|
+grace period early may prevent clients from reclaiming locks.
|
|
+.RB "Setting " lift-grace " to " n
|
|
+will prevent
|
|
+.B sm-notify
|
|
+from ending the grace period early.
|
|
+.B lift-grace
|
|
+has no corresponding command line option.
|
|
+
|
|
The value recognized in the
|
|
.B [statd]
|
|
section is
|
|
diff --git a/utils/statd/statd.c b/utils/statd/statd.c
|
|
index d333b29..1443715 100644
|
|
--- a/utils/statd/statd.c
|
|
+++ b/utils/statd/statd.c
|
|
@@ -37,7 +37,6 @@
|
|
#include <sys/socket.h>
|
|
|
|
int run_mode = 0; /* foreground logging mode */
|
|
-char *conf_path = NFS_CONFFILE;
|
|
|
|
/* LH - I had these local to main, but it seemed silly to have
|
|
* two copies of each - one in main(), one static in log.c...
|
|
@@ -274,7 +273,7 @@ int main (int argc, char **argv)
|
|
/* Set hostname */
|
|
MY_NAME = NULL;
|
|
|
|
- conf_init();
|
|
+ conf_init(NFS_CONFFILE);
|
|
xlog_from_conffile("statd");
|
|
out_port = conf_get_num("statd", "outgoing-port", out_port);
|
|
port = conf_get_num("statd", "port", port);
|