Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/tests/fs/common Add NFS to the list of file systems exercise...



details:   https://anonhg.NetBSD.org/src/rev/cb909e2bd142
branches:  trunk
changeset: 756623:cb909e2bd142
user:      pooka <pooka%NetBSD.org@localhost>
date:      Mon Jul 26 16:15:49 2010 +0000

description:
Add NFS to the list of file systems exercised by the "vfs" tests.

How it works:
NFS tests fork and exec the nfs service from fs/nfs/nfsservice.
The child then:
  a) creates a FFS file system
  b) mounts it
  c) starts rpcbind
  d) starts mountd
  e) starts nfsd
  f) handles requests

The client, as expected, does the standard RPC regotiation and
calls mount(MOUNT_NFS).  It then proceeds to execute the test.

An individual test which executes everything described above and
does a few file operations on the NFS mount takes 0.16s wall time
on my laptop from start to finish.  This means it is feasible to
run hundreds of tests while still getting results in a timely
fashion.

Like in other networked tests, the two processes are connected via
the rump shmif which uses mmapped files as ethernet busses.  The
entire test suite can be executed by an unprivileged account.

As a side effect, these tests exercise also the kernel NFS server
in addition to the kernel NFS client.

While everything is currently targetted at executing the vfs tests,
there is no reason this could not be extended to exercise features
specific to NFS.  For example, the server can run through all
exportable file system types, permissions can be tested, etc.

diffstat:

 tests/fs/common/Makefile     |   17 ++-
 tests/fs/common/h_fsmacros.h |    7 +-
 tests/fs/common/nfs.c        |  225 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 246 insertions(+), 3 deletions(-)

diffs (299 lines):

diff -r 4a07784af24f -r cb909e2bd142 tests/fs/common/Makefile
--- a/tests/fs/common/Makefile  Mon Jul 26 15:56:45 2010 +0000
+++ b/tests/fs/common/Makefile  Mon Jul 26 16:15:49 2010 +0000
@@ -1,9 +1,22 @@
-#      $NetBSD: Makefile,v 1.1 2010/07/19 16:09:08 pooka Exp $
+#      $NetBSD: Makefile,v 1.2 2010/07/26 16:15:49 pooka Exp $
 #
 
+.include <bsd.own.mk>
+
 LIB=   vfstest
-SRCS=  ext2fs.c ffs.c lfs.c msdosfs.c puffs.c sysvbfs.c tmpfs.c
+SRCS=  ext2fs.c ffs.c lfs.c msdosfs.c nfs.c puffs.c sysvbfs.c tmpfs.c
+
+WARNS= 3
+
+.include "nfsrpc/Makefile.inc"
 
 LIBISPRIVATE=  # yup
 
+# NFS client stuff
+.PATH: ${NETBSDSRCDIR}/sbin/mount_nfs ${NETBSDSRCDIR}/sbin/mount
+SRCS+= getnfsargs.c pathadj.c fattr.c mount_nfs.c
+
+CPPFLAGS+=     -I${NETBSDSRCDIR}/sbin/mount_nfs -I${NETBSDSRCDIR}/sbin/mount
+CPPFLAGS+=     -DMOUNT_NOMAIN -DMOUNTNFS_RETRYRPC=1
+
 .include <bsd.lib.mk>
diff -r 4a07784af24f -r cb909e2bd142 tests/fs/common/h_fsmacros.h
--- a/tests/fs/common/h_fsmacros.h      Mon Jul 26 15:56:45 2010 +0000
+++ b/tests/fs/common/h_fsmacros.h      Mon Jul 26 16:15:49 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: h_fsmacros.h,v 1.13 2010/07/20 17:44:01 njoly Exp $    */
+/*     $NetBSD: h_fsmacros.h,v 1.14 2010/07/26 16:15:49 pooka Exp $    */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -47,6 +47,7 @@
 FSPROTOS(ffs);
 FSPROTOS(lfs);
 FSPROTOS(msdosfs);
