Author: alfred
Date: Tue Nov 27 22:34:46 2012
New Revision: 243637
URL: http://svnweb.freebsd.org/changeset/base/243637

Log:
  Autoconfigure nfsd threads based on ncpu.
  
  Rick Macklem and I discussed the default number of nfsd threads and
  concluded that it is too low to perform adiquitely on today's hardware.
  
  We decided to auto tune the number of nfsds based on the number of cpus
  in the system.
  
  While I'm here I've also added:
  
  1) ability to set the minthreads/maxthreads from userland.
  2) ability to run nfsd in debug mode via the cli.
  
  Reviewed by: rmacklem
  MFC after: 2 weeks

Modified:
  head/usr.sbin/nfsd/nfsd.c

Modified: head/usr.sbin/nfsd/nfsd.c
==============================================================================
--- head/usr.sbin/nfsd/nfsd.c   Tue Nov 27 22:14:22 2012        (r243636)
+++ head/usr.sbin/nfsd/nfsd.c   Tue Nov 27 22:34:46 2012        (r243637)
@@ -53,6 +53,7 @@ static const char rcsid[] =
 #include <sys/module.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/sysctl.h>
 #include <sys/ucred.h>
 
 #include <rpc/rpc.h>
@@ -71,14 +72,11 @@ static const char rcsid[] =
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sysexits.h>
+
+#include <getopt.h>
 
-/* Global defs */
-#ifdef DEBUG
-#define        syslog(e, s...) fprintf(stderr,s)
-static int     debug = 1;
-#else
 static int     debug = 0;
-#endif
 
 #define        NFSD_STABLERESTART      "/var/db/nfs-stablerestart"
 #define        NFSD_STABLEBACKUP       "/var/db/nfs-stablerestart.bak"
@@ -86,11 +84,26 @@ static int  debug = 0;
 #define        DEFNFSDCNT       4
 static pid_t children[MAXNFSDCNT]; /* PIDs of children */
 static int nfsdcnt;            /* number of children */
+static int nfsdcnt_set;
+static int minthreads;
+static int maxthreads;
 static int new_syscall;
 static int run_v4server = 1;   /* Force running of nfsv4 server */
 static int nfssvc_nfsd;                /* Set to correct NFSSVC_xxx flag */
 static int stablefd = -1;      /* Fd for the stable restart file */
 static int backupfd;           /* Fd for the backup stable restart file */
+static const char *getopt_shortopts;
+static const char *getopt_usage;
+
+static int minthreads_set;
+static int maxthreads_set;
+
+static struct option longopts[] = {
+       { "debug", no_argument, &debug, 1 },
+       { "minthreads", required_argument, &minthreads_set, 1 },
+       { "maxthreads", required_argument, &maxthreads_set, 1 },
+       { NULL, 0, NULL, 0}
+};
 
 void   cleanup(int);
 void   child_cleanup(int);
@@ -145,26 +158,28 @@ main(int argc, char **argv)
        int udpflag, ecode, error, s, srvcnt;
        int bindhostc, bindanyflag, rpcbreg, rpcbregcnt;
        int nfssvc_addsock;
+       int longindex = 0;
+       const char *lopt;
        char **bindhost = NULL;
        pid_t pid;
 
        nfsdcnt = DEFNFSDCNT;
        unregister = reregister = tcpflag = maxsock = 0;
        bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
-#define        GETOPT  "ah:n:rdtueo"
-#define        USAGE   "[-ardtueo] [-n num_servers] [-h bindip]"
-       while ((ch = getopt(argc, argv, GETOPT)) != -1)
+       getopt_shortopts = "ah:n:rdtueo";
+       getopt_usage =
+           "usage:\n"
+           "  nfsd [-ardtueo] [-h bindip]\n"
+           "       [-n numservers] [--minthreads #] [--maxthreads #]\n";
+       while ((ch = getopt_long(argc, argv, getopt_shortopts, longopts,
+                   &longindex)) != -1)
                switch (ch) {
                case 'a':
                        bindanyflag = 1;
                        break;
                case 'n':
+                       nfsdcnt_set = 1;
                        nfsdcnt = atoi(optarg);
-                       if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
-                               warnx("nfsd count %d; reset to %d", nfsdcnt,
-                                   DEFNFSDCNT);
-                               nfsdcnt = DEFNFSDCNT;
-                       }
                        break;
                case 'h':
                        bindhostc++;
@@ -193,6 +208,14 @@ main(int argc, char **argv)
                case 'o':
                        run_v4server = 0;
                        break;
+               case 0:
+                       lopt = longopts[longindex].name;
+                       if (!strcmp(lopt, "minthreads")) {
+                               minthreads = atoi(optarg);
+                       } else if (!strcmp(lopt, "maxthreads")) {
+                               maxthreads = atoi(optarg);
+                       }
+                       break;
                default:
                case '?':
                        usage();
