1 /* $NetBSD: t_renamerace.c,v 1.32 2014/07/29 09:15:48 gson Exp $ */ 2 3 /* 4 * Modified for rump and atf from a program supplied 5 * by Nicolas Joly in kern/40948 6 */ 7 8 #include <sys/types.h> 9 #include <sys/mount.h> 10 #include <sys/utsname.h> 11 12 #include <atf-c.h> 13 #include <errno.h> 14 #include <fcntl.h> 15 #include <pthread.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <unistd.h> 20 21 #include <rump/rump.h> 22 #include <rump/rump_syscalls.h> 23 24 /* Bump the size of the test file system image to a larger value. 25 * 26 * These tests cause a lot of churn in the file system by creating and 27 * deleting files/directories in quick succession. A faster CPU will cause 28 * more churn because the tests are capped by a run time period in seconds, 29 * not number of operations. 30 * 31 * This is all fine except for LFS, because the lfs_cleanerd cannot keep up 32 * with the churn and thus causes the test to fail on fast machines. Hence 33 * the reason for this hack. */ 34 #define FSTEST_IMGSIZE (50000 * 512) 35 36 #include "../common/h_fsmacros.h" 37 #include "../../h_macros.h" 38 39 static volatile int quittingtime; 40 pid_t wrkpid; 41 42 static void * 43 w1(void *arg) 44 { 45 int fd; 46 47 rump_pub_lwproc_newlwp(wrkpid); 48 49 while (!quittingtime) { 50 fd = rump_sys_open("rename.test1", 51 O_WRONLY|O_CREAT|O_TRUNC, 0666); 52 if (fd == -1 && errno != EEXIST) 53 atf_tc_fail_errno("create"); 54 rump_sys_unlink("rename.test1"); 55 rump_sys_close(fd); 56 } 57 58 return NULL; 59 } 60 61 static void * 62 w1_dirs(void *arg) 63 { 64 65 rump_pub_lwproc_newlwp(wrkpid); 66 67 while (!quittingtime) { 68 if (rump_sys_mkdir("rename.test1", 0777) == -1) 69 atf_tc_fail_errno("mkdir"); 70 rump_sys_rmdir("rename.test1"); 71 } 72 73 return NULL; 74 } 75 76 static void * 77 w2(void *arg) 78 { 79 80 rump_pub_lwproc_newlwp(wrkpid); 81 82 while (!quittingtime) { 83 rump_sys_rename("rename.test1", "rename.test2"); 84 } 85 86 return NULL; 87 } 88 89 #define NWRK 8 90 static void 91 renamerace(const atf_tc_t *tc, const char *mp) 92 { 93 pthread_t pt1[NWRK], pt2[NWRK]; 94 int i; 95 96 /* 97 * Sysvbfs supports only 8 inodes so this test would exhaust 98 * the inode table and creating files would fail with ENOSPC. 99 */ 100 if (FSTYPE_SYSVBFS(tc)) 101 atf_tc_skip("filesystem has not enough inodes"); 102 if (FSTYPE_RUMPFS(tc)) 103 atf_tc_skip("rename not supported by file system"); 104 if (FSTYPE_UDF(tc)) 105 atf_tc_expect_fail("PR kern/49046"); 106 107 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 108 RL(wrkpid = rump_sys_getpid()); 109 110 RL(rump_sys_chdir(mp)); 111 for (i = 0; i < NWRK; i++) 112 pthread_create(&pt1[i], NULL, w1, NULL); 113 114 for (i = 0; i < NWRK; i++) 115 pthread_create(&pt2[i], NULL, w2, NULL); 116 117 sleep(5); 118 quittingtime = 1; 119 120 for (i = 0; i < NWRK; i++) 121 pthread_join(pt1[i], NULL); 122 for (i = 0; i < NWRK; i++) 123 pthread_join(pt2[i], NULL); 124 RL(rump_sys_chdir("/")); 125 126 if (FSTYPE_UDF(tc)) 127 atf_tc_fail("race did not trigger this time"); 128 129 if (FSTYPE_MSDOS(tc)) { 130 atf_tc_expect_fail("PR kern/44661"); 131 /* 132 * XXX: race does not trigger every time at least 133 * on amd64/qemu. 134 */ 135 if (msdosfs_fstest_unmount(tc, mp, 0) != 0) { 136 rump_pub_vfs_mount_print(mp, 1); 137 atf_tc_fail_errno("unmount failed"); 138 } 139 atf_tc_fail("race did not trigger this time"); 140 } 141 } 142 143 static void 144 renamerace_dirs(const atf_tc_t *tc, const char *mp) 145 { 146 pthread_t pt1, pt2; 147 148 if (FSTYPE_SYSVBFS(tc)) 149 atf_tc_skip("directories not supported by file system"); 150 151 if (FSTYPE_RUMPFS(tc)) 152 atf_tc_skip("rename not supported by file system"); 153 154 /* XXX: msdosfs also sometimes hangs */ 155 if (FSTYPE_MSDOS(tc)) 156 atf_tc_expect_signal(-1, "PR kern/43626"); 157 158 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 159 RL(wrkpid = rump_sys_getpid()); 160 161 RL(rump_sys_chdir(mp)); 162 pthread_create(&pt1, NULL, w1_dirs, NULL); 163 pthread_create(&pt2, NULL, w2, NULL); 164 165 sleep(5); 166 quittingtime = 1; 167 168 pthread_join(pt1, NULL); 169 pthread_join(pt2, NULL); 170 RL(rump_sys_chdir("/")); 171 172 /* 173 * Doesn't always trigger when run on a slow backend 174 * (i.e. not on tmpfs/mfs). So do the usual kludge. 175 */ 176 if (FSTYPE_MSDOS(tc)) 177 abort(); 178 } 179 180 ATF_TC_FSAPPLY(renamerace, "rename(2) race with file unlinked mid-operation"); 181 ATF_TC_FSAPPLY(renamerace_dirs, "rename(2) race with directories"); 182 183 ATF_TP_ADD_TCS(tp) 184 { 185 186 ATF_TP_FSAPPLY(renamerace); /* PR kern/41128 */ 187 ATF_TP_FSAPPLY(renamerace_dirs); 188 189 return atf_no_error(); 190 } 191