summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2017-04-04 17:57:26 -0400
committerSteve Dickson <steved@redhat.com>2017-04-05 13:27:57 -0400
commitd53fe5fe72d2b8d645ad362840da42021363384d (patch)
tree49c6aab2abbbf3e254de0e0a6c786c455ca40ad6
parentc9eab79f70e80df51829193858304a797621ecdd (diff)
downloadnfs-utils-d53fe5fe72d2b8d645ad362840da42021363384d.tar.gz
nfs-utils-d53fe5fe72d2b8d645ad362840da42021363384d.tar.xz
nfs-utils-d53fe5fe72d2b8d645ad362840da42021363384d.zip
nfsd: Allow the caller to turn off NFSv4.0 without turning off NFSv4.x
The new semantic is that '-N4' turns off all NFSv4 minor versions, while '-V4' turns them all on. In order to turn off just minor version x (x >= 0), use -N4.x, and to turn it back on. '-V4.x'. Note that on older kernels, attempting to use -N4.0 and -V4.0 is equivalent to specifying -N4 or -V4. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r--support/include/nfs/nfs.h7
-rw-r--r--utils/nfsd/nfsd.c39
-rw-r--r--utils/nfsd/nfsd.man4
-rw-r--r--utils/nfsd/nfssvc.c76
-rw-r--r--utils/nfsd/nfssvc.h1
5 files changed, 92 insertions, 35 deletions
diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h
index 15ecc6b..5860343 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;
@@ -29,15 +29,18 @@ struct nfs_fh_len {
#define NFSCTL_TCPBIT (1 << (18 - 1))
#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)
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
index 20f4b79..1708521 100644
--- a/utils/nfsd/nfsd.c
+++ b/utils/nfsd/nfsd.c
@@ -67,6 +67,7 @@ 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;
int grace = -1;
@@ -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);
}
}
@@ -179,13 +186,17 @@ 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;
}
case 3:
case 2:
@@ -201,14 +212,14 @@ 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;
case 3:
case 2:
NFSCTL_VERSET(versbits, c);
diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man
index 8901fb6..0d797fd 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,
@@ -82,7 +82,7 @@ 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);