@@ -209,6 +232,7 @@ main(int argc, char **argv)
        if (argc > 1)
                usage();
        if (argc == 1) {
+               nfsdcnt_set = 1;
                nfsdcnt = atoi(argv[0]);
                if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
                        warnx("nfsd count %d; reset to %d", nfsdcnt,
@@ -356,7 +380,7 @@ main(int argc, char **argv)
        (void)signal(SIGCHLD, reapchild);
        (void)signal(SIGUSR2, backup_stable);
 
-       openlog("nfsd", LOG_PID, LOG_DAEMON);
+       openlog("nfsd", LOG_PID | (debug ? LOG_PERROR : 0), LOG_DAEMON);
 
        /*
         * For V4, we open the stablerestart file and call nfssvc()
@@ -374,13 +398,13 @@ main(int argc, char **argv)
        if (run_v4server > 0) {
                open_stable(&stablefd, &backupfd);
                if (stablefd < 0) {
-                       syslog(LOG_ERR, "Can't open %s\n", NFSD_STABLERESTART);
+                       syslog(LOG_ERR, "Can't open %s: %m\n", 
NFSD_STABLERESTART);
                        exit(1);
                }
                /* This system call will fail for old kernels, but that's ok. */
                nfssvc(NFSSVC_BACKUPSTABLE, NULL);
                if (nfssvc(NFSSVC_STABLERESTART, (caddr_t)&stablefd) < 0) {
-                       syslog(LOG_ERR, "Can't read stable storage file\n");
+                       syslog(LOG_ERR, "Can't read stable storage file: %m\n");
                        exit(1);
                }
                nfssvc_addsock = NFSSVC_NFSDADDSOCK;
@@ -401,6 +425,16 @@ main(int argc, char **argv)
        }
 
        if (!new_syscall) {
+               if (nfsdcnt < 1) {
+                       warnx("nfsd count too low %d; reset to %d", nfsdcnt,
+                           DEFNFSDCNT);
+                       nfsdcnt = DEFNFSDCNT;
+               }
+               if (nfsdcnt > MAXNFSDCNT) {
+                       warnx("nfsd counta too high %d; reset to %d", nfsdcnt,
+                           DEFNFSDCNT);
+                       nfsdcnt = MAXNFSDCNT;
+               }
                /* If we use UDP only, we start the last server below. */
                srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1;
                for (i = 0; i < srvcnt; i++) {
@@ -855,7 +889,7 @@ setbindhost(struct addrinfo **ai, const 
 void
 usage(void)
 {
-       (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
+       (void)fprintf(stderr, "%s", getopt_usage);
        exit(1);
 }
 
@@ -923,6 +957,29 @@ nfsd_exit(int status)
        exit(status);
 }
 
+static int
+get_tuned_nfsdcount(void)
+{
+       int ncpu, error, tuned_nfsdcnt;
+       size_t ncpu_size;
+
+       ncpu_size = sizeof(ncpu);
+       error = sysctlbyname("hw.ncpu", &ncpu, &ncpu_size, NULL, 0);
+       if (error) {
+               warnx("sysctlbyname(hw.ncpu) failed defaulting to %d nfs 
servers",
+                   DEFNFSDCNT);
+               tuned_nfsdcnt = DEFNFSDCNT;
+       } else {
+               tuned_nfsdcnt = ncpu * 8;
+       }
+       if (!new_syscall && tuned_nfsdcnt > MAXNFSDCNT) {
+               warnx("nfsd count %d; truncated to %d", tuned_nfsdcnt,
+                   MAXNFSDCNT);
+               tuned_nfsdcnt = MAXNFSDCNT;
+       }
+       return tuned_nfsdcnt;
+}
+
 void
 start_server(int master)
 {
@@ -952,8 +1009,28 @@ start_server(int master)
                        }
                }
                nfsdargs.principal = principal;
-               nfsdargs.minthreads = nfsdcnt;
-               nfsdargs.maxthreads = nfsdcnt;
+
+               if (minthreads_set) {
+                       nfsdargs.minthreads = minthreads;
+                       if (!maxthreads_set)
+                               nfsdargs.maxthreads = minthreads;
+               }
+               if (maxthreads_set) {
+                       nfsdargs.maxthreads = maxthreads;
+                       if (!minthreads_set)
+                               nfsdargs.minthreads = maxthreads;
+               }
+               if (nfsdcnt_set) {
+                       nfsdargs.minthreads = nfsdcnt;
+                       nfsdargs.maxthreads = nfsdcnt;
+               }
+               if (!minthreads_set && !maxthreads_set && !nfsdcnt_set) {
+                       int tuned_nfsdcnt;
+
+                       tuned_nfsdcnt = get_tuned_nfsdcount();
+                       nfsdargs.minthreads = tuned_nfsdcnt;
+                       nfsdargs.maxthreads = tuned_nfsdcnt;
+               }
                error = nfssvc(nfssvc_nfsd, &nfsdargs);
                if (error < 0 && errno == EAUTH) {
                        /*
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to