+FSPROTOS(nfs);
 FSPROTOS(puffs);
 FSPROTOS(sysvbfs);
 FSPROTOS(tmpfs);
@@ -92,6 +93,7 @@
   ATF_TC_FSADD(ffs,MOUNT_FFS,func,desc) \
   ATF_TC_FSADD(lfs,MOUNT_LFS,func,desc) \
   ATF_TC_FSADD(msdosfs,MOUNT_MSDOS,func,desc) \
+  ATF_TC_FSADD(nfs,MOUNT_NFS,func,desc) \
   ATF_TC_FSADD(puffs,MOUNT_PUFFS,func,desc) \
   ATF_TC_FSADD(sysvbfs,MOUNT_SYSVBFS,func,desc) \
   ATF_TC_FSADD(tmpfs,MOUNT_TMPFS,func,desc)
@@ -101,6 +103,7 @@
   ATF_TP_FSADD(ffs,func); \
   ATF_TP_FSADD(lfs,func); \
   ATF_TP_FSADD(msdosfs,func); \
+  ATF_TP_FSADD(nfs,func); \
   ATF_TP_FSADD(puffs,func); \
   ATF_TP_FSADD(sysvbfs,func); \
   ATF_TP_FSADD(tmpfs,func);
@@ -134,6 +137,8 @@
     (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), MOUNT_LFS) == 0)
 #define FSTYPE_MSDOS(tc)\
     (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), MOUNT_MSDOS) == 0)
+#define FSTYPE_NFS(tc)\
+    (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), MOUNT_NFS) == 0)
 #define FSTYPE_PUFFS(tc)\
     (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), MOUNT_PUFFS) == 0)
 #define FSTYPE_SYSVBFS(tc)\
