3fff6a7ed8
Signed-off-by: Steve Dickson <steved@redhat.com>
1588 lines
51 KiB
Diff
1588 lines
51 KiB
Diff
diff --git a/.gitignore b/.gitignore
|
|
index df791a83..682153d5 100644
|
|
--- a/.gitignore
|
|
+++ b/.gitignore
|
|
@@ -86,3 +86,5 @@ systemd/rpc-gssd.service
|
|
cscope.*
|
|
# generic editor backup et al
|
|
*~
|
|
+# file generated by ctags
|
|
+tags
|
|
diff --git a/NEWS b/NEWS
|
|
index e70ae8ab..77872c5a 100644
|
|
--- a/NEWS
|
|
+++ b/NEWS
|
|
@@ -1,32 +1,32 @@
|
|
Significant changes for nfs-utils 1.1.0 - March/April 2007
|
|
|
|
- - rpc.lockd is gone. One 3 old kernel releases need it.
|
|
- - rpc.rquotad is gone. Use the one from the 'quota' package.
|
|
- Everone else does.
|
|
+ - rpc.lockd is gone. One 3 old kernel releases need it.
|
|
+ - rpc.rquotad is gone. Use the one from the 'quota' package.
|
|
+ Everyone else does.
|
|
- /sbin/{u,}mount.nfs{,4} are now installed so 'mount' will
|
|
use these to mount nfs filesystems instead of internal code.
|
|
+ mount.nfs will check for 'statd' to be running when mounting
|
|
- a filesystem which requires it. If it is not running it will
|
|
+ a filesystem which requires it. If it is not running it will
|
|
run "/usr/sbin/start-statd" to try to start it.
|
|
If statd is not running and cannot be started, mount.nfs will
|
|
refuse to mount the filesystem and will suggest the 'nolock'
|
|
option.
|
|
- Substantial changes to statd
|
|
+ The 'notify' process that must happen at boot has been split
|
|
- into a separate program "sm-notify". It ensures that it
|
|
- only runs once even if you restart statd. This is correct
|
|
+ into a separate program "sm-notify". It ensures that it
|
|
+ only runs once even if you restart statd. This is correct
|
|
behaviour.
|
|
+ statd stores state in the files in /var/lib/nfs/sm/ so that
|
|
if you kill and restart it, it will restore that state and
|
|
continue working correctly.
|
|
+ statd makes more use of DNS lookup and should handle
|
|
- multi-homed peers better. In particular, files in
|
|
+ multi-homed peers better. In particular, files in
|
|
/var/lib/nfs/sm/ are named with the Full Qualified Domain Name
|
|
if available.
|
|
- If you export a directory as 'crossmnt', all filesystems
|
|
mounted beneath are automatically exported with the same
|
|
options (unless explicitly exported with different options).
|
|
- - subtree_check is no-longer the default. The default is now
|
|
+ - subtree_check is no-longer the default. The default is now
|
|
no_subtree_check.
|
|
- By default the system 'rpcgen' is used while building
|
|
nfs-utils rather than the internal one.
|
|
@@ -43,14 +43,14 @@ Significant changes for nfs-utils 1.1.0 - March/April 2007
|
|
|
|
- A new option, -n, was added to rpc.gssd which specifies that
|
|
accesses by root should not use 'machine credentials' when
|
|
- accessing NFS file systems mounted with Kerberos. Using this
|
|
+ accessing NFS file systems mounted with Kerberos. Using this
|
|
option allows the root user to access the NFS space using any
|
|
Kerberos principal, rather than always using the machine
|
|
- credentials. However, its use also requires that root manually
|
|
+ credentials. However, its use also requires that root manually
|
|
authenticate before attempting a mount with Kerberos.
|
|
|
|
When rpc.gssd uses machine credentials, the selection algorithm has
|
|
- been changed. Instead of simply using the first "nfs/*" key in the
|
|
+ been changed. Instead of simply using the first "nfs/*" key in the
|
|
keytab, the keytab is now searched for keys in the following
|
|
defined order:
|
|
|
|
diff --git a/README b/README
|
|
index 5e982409..3b0e771f 100644
|
|
--- a/README
|
|
+++ b/README
|
|
@@ -25,7 +25,7 @@ Unpack the sources and run these commands:
|
|
# ./configure
|
|
# make
|
|
|
|
-To install binaries and documenation, run this command:
|
|
+To install binaries and documentation, run this command:
|
|
|
|
# make install
|
|
|
|
@@ -40,7 +40,7 @@ Updating to the latest head after you've already got it.
|
|
|
|
git pull
|
|
|
|
-Building requires that autotools be installed. To invoke them
|
|
+Building requires that autotools be installed. To invoke them
|
|
simply
|
|
|
|
sh autogen.sh
|
|
@@ -70,7 +70,7 @@ scripts can be written to work correctly.
|
|
3.1. SERVER STARTUP
|
|
|
|
|
|
- A/ mount -t nfsd /proc/fs/nfsd
|
|
+ A/ mount -t nfsd nfsd /proc/fs/nfsd
|
|
This filesystem needs to be mount before most daemons,
|
|
particularly exportfs, mountd, svcgssd, idmapd.
|
|
It could be mounted once, or the script that starts each daemon
|
|
@@ -95,27 +95,27 @@ scripts can be written to work correctly.
|
|
|
|
D/ rpc.statd --no-notify
|
|
It is best if statd is started before nfsd though this isn't
|
|
- critical. Certainly it should be at most a few seconds after
|
|
+ critical. Certainly, it should be at most a few seconds after
|
|
nfsd.
|
|
When nfsd starts it will start lockd. If lockd then receives a
|
|
- lock request it will communicate with statd. If statd is not
|
|
+ lock request, it will communicate with statd. If statd is not
|
|
running lockd will retry, but it won't wait forever for a
|
|
reply.
|
|
Note that if statd is started before nfsd, the --no-notify
|
|
- option must be used. If notify requests are sent out before
|
|
+ option must be used. If notify requests are sent out before
|
|
nfsd start, clients may try to reclaim locks and, on finding
|
|
that lockd isn't running, they will give up and never reclaim
|
|
the lock.
|
|
rpc.statd is only needed for NFSv2 and NFSv3 support.
|
|
|
|
E/ rpc.nfsd
|
|
- Starting nfsd will automatically start lockd. The nfs server
|
|
+ Starting nfsd will automatically start lockd. The nfs server
|
|
will now be fully active and respond to any requests from
|
|
clients.
|
|
|
|
F/ sm-notify
|
|
This will notify any client which might have locks from before
|
|
- a reboot to try to reclaim their locks. This should start
|
|
+ a reboot to try to reclaim their locks. This should start
|
|
immediately after rpc.nfsd is started so that clients have a
|
|
chance to reclaim locks within the 90 second grace period.
|
|
sm-notify is only needed for NFSv2 and NFSv3 support.
|
|
diff --git a/configure.ac b/configure.ac
|
|
index f1c46c5c..7672a760 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -71,18 +71,6 @@ AC_ARG_WITH(systemd,
|
|
AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1])
|
|
AC_SUBST(unitdir)
|
|
|
|
-modprobedir=/usr/lib/modprobe.d
|
|
-AC_ARG_WITH(modprobedir,
|
|
- [AS_HELP_STRING([--with-modprobedir@<:@=modprobe-dir-path@:>@],[install modprobe config files @<:@Default: /usr/lib/modprobe.d@:>@])],
|
|
- if test "$withval" != "no" ; then
|
|
- modprobedir=$withval
|
|
- else
|
|
- modprobedir=
|
|
- fi
|
|
- )
|
|
- AM_CONDITIONAL(INSTALL_MODPROBEDIR, [test -n "$modprobedir"])
|
|
- AC_SUBST(modprobedir)
|
|
-
|
|
AC_ARG_ENABLE(nfsv4,
|
|
[AS_HELP_STRING([--disable-nfsv4],[disable support for NFSv4 @<:@default=no@:>@])],
|
|
enable_nfsv4=$enableval,
|
|
@@ -249,6 +237,16 @@ AC_ARG_ENABLE(nfsdcld,
|
|
enable_nfsdcld=$enableval,
|
|
enable_nfsdcld="yes")
|
|
|
|
+AC_ARG_ENABLE(nfsrahead,
|
|
+ [AS_HELP_STRING([--disable-nfsrahead],[disable nfsrahead command @<:@default=no@:>@])],
|
|
+ enable_nfsrahead=$enableval,
|
|
+ enable_nfsrahead="yes")
|
|
+ AM_CONDITIONAL(CONFIG_NFSRAHEAD, [test "$enable_nfsrahead" = "yes" ])
|
|
+ if test "$enable_nfsrahead" = yes; then
|
|
+ dnl Check for -lmount
|
|
+ PKG_CHECK_MODULES([LIBMOUNT], [mount])
|
|
+ fi
|
|
+
|
|
AC_ARG_ENABLE(nfsdcltrack,
|
|
[AS_HELP_STRING([--disable-nfsdcltrack],[disable NFSv4 clientid tracking programs @<:@default=no@:>@])],
|
|
enable_nfsdcltrack=$enableval,
|
|
@@ -678,12 +676,12 @@ AC_SUBST([AM_CFLAGS], ["$my_am_cflags $flg1 $flg2 $flg3 $flg4 $flg5"])
|
|
# Make sure that $ACLOCAL_FLAGS are used during a rebuild
|
|
AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_macro_dir \$(ACLOCAL_FLAGS)"])
|
|
|
|
-# make _sysconfdir available for substituion in config files
|
|
+# make _sysconfdir available for substitution in config files
|
|
# 2 "evals" needed late to expand variable names.
|
|
AC_SUBST([_sysconfdir])
|
|
AC_CONFIG_COMMANDS_PRE([eval eval _sysconfdir=$sysconfdir])
|
|
|
|
-# make _statedir available for substituion in config files
|
|
+# make _statedir available for substitution in config files
|
|
# 2 "evals" needed late to expand variable names.
|
|
AC_SUBST([_statedir])
|
|
AC_CONFIG_COMMANDS_PRE([eval eval _statedir=$statedir])
|
|
@@ -695,7 +693,7 @@ else
|
|
fi
|
|
AC_SUBST(rpc_pipefsmount)
|
|
|
|
-# make _rpc_pipefsmount available for substituion in config files
|
|
+# make _rpc_pipefsmount available for substitution in config files
|
|
# 2 "evals" needed late to expand variable names.
|
|
AC_SUBST([_rpc_pipefsmount])
|
|
AC_CONFIG_COMMANDS_PRE([eval eval _rpc_pipefsmount=$rpc_pipefsmount])
|
|
diff --git a/support/export/auth.c b/support/export/auth.c
|
|
index 03ce4b8a..2d7960f1 100644
|
|
--- a/support/export/auth.c
|
|
+++ b/support/export/auth.c
|
|
@@ -82,7 +82,7 @@ check_useipaddr(void)
|
|
}
|
|
|
|
unsigned int
|
|
-auth_reload()
|
|
+auth_reload(void)
|
|
{
|
|
struct stat stb;
|
|
static ino_t last_inode;
|
|
diff --git a/support/export/cache.c b/support/export/cache.c
|
|
index a5823e92..0a37703b 100644
|
|
--- a/support/export/cache.c
|
|
+++ b/support/export/cache.c
|
|
@@ -346,27 +346,27 @@ static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid)
|
|
|
|
/* Possible sources of uuid are
|
|
* - blkid uuid
|
|
- * - statfs64 uuid
|
|
+ * - statfs uuid
|
|
*
|
|
- * On some filesystems (e.g. vfat) the statfs64 uuid is simply an
|
|
+ * On some filesystems (e.g. vfat) the statfs uuid is simply an
|
|
* encoding of the device that the filesystem is mounted from, so
|
|
* it we be very bad to use that (as device numbers change). blkid
|
|
* must be preferred.
|
|
- * On other filesystems (e.g. btrfs) the statfs64 uuid contains
|
|
+ * On other filesystems (e.g. btrfs) the statfs uuid contains
|
|
* important info that the blkid uuid cannot contain: This happens
|
|
* when multiple subvolumes are exported (they have the same
|
|
- * blkid uuid but different statfs64 uuids).
|
|
+ * blkid uuid but different statfs uuids).
|
|
* We rely on get_uuid_blkdev *knowing* which is which and not returning
|
|
- * a uuid for filesystems where the statfs64 uuid is better.
|
|
+ * a uuid for filesystems where the statfs uuid is better.
|
|
*
|
|
*/
|
|
- struct statfs64 st;
|
|
+ struct statfs st;
|
|
char fsid_val[17];
|
|
const char *blkid_val = NULL;
|
|
const char *val;
|
|
int rc;
|
|
|
|
- rc = nfsd_path_statfs64(path, &st);
|
|
+ rc = nfsd_path_statfs(path, &st);
|
|
|
|
if (type == 0 && rc == 0) {
|
|
const unsigned long *bad;
|
|
@@ -410,12 +410,16 @@ static char *next_mnt(void **v, char *p)
|
|
*v = f;
|
|
} else
|
|
f = *v;
|
|
- while ((me = getmntent(f)) != NULL && l > 1) {
|
|
+ while ((me = getmntent(f)) != NULL && l >= 1) {
|
|
char *mnt_dir = nfsd_path_strip_root(me->mnt_dir);
|
|
|
|
if (!mnt_dir)
|
|
continue;
|
|
|
|
+ /* Everything below "/" is a proper sub-mount */
|
|
+ if (strcmp(p, "/") == 0)
|
|
+ return mnt_dir;
|
|
+
|
|
if (strncmp(mnt_dir, p, l) == 0 && mnt_dir[l] == '/')
|
|
return mnt_dir;
|
|
}
|
|
@@ -932,6 +936,7 @@ static void write_fsloc(char **bp, int *blen, struct exportent *ep)
|
|
release_replicas(servers);
|
|
}
|
|
#endif
|
|
+
|
|
static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask)
|
|
{
|
|
struct sec_entry *p;
|
|
@@ -949,7 +954,20 @@ static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_m
|
|
qword_addint(bp, blen, p->flav->fnum);
|
|
qword_addint(bp, blen, p->flags & flag_mask);
|
|
}
|
|
+}
|
|
+
|
|
+static void write_xprtsec(char **bp, int *blen, struct exportent *ep)
|
|
+{
|
|
+ struct xprtsec_entry *p;
|
|
+
|
|
+ for (p = ep->e_xprtsec; p->info; p++);
|
|
+ if (p == ep->e_xprtsec)
|
|
+ return;
|
|
|
|
+ qword_add(bp, blen, "xprtsec");
|
|
+ qword_addint(bp, blen, p - ep->e_xprtsec);
|
|
+ for (p = ep->e_xprtsec; p->info; p++)
|
|
+ qword_addint(bp, blen, p->info->number);
|
|
}
|
|
|
|
static int dump_to_cache(int f, char *buf, int blen, char *domain,
|
|
@@ -992,6 +1010,7 @@ static int dump_to_cache(int f, char *buf, int blen, char *domain,
|
|
qword_add(&bp, &blen, "uuid");
|
|
qword_addhex(&bp, &blen, u, 16);
|
|
}
|
|
+ write_xprtsec(&bp, &blen, exp);
|
|
xlog(D_AUTH, "granted access to %s for %s",
|
|
path, *domain == '$' ? domain+1 : domain);
|
|
} else {
|
|
diff --git a/support/export/client.c b/support/export/client.c
|
|
index ea4f89d3..79164fef 100644
|
|
--- a/support/export/client.c
|
|
+++ b/support/export/client.c
|
|
@@ -699,6 +699,9 @@ check_netgroup(const nfs_client *clp, const struct addrinfo *ai)
|
|
|
|
/* check whether the IP itself is in the netgroup */
|
|
ip = calloc(INET6_ADDRSTRLEN, 1);
|
|
+ if (ip == NULL)
|
|
+ goto out;
|
|
+
|
|
if (inet_ntop(ai->ai_family, &(((struct sockaddr_in *)ai->ai_addr)->sin_addr), ip, INET6_ADDRSTRLEN) == ip) {
|
|
if (innetgr(netgroup, ip, NULL, NULL)) {
|
|
free(hname);
|
|
diff --git a/support/export/v4clients.c b/support/export/v4clients.c
|
|
index 5f15b614..32302512 100644
|
|
--- a/support/export/v4clients.c
|
|
+++ b/support/export/v4clients.c
|
|
@@ -26,7 +26,7 @@ void v4clients_init(void)
|
|
{
|
|
struct stat sb;
|
|
|
|
- if (!stat("/proc/fs/nfsd/clients", &sb) == 0 ||
|
|
+ if (stat("/proc/fs/nfsd/clients", &sb) != 0 ||
|
|
!S_ISDIR(sb.st_mode))
|
|
return;
|
|
if (clients_fd >= 0)
|
|
diff --git a/support/export/v4root.c b/support/export/v4root.c
|
|
index c12a7d85..fbb0ad5f 100644
|
|
--- a/support/export/v4root.c
|
|
+++ b/support/export/v4root.c
|
|
@@ -198,7 +198,7 @@ static int v4root_add_parents(nfs_export *exp)
|
|
* looking for components of the v4 mount.
|
|
*/
|
|
void
|
|
-v4root_set()
|
|
+v4root_set(void)
|
|
{
|
|
nfs_export *exp;
|
|
int i;
|
|
diff --git a/support/export/xtab.c b/support/export/xtab.c
|
|
index c888a80a..e210ca99 100644
|
|
--- a/support/export/xtab.c
|
|
+++ b/support/export/xtab.c
|
|
@@ -135,7 +135,7 @@ xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export)
|
|
}
|
|
|
|
int
|
|
-xtab_export_write()
|
|
+xtab_export_write(void)
|
|
{
|
|
return xtab_write(etab.statefn, etab.tmpfn, etab.lockfn, 1);
|
|
}
|
|
diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
|
|
index 0eca828e..be5867cf 100644
|
|
--- a/support/include/nfs/export.h
|
|
+++ b/support/include/nfs/export.h
|
|
@@ -40,4 +40,18 @@
|
|
#define NFSEXP_OLD_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
|
|
| NFSEXP_ALLSQUASH)
|
|
|
|
+/*
|
|
+ * Transport layer security policies that are permitted to access
|
|
+ * an export
|
|
+ */
|
|
+#define NFSEXP_XPRTSEC_NONE 0x0001
|
|
+#define NFSEXP_XPRTSEC_TLS 0x0002
|
|
+#define NFSEXP_XPRTSEC_MTLS 0x0004
|
|
+
|
|
+#define NFSEXP_XPRTSEC_NUM (3)
|
|
+
|
|
+#define NFSEXP_XPRTSEC_ALL (NFSEXP_XPRTSEC_NONE | \
|
|
+ NFSEXP_XPRTSEC_TLS | \
|
|
+ NFSEXP_XPRTSEC_MTLS)
|
|
+
|
|
#endif /* _NSF_EXPORT_H */
|
|
diff --git a/support/include/nfsd_path.h b/support/include/nfsd_path.h
|
|
index 3b73aadd..aa1e1dd0 100644
|
|
--- a/support/include/nfsd_path.h
|
|
+++ b/support/include/nfsd_path.h
|
|
@@ -7,7 +7,7 @@
|
|
#include <sys/stat.h>
|
|
|
|
struct file_handle;
|
|
-struct statfs64;
|
|
+struct statfs;
|
|
|
|
void nfsd_path_init(void);
|
|
|
|
@@ -18,8 +18,8 @@ char * nfsd_path_prepend_dir(const char *dir, const char *pathname);
|
|
int nfsd_path_stat(const char *pathname, struct stat *statbuf);
|
|
int nfsd_path_lstat(const char *pathname, struct stat *statbuf);
|
|
|
|
-int nfsd_path_statfs64(const char *pathname,
|
|
- struct statfs64 *statbuf);
|
|
+int nfsd_path_statfs(const char *pathname,
|
|
+ struct statfs *statbuf);
|
|
|
|
char * nfsd_realpath(const char *path, char *resolved_path);
|
|
|
|
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
|
|
index 6faba71b..61c19933 100644
|
|
--- a/support/include/nfslib.h
|
|
+++ b/support/include/nfslib.h
|
|
@@ -62,6 +62,18 @@ struct sec_entry {
|
|
int flags;
|
|
};
|
|
|
|
+#define XPRTSECMODE_COUNT 3
|
|
+
|
|
+struct xprtsec_info {
|
|
+ const char *name;
|
|
+ int number;
|
|
+};
|
|
+
|
|
+struct xprtsec_entry {
|
|
+ const struct xprtsec_info *info;
|
|
+ int flags;
|
|
+};
|
|
+
|
|
/*
|
|
* Data related to a single exports entry as returned by getexportent.
|
|
* FIXME: export options should probably be parsed at a later time to
|
|
@@ -83,6 +95,7 @@ struct exportent {
|
|
char * e_fslocdata;
|
|
char * e_uuid;
|
|
struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
|
|
+ struct xprtsec_entry e_xprtsec[XPRTSECMODE_COUNT + 1];
|
|
unsigned int e_ttl;
|
|
char * e_realpath;
|
|
};
|
|
@@ -99,6 +112,7 @@ struct rmtabent {
|
|
void setexportent(char *fname, char *type);
|
|
struct exportent * getexportent(int,int);
|
|
void secinfo_show(FILE *fp, struct exportent *ep);
|
|
+void xprtsecinfo_show(FILE *fp, struct exportent *ep);
|
|
void putexportent(struct exportent *xep);
|
|
void endexportent(void);
|
|
struct exportent * mkexportent(char *hname, char *path, char *opts);
|
|
diff --git a/support/junction/junction.c b/support/junction/junction.c
|
|
index 41cce261..0628bb0f 100644
|
|
--- a/support/junction/junction.c
|
|
+++ b/support/junction/junction.c
|
|
@@ -63,7 +63,7 @@ junction_open_path(const char *pathname, int *fd)
|
|
if (pathname == NULL || fd == NULL)
|
|
return FEDFS_ERR_INVAL;
|
|
|
|
- tmp = open(pathname, O_DIRECTORY);
|
|
+ tmp = open(pathname, O_PATH|O_DIRECTORY);
|
|
if (tmp == -1) {
|
|
switch (errno) {
|
|
case EPERM:
|
|
@@ -93,7 +93,7 @@ junction_is_directory(int fd, const char *path)
|
|
{
|
|
struct stat stb;
|
|
|
|
- if (fstat(fd, &stb) == -1) {
|
|
+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) {
|
|
xlog(D_GENERAL, "%s: failed to stat %s: %m",
|
|
__func__, path);
|
|
return FEDFS_ERR_ACCESS;
|
|
@@ -121,7 +121,7 @@ junction_is_sticky_bit_set(int fd, const char *path)
|
|
{
|
|
struct stat stb;
|
|
|
|
- if (fstat(fd, &stb) == -1) {
|
|
+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) {
|
|
xlog(D_GENERAL, "%s: failed to stat %s: %m",
|
|
__func__, path);
|
|
return FEDFS_ERR_ACCESS;
|
|
@@ -155,7 +155,7 @@ junction_set_sticky_bit(int fd, const char *path)
|
|
{
|
|
struct stat stb;
|
|
|
|
- if (fstat(fd, &stb) == -1) {
|
|
+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) {
|
|
xlog(D_GENERAL, "%s: failed to stat %s: %m",
|
|
__func__, path);
|
|
return FEDFS_ERR_ACCESS;
|
|
@@ -393,7 +393,7 @@ junction_get_mode(const char *pathname, mode_t *mode)
|
|
if (retval != FEDFS_OK)
|
|
return retval;
|
|
|
|
- if (fstat(fd, &stb) == -1) {
|
|
+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) {
|
|
xlog(D_GENERAL, "%s: failed to stat %s: %m",
|
|
__func__, pathname);
|
|
(void)close(fd);
|
|
diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
|
|
index 65e53c13..c3dea4f0 100644
|
|
--- a/support/misc/nfsd_path.c
|
|
+++ b/support/misc/nfsd_path.c
|
|
@@ -184,46 +184,46 @@ nfsd_path_lstat(const char *pathname, struct stat *statbuf)
|
|
return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf);
|
|
}
|
|
|
|
-struct nfsd_statfs64_data {
|
|
+struct nfsd_statfs_data {
|
|
const char *pathname;
|
|
- struct statfs64 *statbuf;
|
|
+ struct statfs *statbuf;
|
|
int ret;
|
|
int err;
|
|
};
|
|
|
|
static void
|
|
-nfsd_statfs64func(void *data)
|
|
+nfsd_statfsfunc(void *data)
|
|
{
|
|
- struct nfsd_statfs64_data *d = data;
|
|
+ struct nfsd_statfs_data *d = data;
|
|
|
|
- d->ret = statfs64(d->pathname, d->statbuf);
|
|
+ d->ret = statfs(d->pathname, d->statbuf);
|
|
if (d->ret < 0)
|
|
d->err = errno;
|
|
}
|
|
|
|
static int
|
|
-nfsd_run_statfs64(struct xthread_workqueue *wq,
|
|
+nfsd_run_statfs(struct xthread_workqueue *wq,
|
|
const char *pathname,
|
|
- struct statfs64 *statbuf)
|
|
+ struct statfs *statbuf)
|
|
{
|
|
- struct nfsd_statfs64_data data = {
|
|
+ struct nfsd_statfs_data data = {
|
|
pathname,
|
|
statbuf,
|
|
0,
|
|
0
|
|
};
|
|
- xthread_work_run_sync(wq, nfsd_statfs64func, &data);
|
|
+ xthread_work_run_sync(wq, nfsd_statfsfunc, &data);
|
|
if (data.ret < 0)
|
|
errno = data.err;
|
|
return data.ret;
|
|
}
|
|
|
|
int
|
|
-nfsd_path_statfs64(const char *pathname, struct statfs64 *statbuf)
|
|
+nfsd_path_statfs(const char *pathname, struct statfs *statbuf)
|
|
{
|
|
if (!nfsd_wq)
|
|
- return statfs64(pathname, statbuf);
|
|
- return nfsd_run_statfs64(nfsd_wq, pathname, statbuf);
|
|
+ return statfs(pathname, statbuf);
|
|
+ return nfsd_run_statfs(nfsd_wq, pathname, statbuf);
|
|
}
|
|
|
|
struct nfsd_realpath_data {
|
|
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
|
|
index 2c8f0752..da8ace3a 100644
|
|
--- a/support/nfs/exports.c
|
|
+++ b/support/nfs/exports.c
|
|
@@ -99,6 +99,7 @@ static void init_exportent (struct exportent *ee, int fromkernel)
|
|
ee->e_fslocmethod = FSLOC_NONE;
|
|
ee->e_fslocdata = NULL;
|
|
ee->e_secinfo[0].flav = NULL;
|
|
+ ee->e_xprtsec[0].info = NULL;
|
|
ee->e_nsquids = 0;
|
|
ee->e_nsqgids = 0;
|
|
ee->e_uuid = NULL;
|
|
@@ -122,7 +123,7 @@ getexportent(int fromkernel, int fromexports)
|
|
if (first || (ok = getexport(exp, sizeof(exp))) == 0) {
|
|
has_default_opts = 0;
|
|
has_default_subtree_opts = 0;
|
|
-
|
|
+
|
|
init_exportent(&def_ee, fromkernel);
|
|
|
|
ok = getpath(def_ee.e_path, sizeof(def_ee.e_path));
|
|
@@ -146,7 +147,7 @@ getexportent(int fromkernel, int fromexports)
|
|
if (exp[0] == '-' && !fromkernel) {
|
|
if (parseopts(exp + 1, &def_ee, 0, &has_default_subtree_opts) < 0)
|
|
return NULL;
|
|
-
|
|
+
|
|
has_default_opts = 1;
|
|
|
|
ok = getexport(exp, sizeof(exp));
|
|
@@ -239,7 +240,6 @@ void secinfo_show(FILE *fp, struct exportent *ep)
|
|
if (ep->e_secinfo[0].flav == NULL)
|
|
secinfo_addflavor(find_flavor("sys"), ep);
|
|
for (p1=ep->e_secinfo; p1->flav; p1=p2) {
|
|
-
|
|
fprintf(fp, ",sec=%s", p1->flav->flavour);
|
|
for (p2=p1+1; (p2->flav != NULL) && (p1->flags == p2->flags);
|
|
p2++) {
|
|
@@ -249,6 +249,17 @@ void secinfo_show(FILE *fp, struct exportent *ep)
|
|
}
|
|
}
|
|
|
|
+void xprtsecinfo_show(FILE *fp, struct exportent *ep)
|
|
+{
|
|
+ struct xprtsec_entry *p1, *p2;
|
|
+
|
|
+ for (p1 = ep->e_xprtsec; p1->info; p1 = p2) {
|
|
+ fprintf(fp, ",xprtsec=%s", p1->info->name);
|
|
+ for (p2 = p1 + 1; p2->info && (p1->flags == p2->flags); p2++)
|
|
+ fprintf(fp, ":%s", p2->info->name);
|
|
+ }
|
|
+}
|
|
+
|
|
static void
|
|
fprintpath(FILE *fp, const char *path)
|
|
{
|
|
@@ -345,6 +356,7 @@ putexportent(struct exportent *ep)
|
|
}
|
|
fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid);
|
|
secinfo_show(fp, ep);
|
|
+ xprtsecinfo_show(fp, ep);
|
|
fprintf(fp, ")\n");
|
|
}
|
|
|
|
@@ -483,6 +495,75 @@ static unsigned int parse_flavors(char *str, struct exportent *ep)
|
|
return out;
|
|
}
|
|
|
|
+static const struct xprtsec_info xprtsec_name2info[] = {
|
|
+ { "none", NFSEXP_XPRTSEC_NONE },
|
|
+ { "tls", NFSEXP_XPRTSEC_TLS },
|
|
+ { "mtls", NFSEXP_XPRTSEC_MTLS },
|
|
+ { NULL, 0 }
|
|
+};
|
|
+
|
|
+static const struct xprtsec_info *find_xprtsec_info(const char *name)
|
|
+{
|
|
+ const struct xprtsec_info *info;
|
|
+
|
|
+ for (info = xprtsec_name2info; info->name; info++)
|
|
+ if (strcmp(info->name, name) == 0)
|
|
+ return info;
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Append the given xprtsec mode to the exportent's e_xprtsec array,
|
|
+ * or do nothing if it's already there. Returns the index of flavor in
|
|
+ * the resulting array in any case.
|
|
+ */
|
|
+static int xprtsec_addmode(const struct xprtsec_info *info, struct exportent *ep)
|
|
+{
|
|
+ struct xprtsec_entry *p;
|
|
+
|
|
+ for (p = ep->e_xprtsec; p->info; p++)
|
|
+ if (p->info == info || p->info->number == info->number)
|
|
+ return p - ep->e_xprtsec;
|
|
+
|
|
+ if (p - ep->e_xprtsec >= XPRTSECMODE_COUNT) {
|
|
+ xlog(L_ERROR, "more than %d xprtsec modes on an export\n",
|
|
+ XPRTSECMODE_COUNT);
|
|
+ return -1;
|
|
+ }
|
|
+ p->info = info;
|
|
+ p->flags = ep->e_flags;
|
|
+ (p + 1)->info = NULL;
|
|
+ return p - ep->e_xprtsec;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * @str is a colon seperated list of transport layer security modes.
|
|
+ * Their order is recorded in @ep, and a bitmap corresponding to the
|
|
+ * list is returned.
|
|
+ *
|
|
+ * A zero return indicates an error.
|
|
+ */
|
|
+static unsigned int parse_xprtsec(char *str, struct exportent *ep)
|
|
+{
|
|
+ unsigned int out = 0;
|
|
+ char *name;
|
|
+
|
|
+ while ((name = strsep(&str, ":"))) {
|
|
+ const struct xprtsec_info *info = find_xprtsec_info(name);
|
|
+ int bit;
|
|
+
|
|
+ if (!info) {
|
|
+ xlog(L_ERROR, "unknown xprtsec mode %s\n", name);
|
|
+ return 0;
|
|
+ }
|
|
+ bit = xprtsec_addmode(info, ep);
|
|
+ if (bit < 0)
|
|
+ return 0;
|
|
+ out |= 1 << bit;
|
|
+ }
|
|
+ return out;
|
|
+}
|
|
+
|
|
/* Sets the bits in @mask for the appropriate security flavor flags. */
|
|
static void setflags(int mask, unsigned int active, struct exportent *ep)
|
|
{
|
|
@@ -621,7 +702,7 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
|
|
ep->e_anonuid = strtol(opt+8, &oe, 10);
|
|
if (opt[8]=='\0' || *oe != '\0') {
|
|
xlog(L_ERROR, "%s: %d: bad anonuid \"%s\"\n",
|
|
- flname, flline, opt);
|
|
+ flname, flline, opt);
|
|
bad_option:
|
|
free(opt);
|
|
return -1;
|
|
@@ -631,7 +712,7 @@ bad_option:
|
|
ep->e_anongid = strtol(opt+8, &oe, 10);
|
|
if (opt[8]=='\0' || *oe != '\0') {
|
|
xlog(L_ERROR, "%s: %d: bad anongid \"%s\"\n",
|
|
- flname, flline, opt);
|
|
+ flname, flline, opt);
|
|
goto bad_option;
|
|
}
|
|
} else if (strncmp(opt, "squash_uids=", 12) == 0) {
|
|
@@ -649,13 +730,13 @@ bad_option:
|
|
setflags(NFSEXP_FSID, active, ep);
|
|
} else {
|
|
ep->e_fsid = strtoul(opt+5, &oe, 0);
|
|
- if (opt[5]!='\0' && *oe == '\0')
|
|
+ if (opt[5]!='\0' && *oe == '\0')
|
|
setflags(NFSEXP_FSID, active, ep);
|
|
else if (valid_uuid(opt+5))
|
|
ep->e_uuid = strdup(opt+5);
|
|
else {
|
|
xlog(L_ERROR, "%s: %d: bad fsid \"%s\"\n",
|
|
- flname, flline, opt);
|
|
+ flname, flline, opt);
|
|
goto bad_option;
|
|
}
|
|
}
|
|
@@ -688,6 +769,9 @@ bad_option:
|
|
active = parse_flavors(opt+4, ep);
|
|
if (!active)
|
|
goto bad_option;
|
|
+ } else if (strncmp(opt, "xprtsec=", 8) == 0) {
|
|
+ if (!parse_xprtsec(opt + 8, ep))
|
|
+ goto bad_option;
|
|
} else {
|
|
xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
|
|
flname, flline, opt);
|
|
@@ -709,7 +793,7 @@ out:
|
|
if (warn && !had_subtree_opt)
|
|
xlog(L_WARNING, "%s [%d]: Neither 'subtree_check' or 'no_subtree_check' specified for export \"%s:%s\".\n"
|
|
" Assuming default behaviour ('no_subtree_check').\n"
|
|
- " NOTE: this default has changed since nfs-utils version 1.0.x\n",
|
|
+ " NOTE: this default has changed since nfs-utils version 1.0.x\n",
|
|
|
|
flname, flline,
|
|
ep->e_hostname, ep->e_path);
|
|
diff --git a/support/nfs/xlog.c b/support/nfs/xlog.c
|
|
index e5861b9d..fa125cef 100644
|
|
--- a/support/nfs/xlog.c
|
|
+++ b/support/nfs/xlog.c
|
|
@@ -46,11 +46,13 @@ int export_errno = 0;
|
|
|
|
static void xlog_toggle(int sig);
|
|
static struct xlog_debugfac debugnames[] = {
|
|
+ { "0", 0, },
|
|
{ "general", D_GENERAL, },
|
|
{ "call", D_CALL, },
|
|
{ "auth", D_AUTH, },
|
|
{ "parse", D_PARSE, },
|
|
{ "all", D_ALL, },
|
|
+ { "1", D_ALL, },
|
|
{ NULL, 0, },
|
|
};
|
|
|
|
@@ -119,13 +121,14 @@ xlog_sconfig(char *kind, int on)
|
|
{
|
|
struct xlog_debugfac *tbl = debugnames;
|
|
|
|
- while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind))
|
|
+ while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind))
|
|
tbl++;
|
|
if (!tbl->df_name) {
|
|
xlog (L_WARNING, "Invalid debug facility: %s\n", kind);
|
|
return;
|
|
}
|
|
- xlog_config(tbl->df_fac, on);
|
|
+ if (tbl->df_fac)
|
|
+ xlog_config(tbl->df_fac, on);
|
|
}
|
|
|
|
void
|
|
diff --git a/support/nfsidmap/regex.c b/support/nfsidmap/regex.c
|
|
index 958b4ac8..8424179f 100644
|
|
--- a/support/nfsidmap/regex.c
|
|
+++ b/support/nfsidmap/regex.c
|
|
@@ -542,7 +542,7 @@ struct trans_func regex_trans = {
|
|
.gss_princ_to_grouplist = regex_gss_princ_to_grouplist,
|
|
};
|
|
|
|
-struct trans_func *libnfsidmap_plugin_init()
|
|
+struct trans_func *libnfsidmap_plugin_init(void)
|
|
{
|
|
return (®ex_trans);
|
|
}
|
|
diff --git a/systemd/50-nfs.conf b/systemd/50-nfs.conf
|
|
deleted file mode 100644
|
|
index 19e8ee73..00000000
|
|
--- a/systemd/50-nfs.conf
|
|
+++ /dev/null
|
|
@@ -1,16 +0,0 @@
|
|
-# Ensure all NFS systctl settings get applied when modules load
|
|
-
|
|
-# sunrpc module supports "sunrpc.*" sysctls
|
|
-install sunrpc /sbin/modprobe --ignore-install sunrpc $CMDLINE_OPTS && { /sbin/sysctl -q --pattern sunrpc --system; exit 0; }
|
|
-
|
|
-# rpcrdma module supports sunrpc.svc_rdma.*
|
|
-install rpcrdma /sbin/modprobe --ignore-install rpcrdma $CMDLINE_OPTS && { /sbin/sysctl -q --pattern sunrpc.svc_rdma --system; exit 0; }
|
|
-
|
|
-# lockd module supports "fs.nfs.nlm*" and "fs.nfs.nsm*" sysctls
|
|
-install lockd /sbin/modprobe --ignore-install lockd $CMDLINE_OPTS && { /sbin/sysctl -q --pattern fs.nfs.n[sl]m --system; exit 0; }
|
|
-
|
|
-# nfsv4 module supports "fs.nfs.*" sysctls (nfs_callback_tcpport and idmap_cache_timeout)
|
|
-install nfsv4 /sbin/modprobe --ignore-install nfsv4 $CMDLINE_OPTS && { /sbin/sysctl -q --pattern 'fs.nfs.(nfs_callback_tcpport|idmap_cache_timeout)' --system; exit 0; }
|
|
-
|
|
-# nfs module supports "fs.nfs.*" sysctls
|
|
-install nfs /sbin/modprobe --ignore-install nfs $CMDLINE_OPTS && { /sbin/sysctl -q --pattern fs.nfs --system; exit 0; }
|
|
diff --git a/systemd/60-nfs.rules b/systemd/60-nfs.rules
|
|
new file mode 100644
|
|
index 00000000..188423c1
|
|
--- /dev/null
|
|
+++ b/systemd/60-nfs.rules
|
|
@@ -0,0 +1,21 @@
|
|
+# Ensure all NFS systctl settings get applied when modules load
|
|
+
|
|
+# sunrpc module supports "sunrpc.*" sysctls
|
|
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="sunrpc", \
|
|
+ RUN+="/sbin/sysctl -q --pattern ^sunrpc --system"
|
|
+
|
|
+# rpcrdma module supports sunrpc.svc_rdma.*
|
|
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="rpcrdma", \
|
|
+ RUN+="/sbin/sysctl -q --pattern ^sunrpc.svc_rdma --system"
|
|
+
|
|
+# lockd module supports "fs.nfs.nlm*" and "fs.nfs.nsm*" sysctls
|
|
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="lockd", \
|
|
+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs.n[sl]m --system"
|
|
+
|
|
+# nfsv4 module supports "fs.nfs.*" sysctls (nfs_callback_tcpport and idmap_cache_timeout)
|
|
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nfsv4", \
|
|
+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs.(nfs_callback_tcpport|idmap_cache_timeout) --system"
|
|
+
|
|
+# nfs module supports "fs.nfs.*" sysctls
|
|
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nfs", \
|
|
+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs --system"
|
|
diff --git a/systemd/Makefile.am b/systemd/Makefile.am
|
|
index 7b5ab84b..577c6a22 100644
|
|
--- a/systemd/Makefile.am
|
|
+++ b/systemd/Makefile.am
|
|
@@ -2,7 +2,8 @@
|
|
|
|
MAINTAINERCLEANFILES = Makefile.in
|
|
|
|
-modprobe_files = 50-nfs.conf
|
|
+udev_rulesdir = /usr/lib/udev/rules.d/
|
|
+udev_files = 60-nfs.rules
|
|
|
|
unit_files = \
|
|
nfs-client.target \
|
|
@@ -53,7 +54,7 @@ endif
|
|
|
|
man5_MANS = nfs.conf.man
|
|
man7_MANS = nfs.systemd.man
|
|
-EXTRA_DIST = $(unit_files) $(modprobe_files) $(man5_MANS) $(man7_MANS)
|
|
+EXTRA_DIST = $(unit_files) $(udev_files) $(man5_MANS) $(man7_MANS)
|
|
|
|
generator_dir = $(unitdir)/../system-generators
|
|
|
|
@@ -75,14 +76,10 @@ rpc_pipefs_generator_LDADD = ../support/nfs/libnfs.la
|
|
|
|
if INSTALL_SYSTEMD
|
|
genexec_PROGRAMS = nfs-server-generator rpc-pipefs-generator
|
|
-install-data-hook: $(unit_files) $(modprobe_files)
|
|
+install-data-hook: $(unit_files) $(udev_files)
|
|
mkdir -p $(DESTDIR)/$(unitdir)
|
|
cp $(unit_files) $(DESTDIR)/$(unitdir)
|
|
cp $(rpc_pipefs_mount_file) $(DESTDIR)/$(unitdir)/$(rpc_pipefsmount)
|
|
-else
|
|
-install-data-hook: $(modprobe_files)
|
|
-endif
|
|
-if INSTALL_MODPROBEDIR
|
|
- mkdir -p $(DESTDIR)$(modprobedir)
|
|
- cp $(modprobe_files) $(DESTDIR)$(modprobedir)
|
|
+ mkdir -p $(DESTDIR)/$(udev_rulesdir)
|
|
+ cp $(udev_files) $(DESTDIR)/$(udev_rulesdir)
|
|
endif
|
|
diff --git a/systemd/auth-rpcgss-module.service b/systemd/auth-rpcgss-module.service
|
|
index 45482833..4a69a7b7 100644
|
|
--- a/systemd/auth-rpcgss-module.service
|
|
+++ b/systemd/auth-rpcgss-module.service
|
|
@@ -8,8 +8,9 @@
|
|
Description=Kernel Module supporting RPCSEC_GSS
|
|
DefaultDependencies=no
|
|
Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service
|
|
-Wants=gssproxy.service rpc-svcgssd.service rpc-gssd.service
|
|
+Wants=gssproxy.service rpc-gssd.service
|
|
ConditionPathExists=/etc/krb5.keytab
|
|
+ConditionVirtualization=!container
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
|
|
index b432f910..2cdd7868 100644
|
|
--- a/systemd/nfs-server.service
|
|
+++ b/systemd/nfs-server.service
|
|
@@ -15,7 +15,7 @@ After=nfsdcld.service
|
|
Before=rpc-statd-notify.service
|
|
|
|
# GSS services dependencies and ordering
|
|
-Wants=auth-rpcgss-module.service
|
|
+Wants=auth-rpcgss-module.service rpc-svcgssd.service
|
|
After=rpc-gssd.service gssproxy.service rpc-svcgssd.service
|
|
|
|
[Service]
|
|
diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
|
|
index e74083e9..bfd3380f 100644
|
|
--- a/systemd/nfs.conf.man
|
|
+++ b/systemd/nfs.conf.man
|
|
@@ -98,6 +98,12 @@ value, which can be one or more from the list
|
|
.BR parse ,
|
|
.BR all .
|
|
When a list is given, the members should be comma-separated.
|
|
+The values
|
|
+.BR 0
|
|
+and
|
|
+.BR 1
|
|
+are also accepted, with '0' making no changes to the debug level, and '1' equivalent to specifying 'all'.
|
|
+
|
|
.TP
|
|
.B general
|
|
Recognized values:
|
|
@@ -166,6 +172,7 @@ for details.
|
|
Recognized values:
|
|
.BR threads ,
|
|
.BR host ,
|
|
+.BR scope ,
|
|
.BR port ,
|
|
.BR grace-time ,
|
|
.BR lease-time ,
|
|
diff --git a/tools/Makefile.am b/tools/Makefile.am
|
|
index 40c17c37..48fd0cdf 100644
|
|
--- a/tools/Makefile.am
|
|
+++ b/tools/Makefile.am
|
|
@@ -12,6 +12,10 @@ if CONFIG_NFSDCLD
|
|
OPTDIRS += nfsdclddb
|
|
endif
|
|
|
|
-SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts nfsrahead $(OPTDIRS)
|
|
+if CONFIG_NFSRAHEAD
|
|
+OPTDIRS += nfsrahead
|
|
+endif
|
|
+
|
|
+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts $(OPTDIRS)
|
|
|
|
MAINTAINERCLEANFILES = Makefile.in
|
|
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
|
|
index 1df74ba8..85294fb9 100755
|
|
--- a/tools/nfs-iostat/nfs-iostat.py
|
|
+++ b/tools/nfs-iostat/nfs-iostat.py
|
|
@@ -43,7 +43,7 @@ NfsEventCounters = [
|
|
'vfspermission',
|
|
'vfsupdatepage',
|
|
'vfsreadpage',
|
|
- 'vfsreadpages',
|
|
+ 'vfsreadpages', # or vfsreadahead in statvers=1.2 or above
|
|
'vfswritepage',
|
|
'vfswritepages',
|
|
'vfsreaddir',
|
|
@@ -86,14 +86,14 @@ class DeviceData:
|
|
self.__nfs_data['export'] = words[1]
|
|
self.__nfs_data['mountpoint'] = words[4]
|
|
self.__nfs_data['fstype'] = words[7]
|
|
- if words[7] == 'nfs':
|
|
- self.__nfs_data['statvers'] = words[8]
|
|
+ if words[7] == 'nfs' or words[7] == 'nfs4':
|
|
+ self.__nfs_data['statvers'] = float(words[8].split('=',1)[1])
|
|
elif 'nfs' in words or 'nfs4' in words:
|
|
self.__nfs_data['export'] = words[0]
|
|
self.__nfs_data['mountpoint'] = words[3]
|
|
self.__nfs_data['fstype'] = words[6]
|
|
if words[6] == 'nfs':
|
|
- self.__nfs_data['statvers'] = words[7]
|
|
+ self.__nfs_data['statvers'] = float(words[7].split('=',1)[1])
|
|
elif words[0] == 'age:':
|
|
self.__nfs_data['age'] = int(words[1])
|
|
elif words[0] == 'opts:':
|
|
@@ -294,8 +294,11 @@ class DeviceData:
|
|
print()
|
|
print('%d nfs_readpage() calls read %d pages' % \
|
|
(vfsreadpage, vfsreadpage))
|
|
- print('%d nfs_readpages() calls read %d pages' % \
|
|
- (vfsreadpages, pages_read - vfsreadpage))
|
|
+ multipageread = "readpages"
|
|
+ if self.__nfs_data['statvers'] >= 1.2:
|
|
+ multipageread = "readahead"
|
|
+ print('%d nfs_%s() calls read %d pages' % \
|
|
+ (vfsreadpages, multipageread, pages_read - vfsreadpage))
|
|
if vfsreadpages != 0:
|
|
print('(%.1f pages per call)' % \
|
|
(float(pages_read - vfsreadpage) / vfsreadpages))
|
|
diff --git a/tools/nfsrahead/Makefile.am b/tools/nfsrahead/Makefile.am
|
|
index 845ea0d5..7e08233a 100644
|
|
--- a/tools/nfsrahead/Makefile.am
|
|
+++ b/tools/nfsrahead/Makefile.am
|
|
@@ -1,6 +1,6 @@
|
|
libexec_PROGRAMS = nfsrahead
|
|
nfsrahead_SOURCES = main.c
|
|
-nfsrahead_LDFLAGS= -lmount
|
|
+nfsrahead_LDFLAGS= $(LIBMOUNT_LIBS)
|
|
nfsrahead_LDADD = ../../support/nfs/libnfsconf.la
|
|
|
|
man5_MANS = nfsrahead.man
|
|
diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c
|
|
index c83c6f71..8a11cf1a 100644
|
|
--- a/tools/nfsrahead/main.c
|
|
+++ b/tools/nfsrahead/main.c
|
|
@@ -167,7 +167,7 @@ int main(int argc, char **argv)
|
|
if ((ret = get_device_info(argv[optind], &device)) == 0)
|
|
break;
|
|
|
|
- if (ret != 0) {
|
|
+ if (ret != 0 || device.fstype == NULL) {
|
|
xlog(D_GENERAL, "unable to find device %s\n", argv[optind]);
|
|
goto out;
|
|
}
|
|
diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c
|
|
index 68206cc5..ec05179e 100644
|
|
--- a/tools/rpcdebug/rpcdebug.c
|
|
+++ b/tools/rpcdebug/rpcdebug.c
|
|
@@ -257,7 +257,7 @@ get_flags(char *module)
|
|
perror(filename);
|
|
exit(1);
|
|
}
|
|
- if ((len = read(sysfd, buffer, sizeof(buffer))) < 0) {
|
|
+ if ((len = read(sysfd, buffer, sizeof(buffer))) <= 0) {
|
|
perror("read");
|
|
exit(1);
|
|
}
|
|
diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c
|
|
index 2736ac89..a565fdbd 100644
|
|
--- a/utils/blkmapd/device-discovery.c
|
|
+++ b/utils/blkmapd/device-discovery.c
|
|
@@ -187,10 +187,7 @@ static void bl_add_disk(char *filepath)
|
|
}
|
|
|
|
if (disk && diskpath) {
|
|
- if (serial) {
|
|
- free(serial->data);
|
|
- free(serial);
|
|
- }
|
|
+ bl_free_scsi_string(serial);
|
|
return;
|
|
}
|
|
|
|
@@ -228,10 +225,7 @@ static void bl_add_disk(char *filepath)
|
|
disk->size = size;
|
|
disk->valid_path = path;
|
|
}
|
|
- if (serial) {
|
|
- free(serial->data);
|
|
- free(serial);
|
|
- }
|
|
+ bl_free_scsi_string(serial);
|
|
}
|
|
return;
|
|
|
|
@@ -241,10 +235,7 @@ static void bl_add_disk(char *filepath)
|
|
free(path->full_path);
|
|
free(path);
|
|
}
|
|
- if (serial) {
|
|
- free(serial->data);
|
|
- free(serial);
|
|
- }
|
|
+ bl_free_scsi_string(serial);
|
|
return;
|
|
}
|
|
|
|
@@ -462,7 +453,7 @@ static void sig_die(int signal)
|
|
unlink(PID_FILE);
|
|
}
|
|
BL_LOG_ERR("exit on signal(%d)\n", signal);
|
|
- exit(1);
|
|
+ exit(0);
|
|
}
|
|
static void usage(void)
|
|
{
|
|
@@ -507,28 +498,44 @@ int main(int argc, char **argv)
|
|
if (fg) {
|
|
openlog("blkmapd", LOG_PERROR, 0);
|
|
} else {
|
|
- if (daemon(0, 0) != 0) {
|
|
- fprintf(stderr, "Daemonize failed\n");
|
|
+ pid_t pid = fork();
|
|
+ if (pid < 0) {
|
|
+ BL_LOG_ERR("fork error\n");
|
|
exit(1);
|
|
+ } else if (pid != 0) {
|
|
+ pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644);
|
|
+ if (pidfd < 0) {
|
|
+ BL_LOG_ERR("Create pid file %s failed\n", PID_FILE);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ if (lockf(pidfd, F_TLOCK, 0) < 0) {
|
|
+ BL_LOG_ERR("Already running; Exiting!");
|
|
+ close(pidfd);
|
|
+ exit(1);
|
|
+ }
|
|
+ if (ftruncate(pidfd, 0) < 0)
|
|
+ BL_LOG_ERR("ftruncate on %s failed: m\n", PID_FILE);
|
|
+ sprintf(pidbuf, "%d\n", pid);
|
|
+ if (write(pidfd, pidbuf, strlen(pidbuf)) != (ssize_t)strlen(pidbuf))
|
|
+ BL_LOG_ERR("write on %s failed: m\n", PID_FILE);
|
|
+ exit(0);
|
|
}
|
|
|
|
- openlog("blkmapd", LOG_PID, 0);
|
|
- pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644);
|
|
- if (pidfd < 0) {
|
|
- BL_LOG_ERR("Create pid file %s failed\n", PID_FILE);
|
|
- exit(1);
|
|
+ (void)setsid();
|
|
+ if (chdir("/")) {
|
|
+ BL_LOG_ERR("chdir error\n");
|
|
}
|
|
+ int fd = open("/dev/null", O_RDWR, 0);
|
|
+ if (fd >= 0) {
|
|
+ (void)dup2(fd, STDIN_FILENO);
|
|
+ (void)dup2(fd, STDOUT_FILENO);
|
|
+ (void)dup2(fd, STDERR_FILENO);
|
|
|
|
- if (lockf(pidfd, F_TLOCK, 0) < 0) {
|
|
- BL_LOG_ERR("Already running; Exiting!");
|
|
- close(pidfd);
|
|
- exit(1);
|
|
+ (void)close(fd);
|
|
}
|
|
- if (ftruncate(pidfd, 0) < 0)
|
|
- BL_LOG_WARNING("ftruncate on %s failed: m\n", PID_FILE);
|
|
- sprintf(pidbuf, "%d\n", getpid());
|
|
- if (write(pidfd, pidbuf, strlen(pidbuf)) != (ssize_t)strlen(pidbuf))
|
|
- BL_LOG_WARNING("write on %s failed: m\n", PID_FILE);
|
|
+
|
|
+ openlog("blkmapd", LOG_PID, 0);
|
|
}
|
|
|
|
signal(SIGINT, sig_die);
|
|
diff --git a/utils/blkmapd/device-discovery.h b/utils/blkmapd/device-discovery.h
|
|
index a86eed99..462aa943 100644
|
|
--- a/utils/blkmapd/device-discovery.h
|
|
+++ b/utils/blkmapd/device-discovery.h
|
|
@@ -151,6 +151,8 @@ uint64_t process_deviceinfo(const char *dev_addr_buf,
|
|
|
|
extern ssize_t atomicio(ssize_t(*f) (int, void *, size_t),
|
|
int fd, void *_s, size_t n);
|
|
+extern struct bl_serial *bl_create_scsi_string(int len, const char *bytes);
|
|
+extern void bl_free_scsi_string(struct bl_serial *str);
|
|
extern struct bl_serial *bldev_read_serial(int fd, const char *filename);
|
|
extern enum bl_path_state_e bldev_read_ap_state(int fd);
|
|
extern int bl_discover_devices(void);
|
|
diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c
|
|
index c7952c3e..9e5749ef 100644
|
|
--- a/utils/blkmapd/device-inq.c
|
|
+++ b/utils/blkmapd/device-inq.c
|
|
@@ -53,7 +53,7 @@
|
|
#define DEF_ALLOC_LEN 255
|
|
#define MX_ALLOC_LEN (0xc000 + 0x80)
|
|
|
|
-static struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
|
|
+struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
|
|
{
|
|
struct bl_serial *s;
|
|
|
|
@@ -66,7 +66,7 @@ static struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
|
|
return s;
|
|
}
|
|
|
|
-static void bl_free_scsi_string(struct bl_serial *str)
|
|
+void bl_free_scsi_string(struct bl_serial *str)
|
|
{
|
|
if (str)
|
|
free(str);
|
|
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
|
|
index 6ba615d1..37b9e4b3 100644
|
|
--- a/utils/exportfs/exportfs.c
|
|
+++ b/utils/exportfs/exportfs.c
|
|
@@ -69,14 +69,14 @@ static int _lockfd = -1;
|
|
* need these additional lockfile() routines.
|
|
*/
|
|
static void
|
|
-grab_lockfile()
|
|
+grab_lockfile(void)
|
|
{
|
|
_lockfd = open(lockfile, O_CREAT|O_RDWR, 0666);
|
|
if (_lockfd != -1)
|
|
lockf(_lockfd, F_LOCK, 0);
|
|
}
|
|
static void
|
|
-release_lockfile()
|
|
+release_lockfile(void)
|
|
{
|
|
if (_lockfd != -1) {
|
|
lockf(_lockfd, F_ULOCK, 0);
|
|
@@ -513,7 +513,7 @@ validate_export(nfs_export *exp)
|
|
*/
|
|
struct stat stb;
|
|
char *path = exportent_realpath(&exp->m_export);
|
|
- struct statfs64 stf;
|
|
+ struct statfs stf;
|
|
int fs_has_fsid = 0;
|
|
|
|
if (stat(path, &stb) < 0) {
|
|
@@ -528,7 +528,7 @@ validate_export(nfs_export *exp)
|
|
if (!can_test())
|
|
return;
|
|
|
|
- if (!statfs64(path, &stf) &&
|
|
+ if (!statfs(path, &stf) &&
|
|
(stf.f_fsid.__val[0] || stf.f_fsid.__val[1]))
|
|
fs_has_fsid = 1;
|
|
|
|
@@ -743,6 +743,7 @@ dump(int verbose, int export_format)
|
|
#endif
|
|
}
|
|
secinfo_show(stdout, ep);
|
|
+ xprtsecinfo_show(stdout, ep);
|
|
printf("%c\n", (c != '(')? ')' : ' ');
|
|
}
|
|
}
|
|
diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
|
|
index 54b3f877..83dd6807 100644
|
|
--- a/utils/exportfs/exports.man
|
|
+++ b/utils/exportfs/exports.man
|
|
@@ -125,7 +125,55 @@ In that case you may include multiple sec= options, and following options
|
|
will be enforced only for access using flavors listed in the immediately
|
|
preceding sec= option. The only options that are permitted to vary in
|
|
this way are ro, rw, no_root_squash, root_squash, and all_squash.
|
|
+.SS Transport layer security
|
|
+The Linux NFS server allows the use of RPC-with-TLS (RFC 9289) to
|
|
+protect RPC traffic between itself and its clients.
|
|
+Alternately, administrators can secure NFS traffic using a VPN,
|
|
+or an ssh tunnel or similar mechanism, in a way that is transparent
|
|
+to the server.
|
|
.PP
|
|
+To enable the use of RPC-with-TLS, the server's administrator must
|
|
+install and configure
|
|
+.BR tlshd
|
|
+to handle transport layer security handshake requests from the local
|
|
+kernel.
|
|
+Clients can then choose to use RPC-with-TLS or they may continue
|
|
+operating without it.
|
|
+.PP
|
|
+Administrators may require the use of RPC-with-TLS to protect access
|
|
+to individual exports.
|
|
+This is particularly useful when using non-cryptographic security
|
|
+flavors such as
|
|
+.IR sec=sys .
|
|
+The
|
|
+.I xprtsec=
|
|
+option, followed by an unordered colon-delimited list of security policies,
|
|
+can restrict access to the export to only clients that have negotiated
|
|
+transport-layer security.
|
|
+Currently supported transport layer security policies include:
|
|
+.TP
|
|
+.IR none
|
|
+The server permits clients to access the export
|
|
+without the use of transport layer security.
|
|
+.TP
|
|
+.IR tls
|
|
+The server permits clients that have negotiated an RPC-with-TLS session
|
|
+without peer authentication (confidentiality only) to access the export.
|
|
+Clients are not required to offer an x.509 certificate
|
|
+when establishing a transport layer security session.
|
|
+.TP
|
|
+.IR mtls
|
|
+The server permits clients that have negotiated an RPC-with-TLS session
|
|
+with peer authentication to access the export.
|
|
+The server requires clients to offer an x.509 certificate
|
|
+when establishing a transport layer security session.
|
|
+.PP
|
|
+If RPC-with-TLS is configured and enabled and the
|
|
+.I xprtsec=
|
|
+option is not specified, the default setting for an export is
|
|
+.IR xprtsec=none:tls:mtls .
|
|
+With this setting, the server permits clients to use any transport
|
|
+layer security mechanism or none at all to access the export.
|
|
.SS General Options
|
|
.BR exportfs
|
|
understands the following export options:
|
|
@@ -581,7 +629,8 @@ a character class wildcard match.
|
|
.BR netgroup (5),
|
|
.BR mountd (8),
|
|
.BR nfsd (8),
|
|
-.BR showmount (8).
|
|
+.BR showmount (8),
|
|
+.BR tlshd (8).
|
|
.\".SH DIAGNOSTICS
|
|
.\"An error parsing the file is reported using syslogd(8) as level NOTICE from
|
|
.\"a DAEMON whenever
|
|
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
|
|
index e79c124d..cd9a965f 100644
|
|
--- a/utils/idmapd/idmapd.c
|
|
+++ b/utils/idmapd/idmapd.c
|
|
@@ -867,7 +867,7 @@ nfsdreopen_one(struct idmap_client *ic)
|
|
}
|
|
|
|
static void
|
|
-nfsdreopen()
|
|
+nfsdreopen(void)
|
|
{
|
|
nfsdreopen_one(&nfsd_ic[IC_NAMEID]);
|
|
nfsdreopen_one(&nfsd_ic[IC_IDNAME]);
|
|
diff --git a/utils/mount/error.c b/utils/mount/error.c
|
|
index 73295bf0..9ddbcc09 100644
|
|
--- a/utils/mount/error.c
|
|
+++ b/utils/mount/error.c
|
|
@@ -207,16 +207,17 @@ void mount_error(const char *spec, const char *mount_point, int error)
|
|
progname, spec);
|
|
break;
|
|
case EINVAL:
|
|
- nfs_error(_("%s: an incorrect mount option was specified"), progname);
|
|
+ nfs_error(_("%s: an incorrect mount option was specified for %s"),
|
|
+ progname, mount_point);
|
|
break;
|
|
case EOPNOTSUPP:
|
|
- nfs_error(_("%s: requested NFS version or transport protocol is not supported"),
|
|
- progname);
|
|
+ nfs_error(_("%s: requested NFS version or transport protocol is not supported for %s"),
|
|
+ progname, mount_point);
|
|
break;
|
|
case ENOTDIR:
|
|
if (spec)
|
|
- nfs_error(_("%s: mount spec %s or point %s is not a "
|
|
- "directory"), progname, spec, mount_point);
|
|
+ nfs_error(_("%s: mount spec %s or point %s is not a directory"),
|
|
+ progname, spec, mount_point);
|
|
else
|
|
nfs_error(_("%s: mount point %s is not a directory"),
|
|
progname, mount_point);
|
|
@@ -227,31 +228,31 @@ void mount_error(const char *spec, const char *mount_point, int error)
|
|
break;
|
|
case ENOENT:
|
|
if (spec)
|
|
- nfs_error(_("%s: mounting %s failed, "
|
|
- "reason given by server: %s"),
|
|
- progname, spec, strerror(error));
|
|
+ nfs_error(_("%s: mounting %s failed, reason given by server: %s"),
|
|
+ progname, spec, strerror(error));
|
|
else
|
|
nfs_error(_("%s: mount point %s does not exist"),
|
|
- progname, mount_point);
|
|
+ progname, mount_point);
|
|
break;
|
|
case ESPIPE:
|
|
rpc_mount_errors((char *)spec, 0, 0);
|
|
break;
|
|
case EIO:
|
|
- nfs_error(_("%s: mount system call failed"), progname);
|
|
+ nfs_error(_("%s: mount system call failed for %s"),
|
|
+ progname, mount_point);
|
|
break;
|
|
case EFAULT:
|
|
- nfs_error(_("%s: encountered unexpected error condition."),
|
|
- progname);
|
|
+ nfs_error(_("%s: encountered unexpected error condition for %s."),
|
|
+ progname, mount_point);
|
|
nfs_error(_("%s: please report the error to" PACKAGE_BUGREPORT),
|
|
- progname);
|
|
+ progname);
|
|
break;
|
|
case EALREADY:
|
|
/* Error message has already been provided */
|
|
break;
|
|
default:
|
|
- nfs_error(_("%s: %s"),
|
|
- progname, strerror(error));
|
|
+ nfs_error(_("%s: %s for %s on %s"),
|
|
+ progname, strerror(error), spec, mount_point);
|
|
}
|
|
}
|
|
|
|
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
|
index ed2f8253..01ead49f 100644
|
|
--- a/utils/mount/network.c
|
|
+++ b/utils/mount/network.c
|
|
@@ -179,7 +179,7 @@ static const unsigned long probe_mnt3_only[] = {
|
|
|
|
static const unsigned int *nfs_default_proto(void);
|
|
#ifdef MOUNT_CONFIG
|
|
-static const unsigned int *nfs_default_proto()
|
|
+static const unsigned int *nfs_default_proto(void)
|
|
{
|
|
extern unsigned long config_default_proto;
|
|
/*
|
|
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
|
|
index d9f34df3..7a410422 100644
|
|
--- a/utils/mount/nfs.man
|
|
+++ b/utils/mount/nfs.man
|
|
@@ -574,7 +574,39 @@ The
|
|
.B sloppy
|
|
option is an alternative to specifying
|
|
.BR mount.nfs " -s " option.
|
|
-
|
|
+.TP 1.5i
|
|
+.BI xprtsec= policy
|
|
+Specifies the use of transport layer security to protect NFS network
|
|
+traffic on behalf of this mount point.
|
|
+.I policy
|
|
+can be one of
|
|
+.BR none ,
|
|
+.BR tls ,
|
|
+or
|
|
+.BR mtls .
|
|
+.IP
|
|
+If
|
|
+.B none
|
|
+is specified,
|
|
+transport layer security is forced off, even if the NFS server supports
|
|
+transport layer security.
|
|
+If
|
|
+.B tls
|
|
+is specified, the client uses RPC-with-TLS to provide in-transit
|
|
+confidentiality.
|
|
+If
|
|
+.B mtls
|
|
+is specified, the client uses RPC-with-TLS to authenticate itself and
|
|
+to provide in-transit confidentiality.
|
|
+If the server does not support RPC-with-TLS or peer authentication
|
|
+fails, the mount attempt fails.
|
|
+.IP
|
|
+If the
|
|
+.B xprtsec=
|
|
+option is not specified,
|
|
+the default behavior depends on the kernel,
|
|
+but is usually equivalent to
|
|
+.BR "xprtsec=none" .
|
|
.SS "Options for NFS versions 2 and 3 only"
|
|
Use these options, along with the options in the above subsection,
|
|
for NFS versions 2 and 3 only.
|
|
diff --git a/utils/mount/nfsmount.conf b/utils/mount/nfsmount.conf
|
|
index 342063f7..c498eb80 100644
|
|
--- a/utils/mount/nfsmount.conf
|
|
+++ b/utils/mount/nfsmount.conf
|
|
@@ -59,13 +59,13 @@
|
|
# acregmin=30
|
|
#
|
|
# The Maximum time (in seconds) file attributes are cached
|
|
-# acregmin=60
|
|
+# acregmax=60
|
|
#
|
|
# The minimum time (in seconds) directory attributes are cached
|
|
-# acregmin=30
|
|
+# acdirmin=30
|
|
#
|
|
# The Maximum time (in seconds) directory attributes are cached
|
|
-# acregmin=60
|
|
+# acdirmax=60
|
|
#
|
|
# Enable Access Control Lists
|
|
# Acl=False
|
|
diff --git a/utils/mount/parse_dev.c b/utils/mount/parse_dev.c
|
|
index 0d3bcb95..2ade5d5d 100644
|
|
--- a/utils/mount/parse_dev.c
|
|
+++ b/utils/mount/parse_dev.c
|
|
@@ -170,7 +170,8 @@ static int nfs_parse_square_bracket(const char *dev,
|
|
if (pathname) {
|
|
*pathname = strndup(cbrace, path_len);
|
|
if (*pathname == NULL) {
|
|
- free(*hostname);
|
|
+ if (hostname)
|
|
+ free(*hostname);
|
|
return nfs_pdn_nomem_err();
|
|
}
|
|
}
|
|
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
|
|
index 4016a761..249df00b 100644
|
|
--- a/utils/nfsd/nfsd.c
|
|
+++ b/utils/nfsd/nfsd.c
|
|
@@ -23,6 +23,7 @@
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
+#include <sched.h>
|
|
|
|
#include "conffile.h"
|
|
#include "nfslib.h"
|
|
@@ -39,6 +40,7 @@ static void usage(const char *);
|
|
static struct option longopts[] =
|
|
{
|
|
{ "host", 1, 0, 'H' },
|
|
+ { "scope", 1, 0, 'S'},
|
|
{ "help", 0, 0, 'h' },
|
|
{ "no-nfs-version", 1, 0, 'N' },
|
|
{ "nfs-version", 1, 0, 'V' },
|
|
@@ -69,6 +71,7 @@ main(int argc, char **argv)
|
|
int count = NFSD_NPROC, c, i, error = 0, portnum, fd, found_one;
|
|
char *p, *progname, *port, *rdma_port = NULL;
|
|
char **haddr = NULL;
|
|
+ char *scope = NULL;
|
|
int hcounter = 0;
|
|
struct conf_list *hosts;
|
|
int socket_up = 0;
|
|
@@ -168,8 +171,9 @@ main(int argc, char **argv)
|
|
hcounter++;
|
|
}
|
|
}
|
|
+ scope = conf_get_str("nfsd", "scope");
|
|
|
|
- while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:stTuUrG:L:", longopts, NULL)) != EOF) {
|
|
+ while ((c = getopt_long(argc, argv, "dH:S:hN:V:p:P:stTuUrG:L:", longopts, NULL)) != EOF) {
|
|
switch(c) {
|
|
case 'd':
|
|
xlog_config(D_ALL, 1);
|
|
@@ -190,6 +194,9 @@ main(int argc, char **argv)
|
|
haddr[hcounter] = optarg;
|
|
hcounter++;
|
|
break;
|
|
+ case 'S':
|
|
+ scope = optarg;
|
|
+ break;
|
|
case 'P': /* XXX for nfs-server compatibility */
|
|
case 'p':
|
|
/* only the last -p option has any effect */
|
|
@@ -367,6 +374,14 @@ main(int argc, char **argv)
|
|
if (lease > 0)
|
|
nfssvc_set_time("lease", lease);
|
|
|
|
+ if (scope) {
|
|
+ if (unshare(CLONE_NEWUTS) < 0 ||
|
|
+ sethostname(scope, strlen(scope)) < 0) {
|
|
+ xlog(L_ERROR, "Unable to set server scope: %m");
|
|
+ error = -1;
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
i = 0;
|
|
do {
|
|
error = nfssvc_set_sockets(protobits, haddr[i], port);
|
|
diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man
|
|
index 634b8a63..6f4fc1df 100644
|
|
--- a/utils/nfsd/nfsd.man
|
|
+++ b/utils/nfsd/nfsd.man
|
|
@@ -35,9 +35,17 @@ Note that
|
|
.B lockd
|
|
(which performs file locking services for NFS) may still accept
|
|
request on all known network addresses. This may change in future
|
|
-releases of the Linux Kernel. This option can be used multiple time
|
|
+releases of the Linux Kernel. This option can be used multiple times
|
|
to listen to more than one interface.
|
|
.TP
|
|
+.B \-S " or " \-\-scope scope
|
|
+NFSv4.1 and later require the server to report a "scope" which is used
|
|
+by the clients to detect if two connections are to the same server.
|
|
+By default Linux NFSD uses the host name as the scope.
|
|
+.sp
|
|
+It is particularly important for high-availablity configurations to ensure
|
|
+that all potential server nodes report the same server scope.
|
|
+.TP
|
|
.B \-p " or " \-\-port port
|
|
specify a different port to listen on for NFS requests. By default,
|
|
.B rpc.nfsd
|
|
@@ -134,6 +142,9 @@ will listen on. Use of the
|
|
.B --host
|
|
option replaces all host names listed here.
|
|
.TP
|
|
+.B scope
|
|
+Set the server scope.
|
|
+.TP
|
|
.B grace-time
|
|
The grace time, for both NFSv4 and NLM, in seconds.
|
|
.TP
|
|
@@ -159,7 +170,9 @@ Enable or disable TCP support.
|
|
.B vers3
|
|
.TP
|
|
.B vers4
|
|
-Enable or disable a major NFS version. 3 and 4 are normally enabled
|
|
+Enable or disable
|
|
+.B all
|
|
+NFSv4 versions. All versions are normally enabled
|
|
by default.
|
|
.TP
|
|
.B vers4.1
|