[PATCH] knfsd: remove nfsd_versbits as intermediate storage for desired versions
authorNeilBrown <neilb@suse.de>
Mon, 2 Oct 2006 09:17:46 +0000 (02:17 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 2 Oct 2006 14:57:17 +0000 (07:57 -0700)
We have an array 'nfsd_version' which lists the available versions of nfsd,
and 'nfsd_versions' (poor choice there :-() which lists the currently active
versions.

Then we have a bitmap - nfsd_versbits which says which versions are wanted.
The bits in this bitset cause content to be copied from nfsd_version to
nfsd_versions when nfsd starts.

This patch removes nfsd_versbits and moves information directly from
nfsd_version to nfsd_versions when requests for version changes arrive.

Note that this doesn't make it possible to change versions while the server is
running.  This is because serv->sv_xdrsize is calculated when a service is
created, and used when threads are created, and xdrsize depends on the active
versions.

Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/nfsd/nfsctl.c
fs/nfsd/nfssvc.c
include/linux/nfsd/nfsd.h
include/linux/nfsd/syscall.h

index 7046ac9cf97fa14e50743ed1cc4655d4b4ec26f7..d6881774ea5758ed1bb9b635aaa823741c046c40 100644 (file)
@@ -35,8 +35,6 @@
 
 #include <asm/uaccess.h>
 
-unsigned int nfsd_versbits = ~0;
-
 /*
  *     We have a single directory with 9 nodes in it.
  */
@@ -372,6 +370,10 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
 
        if (size>0) {
                if (nfsd_serv)
+                       /* Cannot change versions without updating
+                        * nfsd_serv->sv_xdrsize, and reallocing
+                        * rq_argp and rq_resp
+                        */
                        return -EBUSY;
                if (buf[size-1] != '\n')
                        return -EINVAL;
@@ -390,10 +392,7 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
                        case 2:
                        case 3:
                        case 4:
-                               if (sign != '-')
-                                       NFSCTL_VERSET(nfsd_versbits, num);
-                               else
-                                       NFSCTL_VERUNSET(nfsd_versbits, num);
+                               nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
                                break;
                        default:
                                return -EINVAL;
@@ -404,16 +403,15 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
                /* If all get turned off, turn them back on, as
                 * having no versions is BAD
                 */
-               if ((nfsd_versbits & NFSCTL_VERALL)==0)
-                       nfsd_versbits = NFSCTL_VERALL;
+               nfsd_reset_versions();
        }
        /* Now write current state into reply buffer */
        len = 0;
        sep = "";
        for (num=2 ; num <= 4 ; num++)
-               if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) {
+               if (nfsd_vers(num, NFSD_AVAIL)) {
                        len += sprintf(buf+len, "%s%c%d", sep,
-                                      NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-',
+                                      nfsd_vers(num, NFSD_TEST)?'+':'-',
                                       num);
                        sep = " ";
                }
index 0339b4ddfa3bc2a0fc425c301cc223073e9499cf..140e3a2d1b9f89a0d5f7bbf58b56287c028def82 100644 (file)
@@ -117,6 +117,32 @@ struct svc_program         nfsd_program = {
 
 };
 
+int nfsd_vers(int vers, enum vers_op change)
+{
+       if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
+               return -1;
+       switch(change) {
+       case NFSD_SET:
+               nfsd_versions[vers] = nfsd_version[vers];
+               break;
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+               if (vers < NFSD_ACL_NRVERS)
+                       nfsd_acl_version[vers] = nfsd_acl_version[vers];
+#endif
+       case NFSD_CLEAR:
+               nfsd_versions[vers] = NULL;
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+               if (vers < NFSD_ACL_NRVERS)
+                       nfsd_acl_version[vers] = NULL;
+#endif
+               break;
+       case NFSD_TEST:
+               return nfsd_versions[vers] != NULL;
+       case NFSD_AVAIL:
+               return nfsd_version[vers] != NULL;
+       }
+       return 0;
+}
 /*
  * Maximum number of nfsd processes
  */
@@ -147,16 +173,36 @@ static void nfsd_last_thread(struct svc_serv *serv)
                nfsd_export_flush();
        }
 }
