Source-Changes-HG archive

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

[src/trunk]: src/tests/fs/tmpfs Add a test case for PR kern/36681 demonstrati...



details:   https://anonhg.NetBSD.org/src/rev/5daed1dc12b0
branches:  trunk
changeset: 756033:5daed1dc12b0
user:      pooka <pooka%NetBSD.org@localhost>
date:      Sun Jul 04 12:43:23 2010 +0000

description:
Add a test case for PR kern/36681 demonstrating how easy it is to
get tmpfs rename to "tstile".

Note1: triggering this on any non-SMP system is not as easy (because
one system call tends to run from start to finish in one go) and
therefore I've limited it to i386 and amd64.  Incidentally, I'm
still waiting for the eternally elusive MI CPU_INFO_FOREACH (or at
least something else than a stupid macro) ...

Note2: this is a "race condition" test.  I tested it on my development
host and in qemu and it triggers pretty instantly.  But YMMV.

diffstat:

 tests/fs/tmpfs/t_renamerace.c |  102 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 99 insertions(+), 3 deletions(-)

diffs (131 lines):

diff -r b57977880683 -r 5daed1dc12b0 tests/fs/tmpfs/t_renamerace.c
--- a/tests/fs/tmpfs/t_renamerace.c     Sun Jul 04 07:30:33 2010 +0000
+++ b/tests/fs/tmpfs/t_renamerace.c     Sun Jul 04 12:43:23 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: t_renamerace.c,v 1.6 2009/04/26 15:15:38 pooka Exp $   */
+/*     $NetBSD: t_renamerace.c,v 1.7 2010/07/04 12:43:23 pooka Exp $   */
 
 /*
  * Modified for rump and atf from a program supplied
@@ -7,14 +7,16 @@
 
 #include <sys/types.h>
 #include <sys/mount.h>
+#include <sys/utsname.h>
 
 #include <atf-c.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <pthread.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
-#include <string.h>
 
 #include <rump/rump.h>
 #include <rump/rump_syscalls.h>
@@ -73,8 +75,102 @@
        sleep(10);
 }
 
+ATF_TC(renamerace2);
+ATF_TC_HEAD(renamerace2, tc)
+{
+       atf_tc_set_md_var(tc, "descr", "rename(2) lock order inversion");
+       atf_tc_set_md_var(tc, "timeout", "6");
+}
+
+static volatile int quittingtime = 0;
+
+static void *
+r2w1(void *arg)
+{
+       int fd;
+
+       rump_pub_lwp_alloc_and_switch(0, 0);
+
+       fd = rump_sys_open("/file", O_CREAT | O_RDWR, 0777);
+       if (fd == -1)
+               atf_tc_fail_errno("creat");
+       rump_sys_close(fd);
+
+       while (!quittingtime) {
+               if (rump_sys_rename("/file", "/dir/file") == -1)
+                       atf_tc_fail_errno("rename 1");
+               if (rump_sys_rename("/dir/file", "/file") == -1)
+                       atf_tc_fail_errno("rename 2");
+       }
+
+       return NULL;
+}
+
+static void *
+r2w2(void *arg)
+{
+       int fd;
+
+       rump_pub_lwp_alloc_and_switch(0, 0);
+
+       while (!quittingtime) {
+               fd = rump_sys_open("/dir/file1", O_RDWR);
+               if (fd != -1)
+                       rump_sys_close(fd);
+       }
+
+       return NULL;
+}
+
+ATF_TC_BODY(renamerace2, tc)
+{
+       struct tmpfs_args args;
+       struct utsname un;
+       pthread_t pt[2];
+
+       /*
+        * Check that we are running on an SMP-capable arch.  It should
+        * be a rump capability, but after the CPU_INFO_FOREACH is
+        * fixed, it will be every arch (for rump), so don't bother.
+        */
+       if (uname(&un) == -1)
+               atf_tc_fail_errno("uname");
+       if (strcmp(un.machine, "i386") != 0 && strcmp(un.machine, "amd64") != 0)
+               atf_tc_skip("i386 or amd64 required (have %s)", un.machine);
+
+       /*
+        * Force SMP regardless of how many host CPUs there are.
+        * Deadlock is highly unlikely to trigger otherwise.
+        */
+       setenv("RUMP_NCPU", "2", 1);
+
+       rump_init();
+       memset(&args, 0, sizeof(args));
+       args.ta_version = TMPFS_ARGS_VERSION;
+       args.ta_root_mode = 0777;
+       if (rump_sys_mount(MOUNT_TMPFS, "/", 0, &args, sizeof(args)) == -1)
+               atf_tc_fail_errno("could not mount tmpfs");
+
+       if (rump_sys_mkdir("/dir", 0777) == -1)
+               atf_tc_fail_errno("cannot create directory");
+
+       pthread_create(&pt[0], NULL, r2w1, NULL);
+       pthread_create(&pt[1], NULL, r2w2, NULL);
+
+       /* usually triggers in <<1s for me */
+       sleep(4);
+       quittingtime = 1;
+
+       atf_tc_expect_timeout("PR kern/36681");
+
+       pthread_join(pt[0], NULL);
+       pthread_join(pt[1], NULL);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
        ATF_TP_ADD_TC(tp, renamerace);
-       return 0; /*XXX?*/
+       ATF_TP_ADD_TC(tp, renamerace2);
+
+       return atf_no_error();
 }



Home | Main Index | Thread Index | Old Index