Module Name:    src
Committed By:   pooka
Date:           Sun Jul  4 12:43:23 UTC 2010

Modified Files:
        src/tests/fs/tmpfs: t_renamerace.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/tests/fs/tmpfs/t_renamerace.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/fs/tmpfs/t_renamerace.c
diff -u src/tests/fs/tmpfs/t_renamerace.c:1.6 src/tests/fs/tmpfs/t_renamerace.c:1.7
--- src/tests/fs/tmpfs/t_renamerace.c:1.6	Sun Apr 26 15:15:38 2009
+++ src/tests/fs/tmpfs/t_renamerace.c	Sun Jul  4 12:43:23 2010
@@ -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 <unistd.h>
+#include <stdlib.h>
 #include <string.h>
+#include <unistd.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();
 }

Reply via email to