diff -r 4a07784af24f -r cb909e2bd142 tests/fs/common/nfs.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/fs/common/nfs.c     Mon Jul 26 16:15:49 2010 +0000
@@ -0,0 +1,225 @@
+/*     $NetBSD: nfs.c,v 1.1 2010/07/26 16:15:49 pooka Exp $    */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/statvfs.h>
+#include <sys/wait.h>
+
+#include <assert.h>
+#include <atf-c.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <pthread.h>
+#include <puffs.h>
+#include <puffsdump.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <rump/rump.h>
+#include <rump/rump_syscalls.h>
+
+#include "h_fsmacros.h"
+#include "mount_nfs.h"
+#include "../../net/config/netconfig.c"
+
+#define SERVERADDR "10.3.2.1"
+#define CLIENTADDR "10.3.2.2"
+#define NETNETMASK "255.255.255.0"
+#define EXPORTPATH "/myexport"
+
+struct nfstestargs {
+       pid_t ta_childpid;
+       char ta_ethername[MAXPATHLEN];
+};
+
+static void
+childfail(int status)
+{
+
+       atf_tc_fail("child died");
+}
+
+struct nfstestargs *theargs;
+
+/* fork rump nfsd, configure interface */
+int
+nfs_fstest_newfs(const atf_tc_t *tc, void **argp,
+       const char *image, off_t size)
+{
+       const char *srcdir;
+       char *nfsdargv[7];
+       char nfsdpath[MAXPATHLEN];
+       char ethername[MAXPATHLEN];
+       char imagepath[MAXPATHLEN];
+       char ifname[IFNAMSIZ];
+       char cwd[MAXPATHLEN];
+       struct nfstestargs *args;
+       pid_t childpid;
+       int pipes[2];
+       int devnull;
+
+       /*
+        * First, we start the nfs service.
+        */
+       srcdir = atf_tc_get_config_var(tc, "srcdir");
+       sprintf(nfsdpath, "%s/../nfs/nfsservice/rumpnfsd", srcdir);
+       sprintf(ethername, "/%s/%s.etherbus", getcwd(cwd, sizeof(cwd)), image);
+       sprintf(imagepath, "/%s/%s", cwd, image);
+
+       nfsdargv[0] = nfsdpath;
+       nfsdargv[1] = ethername;
+       nfsdargv[2] = __UNCONST(SERVERADDR);
+       nfsdargv[3] = __UNCONST(NETNETMASK);
+       nfsdargv[4] = __UNCONST(EXPORTPATH);
+       nfsdargv[5] = imagepath;
+       nfsdargv[6] = NULL;
+
+       signal(SIGCHLD, childfail);
+       if (pipe(pipes) == -1)
+               return errno;
+
+       switch ((childpid = fork())) {
+       case 0:
+               if (chdir(dirname(nfsdpath)) == -1)
+                       err(1, "chdir");
+               close(pipes[0]);
+               if (dup2(pipes[1], 3) == -1)
+                       err(1, "dup2");
+               if (execvp(nfsdargv[0], nfsdargv) == -1)
+                       err(1, "execvp");
+       case -1:
+               return errno;
+       default:
+               close(pipes[1]);
+               break;  
+       }
+
+       /*
+        * Ok, nfsd has been run.  The following sleep helps with the
+        * theoretical problem that nfsd can't start fast enough to
+        * process our mount request and we end up doing a timeout
+        * before the mount.  This would take several seconds.  So
+        * try to make sure nfsd is up&running already at this stage.
+        */
+       if (read(pipes[0], &devnull, 4) == -1)
+               return errno;
+
+       /*
+        * Configure our networking interface.
+        */
+       rump_init();
+       netcfg_rump_makeshmif(ethername, ifname);
+       netcfg_rump_if(ifname, CLIENTADDR, NETNETMASK);
+
+       /*
+        * That's it.  The rest is done in mount, since we don't have
+        * the mountpath available here.
+        */
+       args = malloc(sizeof(*args));
+       args->ta_childpid = childpid;
+       strcpy(args->ta_ethername, ethername);
+
+       *argp = args;
+       theargs = args;
+
+       return 0;
+}
+
+/* mount the file system */
+int
+nfs_fstest_mount(const atf_tc_t *tc, void *arg, const char *path, int flags)
+{
+       char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
+       const char *nfscliargs[] = {
+               "nfsclient",
+               SERVERADDR ":" EXPORTPATH,
+               path,
+               NULL,
+       };
+       struct nfs_args args;
+       int mntflags;
+
+       if (rump_sys_mkdir(path, 0777) == -1)
+               return errno;
+
+       /* XXX: atf does not reset values */
+       optind = 1;
+       opterr = 1;
+
+       mount_nfs_parseargs(__arraycount(nfscliargs)-1, __UNCONST(nfscliargs),
+           &args, &mntflags, canon_dev, canon_dir);
+
+       /*
+        * We use nfs parseargs here, since as a side effect it
+        * takes care of the  RPC hulabaloo.
+        */
+       if (rump_sys_mount(MOUNT_NFS, path, flags, &args, sizeof(args)) == -1) {
+               return errno;
+       }
+
+       return 0;
+}
+
+int
+nfs_fstest_delfs(const atf_tc_t *tc, void *arg)
+{
+       return 0;
+
+}
+
+int
+nfs_fstest_unmount(const atf_tc_t *tc, const char *path, int flags)
+{
+       struct nfstestargs *args = theargs;
+
+       if (rump_sys_unmount(path, flags) == -1) {
+               return errno;
+       }
+
+       /*
+        * It's highly expected that the child will die next, so we
+        * don't need that information anymore thank you very many.
+        */
+       signal(SIGCHLD, SIG_IGN);
+
+       /*
+        * Just KILL it.  Sending it SIGTERM first causes it to try
+        * to send some unmount RPCs, leading to sticky situations.
+        */
+       kill(args->ta_childpid, SIGKILL);
+
+       /* remove ethernet bus */
+       unlink(args->ta_ethername);
+
+       return 0;
+}



Home | Main Index | Thread Index | Old Index