Add support for suppressing different NFS versions.
authorSteve Dickson <SteveD@redhat.com>
Mon, 26 Jun 2006 05:23:19 +0000 (15:23 +1000)
committerNeil Brown <neilb@suse.de>
Mon, 26 Jun 2006 05:23:19 +0000 (15:23 +1000)
e.g.  -N 2
means that NFSv2 won't be supported, just v3 and v4 (if the kernel
supports them).

support/include/nfs/nfs.h
support/include/nfslib.h
support/nfs/nfssvc.c
utils/nfsd/nfsd.c
utils/nfsd/nfsd.man

index c7fc42c..2cf6857 100644 (file)
@@ -10,6 +10,9 @@
 #define        NFS3_FHSIZE     64
 #define        NFS_FHSIZE      32
 
+#define NFSD_MINVERS 2
+#define NFSD_MAXVERS 4
+
 struct nfs_fh_len {
        int             fh_size;
        u_int8_t        fh_handle[NFS3_FHSIZE];
@@ -40,7 +43,11 @@ struct nfs_fh_old {
 #define NFSCTL_LOCKD           0x10000
 #define LOCKDCTL_SVC           NFSCTL_LOCKD
 
+#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << ((_v) - 1))) 
+
+#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << ((_v) - 1))) 
 
+#define NFSCTL_ALLBITS (~0)
 
 /* SVC */
 struct nfsctl_svc {
index 8c83262..50892e2 100644 (file)
@@ -120,7 +120,7 @@ int                 wildmat(char *text, char *pattern);
  * nfsd library functions.
  */
 int                    nfsctl(int, struct nfsctl_arg *, union nfsctl_res *);
-int                    nfssvc(int port, int nrservs);
+int                    nfssvc(int port, int nrservs, unsigned int versbits);
 int                    nfsaddclient(struct nfsctl_client *clp);
 int                    nfsdelclient(struct nfsctl_client *clp);
 int                    nfsexport(struct nfsctl_export *exp);
index 38240a0..c51ace1 100644 (file)
 
 #include <unistd.h>
 #include <fcntl.h>
+#include <errno.h>
+#include <syslog.h>
 
 #include "nfslib.h"
 
+static void
+nfssvc_versbits(unsigned int ctlbits)
+{
+       int fd, n, off;
+       char buf[BUFSIZ], *ptr;
+
+       ptr = buf;
+       off = 0;
+       fd = open("/proc/fs/nfsd/versions", O_WRONLY);
+       if (fd < 0)
+               return;
+
+       for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) {
+               if (NFSCTL_VERISSET(ctlbits, n))
+                   off += snprintf(ptr+off, BUFSIZ - off, "+%d ", n);
+               else
+                   off += snprintf(ptr+off, BUFSIZ - off, "-%d ", n);
+       }
+       snprintf(ptr+off, BUFSIZ - off, "\n");
+       if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+               syslog(LOG_ERR, "nfssvc: Setting version failed: errno %d (%s)", 
+                       errno, strerror(errno));
+       }
+       close(fd);
+
+       return;
+}
 int
-nfssvc(int port, int nrservs)
+nfssvc(int port, int nrservs, unsigned int versbits)
 {
        struct nfsctl_arg       arg;
        int fd;
 
+       nfssvc_versbits(versbits);
+
        fd = open("/proc/fs/nfsd/threads", O_WRONLY);
        if (fd < 0)
                fd = open("/proc/fs/nfs/threads", O_WRONLY);
index 05506ee..fa6ee71 100644 (file)
 
 static void    usage(const char *);
 
+static struct option longopts[] =
+{
+       { "help", 0, 0, 'h' },
+       { "no-nfs-version", 1, 0, 'N' },
+       { NULL, 0, 0, 0 }
+};
+unsigned int versbits = NFSCTL_ALLBITS;
+
 int
 main(int argc, char **argv)
 {
-       int     count = 1, c, error, port, fd;
+       int     count = 1, c, error, port, fd, found_one;
        struct servent *ent;
 
        ent = getservbyname ("nfs", "udp");
@@ -36,7 +44,7 @@ main(int argc, char **argv)
        else
                port = 2049;
 
-       while ((c = getopt(argc, argv, "hp:P:")) != EOF) {
+       while ((c = getopt_long(argc, argv, "hN:p:P:", longopts, NULL)) != EOF) {
                switch(c) {
                case 'P':       /* XXX for nfs-server compatibility */
                case 'p':
@@ -47,12 +55,36 @@ main(int argc, char **argv)
                                usage(argv [0]);
                        }
                        break;
+               case 'N':
+                       switch((c = atoi(optarg))) {
+                       case 2:
+                       case 3:
+                       case 4:
+                               NFSCTL_VERUNSET(versbits, c);
+                               break;
+                       default:
+                               fprintf(stderr, "%c: Unsupported version\n", c);
+                               exit(1);
+                       }
                        break;
-               case 'h':
                default:
+                       fprintf(stderr, "Invalid argument: '%c'\n", c);
+               case 'h':
                        usage(argv[0]);
                }
        }
+       /*
+        * Do some sanity checking, if the ctlbits are set
+        */
+       found_one = 0;
+       for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
+               if (NFSCTL_VERISSET(versbits, c))
+                       found_one = 1;
+       }
+       if (!found_one) {
+               fprintf(stderr, "no version specified\n");
+               exit(1);
+       }                       
 
        if (chdir(NFS_STATEDIR)) {
                fprintf(stderr, "%s: chdir(%s) failed: %s\n",
@@ -69,7 +101,6 @@ main(int argc, char **argv)
                        count = 1;
                }
        }
-
        /* KLUDGE ALERT:
           Some kernels let nfsd kernel threads inherit open files
           from the program that spawns them (i.e. us).  So close
@@ -84,9 +115,9 @@ main(int argc, char **argv)
        }
        closeall(3);
 
-       if ((error = nfssvc(port, count)) < 0) {
+       openlog("nfsd", LOG_PID, LOG_DAEMON);
+       if ((error = nfssvc(port, count, versbits)) < 0) {
                int e = errno;
-               openlog("nfsd", LOG_PID, LOG_DAEMON);
                syslog(LOG_ERR, "nfssvc: %s", strerror(e));
                closelog();
        }
@@ -97,7 +128,8 @@ main(int argc, char **argv)
 static void
 usage(const char *prog)
 {
-       fprintf(stderr, "usage:\n"
-                       "%s nrservs\n", prog);
+       fprintf(stderr, "Usage:\n"
+               "%s [-p|-P|--port port] [-N|--no-nfs-version version ] nrservs\n", 
+               prog);
        exit(2);
 }
index a890ea6..d175d11 100644 (file)
@@ -6,7 +6,7 @@
 .SH NAME
 rpc.nfsd \- NFS server process
 .SH SYNOPSIS
-.BI "/usr/sbin/rpc.nfsd [-p " port "] " nproc
+.BI "/usr/sbin/rpc.nfsd [" options "]" " "nproc
 .SH DESCRIPTION
 The
 .B rpc.nfsd
@@ -22,11 +22,18 @@ server provides an ancillary service needed to satisfy mount requests
 by NFS clients.
 .SH OPTIONS
 .TP
-.BI \-p " port"
+.B \-p " or " \-\-port  port
 specify a diferent port to listen on for NFS requests. By default,
 .B rpc.nfsd
 will listen on port 2049.
 .TP
+.B \-N " or " \-\-no-nfs-version vers
+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 both NFS version 2,3 and the newer version 4.
+.TP
 .I nproc
 specify the number of NFS server threads. By default, just one
 thread is started. However, for optimum performance several threads