1/* $NetBSD$ */ 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#include "../common/h_fsmacros.h" 25#include "../../h_macros.h" 26 27static volatile int quittingtime; 28pid_t wrkpid; 29 30static void * 31w1(void *arg) 32{ 33 int fd; 34 35 rump_pub_lwproc_newlwp(wrkpid); 36 37 while (!quittingtime) { 38 fd = rump_sys_open("rename.test1", 39 O_WRONLY|O_CREAT|O_TRUNC, 0666); 40 if (fd == -1 && errno != EEXIST) 41 atf_tc_fail_errno("create"); 42 rump_sys_unlink("rename.test1"); 43 rump_sys_close(fd); 44 } 45 46 return NULL; 47} 48 49static void * 50w1_dirs(void *arg) 51{ 52 53 rump_pub_lwproc_newlwp(wrkpid); 54 55 while (!quittingtime) { 56 if (rump_sys_mkdir("rename.test1", 0777) == -1) 57 atf_tc_fail_errno("mkdir"); 58 rump_sys_rmdir("rename.test1"); 59 } 60 61 return NULL; 62} 63 64static void * 65w2(void *arg) 66{ 67 68 rump_pub_lwproc_newlwp(wrkpid); 69 70 while (!quittingtime) { 71 rump_sys_rename("rename.test1", "rename.test2"); 72 } 73 74 return NULL; 75} 76 77#define NWRK 8 78static void 79renamerace(const atf_tc_t *tc, const char *mp) 80{ 81 pthread_t pt1[NWRK], pt2[NWRK]; 82 int i; 83 84 if (FSTYPE_RUMPFS(tc)) 85 atf_tc_skip("rename not supported by file system"); 86 87 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 88 RL(wrkpid = rump_sys_getpid()); 89 90 RL(rump_sys_chdir(mp)); 91 for (i = 0; i < NWRK; i++) 92 pthread_create(&pt1[i], NULL, w1, NULL); 93 94 for (i = 0; i < NWRK; i++) 95 pthread_create(&pt2[i], NULL, w2, NULL); 96 97 sleep(5); 98 quittingtime = 1; 99 100 for (i = 0; i < NWRK; i++) 101 pthread_join(pt1[i], NULL); 102 for (i = 0; i < NWRK; i++) 103 pthread_join(pt2[i], NULL); 104 RL(rump_sys_chdir("/")); 105 106 if (FSTYPE_MSDOS(tc)) { 107 atf_tc_expect_fail("PR kern/44661"); 108 /* 109 * XXX: race does not trigger every time at least 110 * on amd64/qemu. 111 */ 112 if (msdosfs_fstest_unmount(tc, mp, 0) != 0) { 113 rump_pub_vfs_mount_print(mp, 1); 114 atf_tc_fail_errno("unmount failed"); 115 } 116 atf_tc_fail("race did not trigger this time"); 117 } 118} 119 120static void 121renamerace_dirs(const atf_tc_t *tc, const char *mp) 122{ 123 pthread_t pt1, pt2; 124 125 if (FSTYPE_SYSVBFS(tc)) 126 atf_tc_skip("directories not supported by file system"); 127 128 if (FSTYPE_RUMPFS(tc)) 129 atf_tc_skip("rename not supported by file system"); 130 131 /* XXX: msdosfs also sometimes hangs */ 132 if (FSTYPE_EXT2FS(tc) || FSTYPE_MSDOS(tc)) 133 atf_tc_expect_signal(-1, "PR kern/43626"); 134 135 /* XXX: unracy execution not caught */ 136 if (FSTYPE_P2K_FFS(tc)) 137 atf_tc_expect_fail("PR kern/44336"); /* child dies */ 138 139 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 140 RL(wrkpid = rump_sys_getpid()); 141 142 RL(rump_sys_chdir(mp)); 143 pthread_create(&pt1, NULL, w1_dirs, NULL); 144 pthread_create(&pt2, NULL, w2, NULL); 145 146 sleep(5); 147 quittingtime = 1; 148 149 pthread_join(pt1, NULL); 150 pthread_join(pt2, NULL); 151 RL(rump_sys_chdir("/")); 152 153 /* 154 * Doesn't always trigger when run on a slow backend 155 * (i.e. not on tmpfs/mfs). So do the usual kludge. 156 */ 157 if (FSTYPE_EXT2FS(tc) || FSTYPE_MSDOS(tc)) 158 abort(); 159 160 if (FSTYPE_P2K_FFS(tc)) { 161 /* XXX: some races may hang test run if we don't unmount */ 162 puffs_fstest_unmount(tc, mp, MNT_FORCE); 163 atf_tc_fail("problem did not trigger"); 164 } 165} 166 167ATF_TC_FSAPPLY(renamerace, "rename(2) race with file unlinked mid-operation"); 168ATF_TC_FSAPPLY(renamerace_dirs, "rename(2) race with directories"); 169 170ATF_TP_ADD_TCS(tp) 171{ 172 173 ATF_TP_FSAPPLY(renamerace); /* PR kern/41128 */ 174 ATF_TP_FSAPPLY(renamerace_dirs); 175 176 return atf_no_error(); 177} 178