+
+void nfsd_reset_versions(void)
+{
+       int found_one = 0;
+       int i;
+
+       for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
+               if (nfsd_program.pg_vers[i])
+                       found_one = 1;
+       }
+
+       if (!found_one) {
+               for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
+                       nfsd_program.pg_vers[i] = nfsd_version[i];
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+               for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
+                       nfsd_acl_program.pg_vers[i] =
+                               nfsd_acl_version[i];
+#endif
+       }
+}
+
 int
 nfsd_svc(unsigned short port, int nrservs)
 {
        int     error;
-       int     found_one, i;
        struct list_head *victim;
        
        lock_kernel();
-       dprintk("nfsd: creating service: vers 0x%x\n",
-               nfsd_versbits);
+       dprintk("nfsd: creating service\n");
        error = -EINVAL;
        if (nrservs <= 0)
                nrservs = 0;
@@ -171,46 +217,7 @@ nfsd_svc(unsigned short port, int nrservs)
        if (error<0)
                goto out;
        if (!nfsd_serv) {
-               /*
-                * Use the nfsd_ctlbits to define which
-                * versions that will be advertised.
-                * If nfsd_ctlbits doesn't list any version,
-                * export them all.
-                */
-               found_one = 0;
-
-               for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
-                       if (NFSCTL_VERISSET(nfsd_versbits, i)) {
-                               nfsd_program.pg_vers[i] = nfsd_version[i];
-                               found_one = 1;
-                       } else
-                               nfsd_program.pg_vers[i] = NULL;
-               }
-
-               if (!found_one) {
-                       for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
-                               nfsd_program.pg_vers[i] = nfsd_version[i];
-               }
-
-
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-               found_one = 0;
-
-               for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
-                       if (NFSCTL_VERISSET(nfsd_versbits, i)) {
-                               nfsd_acl_program.pg_vers[i] =
-                                       nfsd_acl_version[i];
-                               found_one = 1;
-                       } else
-                               nfsd_acl_program.pg_vers[i] = NULL;
-               }
-
-               if (!found_one) {
-                       for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
-                               nfsd_acl_program.pg_vers[i] =
-                                       nfsd_acl_version[i];
-               }
-#endif
+               nfsd_reset_versions();
 
                atomic_set(&nfsd_busy, 0);
                error = -ENOMEM;
index 2dcad295fecef2685ffb4121d4ea977cc6b8c279..46f1dc5b96dd215cc5f3ff9bdb2b5069397c4611 100644 (file)
@@ -140,6 +140,10 @@ struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
 int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
 #endif
 
+enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
+int nfsd_vers(int vers, enum vers_op change);
+void nfsd_reset_versions(void);
+
 
 /* 
  * NFSv4 State
index dae0faea28070a594c49d886458e1ebc4934a477..8bcddccb6c427e81a7a7b960d1f25afaa1bb9b6f 100644 (file)
 #define NFSCTL_GETFD           7       /* get an fh by path (used by mountd) */
 #define        NFSCTL_GETFS            8       /* get an fh by path with max FH len */
 
-/*
- * Macros used to set version
- */
-#define NFSCTL_VERSET(_cltbits, _v)   ((_cltbits) |=  (1 << (_v)))
-#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v)))
-#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v)))
-
-#if defined(CONFIG_NFSD_V4)
-#define        NFSCTL_VERALL   (0x1c /* 0b011100 */)
-#elif defined(CONFIG_NFSD_V3)
-#define        NFSCTL_VERALL   (0x0c /* 0b001100 */)
-#else
-#define        NFSCTL_VERALL   (0x04 /* 0b000100 */)
-#endif
-
 /* SVC */
 struct nfsctl_svc {
        unsigned short          svc_port;
@@ -134,8 +119,6 @@ extern int          exp_delclient(struct nfsctl_client *ncp);
 extern int             exp_export(struct nfsctl_export *nxp);
 extern int             exp_unexport(struct nfsctl_export *nxp);
 
-extern unsigned int nfsd_versbits;
-
 #endif /* __KERNEL__ */
 
 #endif /* NFSD_SYSCALL_H */