NFSD_List,
        NFSD_Fh,
        NFSD_Threads,
+       NFSD_Pool_Threads,
        NFSD_Versions,
        NFSD_Ports,
        /*
 static ssize_t write_getfs(struct file *file, char *buf, size_t size);
 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 static ssize_t write_threads(struct file *file, char *buf, size_t size);
+static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
 static ssize_t write_versions(struct file *file, char *buf, size_t size);
 static ssize_t write_ports(struct file *file, char *buf, size_t size);
 #ifdef CONFIG_NFSD_V4
        [NFSD_Getfs] = write_getfs,
        [NFSD_Fh] = write_filehandle,
        [NFSD_Threads] = write_threads,
+       [NFSD_Pool_Threads] = write_pool_threads,
        [NFSD_Versions] = write_versions,
        [NFSD_Ports] = write_ports,
 #ifdef CONFIG_NFSD_V4
        return strlen(buf);
 }
 
+extern int nfsd_nrpools(void);
+extern int nfsd_get_nrthreads(int n, int *);
+extern int nfsd_set_nrthreads(int n, int *);
+
+static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
+{
+       /* if size > 0, look for an array of number of threads per node
+        * and apply them  then write out number of threads per node as reply
+        */
+       char *mesg = buf;
+       int i;
+       int rv;
+       int len;
+       int npools = nfsd_nrpools();
+       int *nthreads;
+
+       if (npools == 0) {
+               /*
+                * NFS is shut down.  The admin can start it by
+                * writing to the threads file but NOT the pool_threads
+                * file, sorry.  Report zero threads.
+                */
+               strcpy(buf, "0\n");
+               return strlen(buf);
+       }
+
+       nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
+       if (nthreads == NULL)
+               return -ENOMEM;
+
+       if (size > 0) {
+               for (i = 0; i < npools; i++) {
+                       rv = get_int(&mesg, &nthreads[i]);
+                       if (rv == -ENOENT)
+                               break;          /* fewer numbers than pools */
+                       if (rv)
+                               goto out_free;  /* syntax error */
+                       rv = -EINVAL;
+                       if (nthreads[i] < 0)
+                               goto out_free;
+               }
+               rv = nfsd_set_nrthreads(i, nthreads);
+               if (rv)
+                       goto out_free;
+       }
+
+       rv = nfsd_get_nrthreads(npools, nthreads);
+       if (rv)
+               goto out_free;
+
+       mesg = buf;
+       size = SIMPLE_TRANSACTION_LIMIT;
+       for (i = 0; i < npools && size > 0; i++) {
+               snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
+               len = strlen(mesg);
+               size -= len;
+               mesg += len;
+       }
+
+       return (mesg-buf);
+
+out_free:
+       kfree(nthreads);
+       return rv;
+}
+
 static ssize_t write_versions(struct file *file, char *buf, size_t size)
 {
        /*
                [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
                [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
+               [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
 #ifdef CONFIG_NFSD_V4
 
        return 0;
 }
 
+int nfsd_nrpools(void)
+{
+       if (nfsd_serv == NULL)
+               return 0;
+       else
+               return nfsd_serv->sv_nrpools;
+}
+
+int nfsd_get_nrthreads(int n, int *nthreads)
+{
+       int i = 0;
+
+       if (nfsd_serv != NULL) {
+               for (i = 0; i < nfsd_serv->sv_nrpools && i < n; i++)
+                       nthreads[i] = nfsd_serv->sv_pools[i].sp_nrthreads;
+       }
+
+       return 0;
+}
+
+int nfsd_set_nrthreads(int n, int *nthreads)
+{
+       int i = 0;
+       int tot = 0;
+       int err = 0;
+
+       if (nfsd_serv == NULL || n <= 0)
+               return 0;
+
+       if (n > nfsd_serv->sv_nrpools)
+               n = nfsd_serv->sv_nrpools;
+
+       /* enforce a global maximum number of threads */
+       tot = 0;
+       for (i = 0; i < n; i++) {
+               if (nthreads[i] > NFSD_MAXSERVS)
+                       nthreads[i] = NFSD_MAXSERVS;
+               tot += nthreads[i];
+       }
+       if (tot > NFSD_MAXSERVS) {
+               /* total too large: scale down requested numbers */
+               for (i = 0; i < n && tot > 0; i++) {
+                       int new = nthreads[i] * NFSD_MAXSERVS / tot;
+                       tot -= (nthreads[i] - new);
+                       nthreads[i] = new;
+               }
+               for (i = 0; i < n && tot > 0; i++) {
+                       nthreads[i]--;
+                       tot--;
+               }
+       }
+
+       /*
+        * There must always be a thread in pool 0; the admin
+        * can't shut down NFS completely using pool_threads.
+        */
+       if (nthreads[0] == 0)
+               nthreads[0] = 1;
+
+       /* apply the new numbers */
+       lock_kernel();
+       svc_get(nfsd_serv);
+       for (i = 0; i < n; i++) {
+               err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i],
+                                         nthreads[i]);
+               if (err)
+                       break;
+       }
+       svc_destroy(nfsd_serv);
+       unlock_kernel();
+
+       return err;
+}
+
 int
 nfsd_svc(unsigned short port, int nrservs)
 {