1*aa60659cSryo /* $NetBSD: t_renamerace.c,v 1.44 2022/01/31 17:23:37 ryo Exp $ */
23b5bc723Spooka
33b5bc723Spooka /*
43b5bc723Spooka * Modified for rump and atf from a program supplied
53b5bc723Spooka * by Nicolas Joly in kern/40948
63b5bc723Spooka */
73b5bc723Spooka
83b5bc723Spooka #include <sys/types.h>
93b5bc723Spooka #include <sys/mount.h>
103b5bc723Spooka #include <sys/utsname.h>
113b5bc723Spooka
123b5bc723Spooka #include <atf-c.h>
133b5bc723Spooka #include <errno.h>
143b5bc723Spooka #include <fcntl.h>
153b5bc723Spooka #include <pthread.h>
163b5bc723Spooka #include <stdio.h>
173b5bc723Spooka #include <stdlib.h>
183b5bc723Spooka #include <string.h>
193b5bc723Spooka #include <unistd.h>
203b5bc723Spooka
213b5bc723Spooka #include <rump/rump.h>
223b5bc723Spooka #include <rump/rump_syscalls.h>
233b5bc723Spooka
242f611e9fSjmmv /* Bump the size of the test file system image to a larger value.
252f611e9fSjmmv *
262f611e9fSjmmv * These tests cause a lot of churn in the file system by creating and
272f611e9fSjmmv * deleting files/directories in quick succession. A faster CPU will cause
282f611e9fSjmmv * more churn because the tests are capped by a run time period in seconds,
292f611e9fSjmmv * not number of operations.
302f611e9fSjmmv *
312f611e9fSjmmv * This is all fine except for LFS, because the lfs_cleanerd cannot keep up
322f611e9fSjmmv * with the churn and thus causes the test to fail on fast machines. Hence
332f611e9fSjmmv * the reason for this hack. */
342f611e9fSjmmv #define FSTEST_IMGSIZE (50000 * 512)
352f611e9fSjmmv
363b5bc723Spooka #include "../common/h_fsmacros.h"
37c54cb811Schristos #include "h_macros.h"
383b5bc723Spooka
393b5bc723Spooka static volatile int quittingtime;
402a47331eSpooka pid_t wrkpid;
413b5bc723Spooka
423b5bc723Spooka static void *
w1(void * arg)433b5bc723Spooka w1(void *arg)
443b5bc723Spooka {
453b5bc723Spooka int fd;
463b5bc723Spooka
472a47331eSpooka rump_pub_lwproc_newlwp(wrkpid);
483b5bc723Spooka
493b5bc723Spooka while (!quittingtime) {
503b5bc723Spooka fd = rump_sys_open("rename.test1",
513b5bc723Spooka O_WRONLY|O_CREAT|O_TRUNC, 0666);
524541e133Spooka if (fd == -1 && errno != EEXIST)
533b5bc723Spooka atf_tc_fail_errno("create");
543b5bc723Spooka rump_sys_unlink("rename.test1");
553b5bc723Spooka rump_sys_close(fd);
563b5bc723Spooka }
573b5bc723Spooka
583b5bc723Spooka return NULL;
593b5bc723Spooka }
603b5bc723Spooka
613b5bc723Spooka static void *
w1_dirs(void * arg)628206e1e6Spooka w1_dirs(void *arg)
638206e1e6Spooka {
648206e1e6Spooka
652a47331eSpooka rump_pub_lwproc_newlwp(wrkpid);
668206e1e6Spooka
678206e1e6Spooka while (!quittingtime) {
688206e1e6Spooka if (rump_sys_mkdir("rename.test1", 0777) == -1)
698206e1e6Spooka atf_tc_fail_errno("mkdir");
708206e1e6Spooka rump_sys_rmdir("rename.test1");
718206e1e6Spooka }
728206e1e6Spooka
738206e1e6Spooka return NULL;
748206e1e6Spooka }
758206e1e6Spooka
768206e1e6Spooka static void *
w2(void * arg)773b5bc723Spooka w2(void *arg)
783b5bc723Spooka {
793b5bc723Spooka
802a47331eSpooka rump_pub_lwproc_newlwp(wrkpid);
813b5bc723Spooka
823b5bc723Spooka while (!quittingtime) {
833b5bc723Spooka rump_sys_rename("rename.test1", "rename.test2");
843b5bc723Spooka }
853b5bc723Spooka
863b5bc723Spooka return NULL;
873b5bc723Spooka }
883b5bc723Spooka
8960f4a93eSriastradh static void
w3_mkdir(void)9060f4a93eSriastradh w3_mkdir(void)
9160f4a93eSriastradh {
9260f4a93eSriastradh
9360f4a93eSriastradh if (rump_sys_mkdir("c", 0777) == -1)
9460f4a93eSriastradh ATF_CHECK_MSG(errno == ENOENT || errno == EEXIST,
9560f4a93eSriastradh "mkdir: %s (errno=%d)\n", strerror(errno), errno);
9660f4a93eSriastradh if (rump_sys_mkdir("c/d", 0777) == -1)
9760f4a93eSriastradh ATF_CHECK_MSG(errno == ENOENT || errno == EEXIST,
9860f4a93eSriastradh "mkdir: %s (errno=%d)\n", strerror(errno), errno);
9960f4a93eSriastradh if (rump_sys_mkdir("c/d/e", 0777) == -1)
10060f4a93eSriastradh ATF_CHECK_MSG(errno == ENOENT || errno == EEXIST,
10160f4a93eSriastradh "mkdir: %s (errno=%d)\n", strerror(errno), errno);
10260f4a93eSriastradh }
10360f4a93eSriastradh
10460f4a93eSriastradh static void *
w3_rmdir(void * arg)10560f4a93eSriastradh w3_rmdir(void *arg)
10660f4a93eSriastradh {
10760f4a93eSriastradh
10860f4a93eSriastradh rump_pub_lwproc_newlwp(wrkpid);
10960f4a93eSriastradh
11060f4a93eSriastradh while (!quittingtime) {
11160f4a93eSriastradh w3_mkdir();
11260f4a93eSriastradh rump_sys_rmdir("c/d/e");
11360f4a93eSriastradh rump_sys_rmdir("c/d");
11460f4a93eSriastradh }
11560f4a93eSriastradh
11660f4a93eSriastradh return NULL;
11760f4a93eSriastradh }
11860f4a93eSriastradh
11960f4a93eSriastradh static void *
w3_rename1(void * arg)12060f4a93eSriastradh w3_rename1(void *arg)
12160f4a93eSriastradh {
12260f4a93eSriastradh
12360f4a93eSriastradh rump_pub_lwproc_newlwp(wrkpid);
12460f4a93eSriastradh
12560f4a93eSriastradh while (!quittingtime) {
12660f4a93eSriastradh w3_mkdir();
12760f4a93eSriastradh rump_sys_rename("c", "c/d/e");
12860f4a93eSriastradh }
12960f4a93eSriastradh
13060f4a93eSriastradh return NULL;
13160f4a93eSriastradh }
13260f4a93eSriastradh
13360f4a93eSriastradh static void *
w3_rename2(void * arg)13460f4a93eSriastradh w3_rename2(void *arg)
13560f4a93eSriastradh {
13660f4a93eSriastradh
13760f4a93eSriastradh rump_pub_lwproc_newlwp(wrkpid);
13860f4a93eSriastradh
13960f4a93eSriastradh while (!quittingtime) {
14060f4a93eSriastradh w3_mkdir();
14160f4a93eSriastradh rump_sys_rename("c/d/e", "c");
14260f4a93eSriastradh }
14360f4a93eSriastradh
14460f4a93eSriastradh return NULL;
14560f4a93eSriastradh }
14660f4a93eSriastradh
1474541e133Spooka #define NWRK 8
1483b5bc723Spooka static void
renamerace(const atf_tc_t * tc,const char * mp)1493b5bc723Spooka renamerace(const atf_tc_t *tc, const char *mp)
1503b5bc723Spooka {
1514541e133Spooka pthread_t pt1[NWRK], pt2[NWRK];
1524541e133Spooka int i;
1533b5bc723Spooka
1549cd2f4b9Shannken /*
1559cd2f4b9Shannken * Sysvbfs supports only 8 inodes so this test would exhaust
1569cd2f4b9Shannken * the inode table and creating files would fail with ENOSPC.
1579cd2f4b9Shannken */
1589cd2f4b9Shannken if (FSTYPE_SYSVBFS(tc))
1599cd2f4b9Shannken atf_tc_skip("filesystem has not enough inodes");
16088b6bdf1Spooka if (FSTYPE_RUMPFS(tc))
1617557af29Snjoly atf_tc_skip("rename not supported by file system");
162b6f40f55Sgson if (FSTYPE_UDF(tc))
16340aea223Sgson atf_tc_expect_fail("PR kern/53865");
16488b6bdf1Spooka
1655c3365ceSpooka RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
166110455efSpooka RL(wrkpid = rump_sys_getpid());
167110455efSpooka
1681457068cSpooka RL(rump_sys_chdir(mp));
1694541e133Spooka for (i = 0; i < NWRK; i++)
1701457068cSpooka pthread_create(&pt1[i], NULL, w1, NULL);
1714541e133Spooka
1724541e133Spooka for (i = 0; i < NWRK; i++)
1731457068cSpooka pthread_create(&pt2[i], NULL, w2, NULL);
1743b5bc723Spooka
1753b5bc723Spooka sleep(5);
1763b5bc723Spooka quittingtime = 1;
1773b5bc723Spooka
1784541e133Spooka for (i = 0; i < NWRK; i++)
1794541e133Spooka pthread_join(pt1[i], NULL);
1804541e133Spooka for (i = 0; i < NWRK; i++)
1814541e133Spooka pthread_join(pt2[i], NULL);
1821457068cSpooka RL(rump_sys_chdir("/"));
183b006a8b6Spooka
184b6f40f55Sgson if (FSTYPE_UDF(tc))
185b6f40f55Sgson atf_tc_fail("race did not trigger this time");
1863b5bc723Spooka }
1873b5bc723Spooka
1888206e1e6Spooka static void
renamerace_dirs(const atf_tc_t * tc,const char * mp)1898206e1e6Spooka renamerace_dirs(const atf_tc_t *tc, const char *mp)
1908206e1e6Spooka {
1918206e1e6Spooka pthread_t pt1, pt2;
1928206e1e6Spooka
193978c8480Spooka if (FSTYPE_SYSVBFS(tc))
1947557af29Snjoly atf_tc_skip("directories not supported by file system");
19588b6bdf1Spooka if (FSTYPE_RUMPFS(tc))
1967557af29Snjoly atf_tc_skip("rename not supported by file system");
1975a561c0cSgson if (FSTYPE_UDF(tc))
1985a561c0cSgson atf_tc_expect_fail("PR kern/53865");
19988b6bdf1Spooka
2005c3365ceSpooka RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
2012a47331eSpooka RL(wrkpid = rump_sys_getpid());
2022a47331eSpooka
2031457068cSpooka RL(rump_sys_chdir(mp));
2041457068cSpooka pthread_create(&pt1, NULL, w1_dirs, NULL);
2051457068cSpooka pthread_create(&pt2, NULL, w2, NULL);
2068206e1e6Spooka
2078206e1e6Spooka sleep(5);
2088206e1e6Spooka quittingtime = 1;
2098206e1e6Spooka
2108206e1e6Spooka pthread_join(pt1, NULL);
2118206e1e6Spooka pthread_join(pt2, NULL);
2121457068cSpooka RL(rump_sys_chdir("/"));
2138206e1e6Spooka
2145a561c0cSgson if (FSTYPE_UDF(tc))
2155a561c0cSgson atf_tc_fail("race did not trigger this time");
2168206e1e6Spooka }
2178206e1e6Spooka
21860f4a93eSriastradh static void
renamerace_cycle(const atf_tc_t * tc,const char * mp)21960f4a93eSriastradh renamerace_cycle(const atf_tc_t *tc, const char *mp)
22060f4a93eSriastradh {
22160f4a93eSriastradh pthread_t pt_rmdir, pt_rename1, pt_rename2;
22260f4a93eSriastradh
22360f4a93eSriastradh if (FSTYPE_SYSVBFS(tc))
22460f4a93eSriastradh atf_tc_skip("directories not supported by file system");
22560f4a93eSriastradh if (FSTYPE_RUMPFS(tc))
22660f4a93eSriastradh atf_tc_skip("rename not supported by file system");
22713a2b733Sriastradh if (FSTYPE_P2K_FFS(tc))
22813a2b733Sriastradh atf_tc_expect_fail("assertion \"vp->v_size == ip->i_size\" failed");
22960f4a93eSriastradh if (FSTYPE_PUFFS(tc))
23060f4a93eSriastradh atf_tc_expect_fail("assertion \"dfd\" failed");
23160f4a93eSriastradh if (FSTYPE_NFS(tc))
23260f4a93eSriastradh atf_tc_expect_fail("mkdir fails with ESTALE");
233ef09d380Sriastradh if (FSTYPE_UDF(tc))
234ef09d380Sriastradh atf_tc_expect_fail("sometimes fails with ENOSPC, PR kern/56253");
23560f4a93eSriastradh
23660f4a93eSriastradh RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
23760f4a93eSriastradh RL(wrkpid = rump_sys_getpid());
23860f4a93eSriastradh
23960f4a93eSriastradh RL(rump_sys_chdir(mp));
24060f4a93eSriastradh pthread_create(&pt_rmdir, NULL, w3_rmdir, NULL);
24160f4a93eSriastradh pthread_create(&pt_rename1, NULL, w3_rename1, NULL);
24260f4a93eSriastradh pthread_create(&pt_rename2, NULL, w3_rename2, NULL);
24360f4a93eSriastradh
24460f4a93eSriastradh sleep(10);
24560f4a93eSriastradh quittingtime = 1;
24660f4a93eSriastradh
247*aa60659cSryo alarm(5);
24860f4a93eSriastradh pthread_join(pt_rmdir, NULL);
24960f4a93eSriastradh pthread_join(pt_rename1, NULL);
25060f4a93eSriastradh pthread_join(pt_rename2, NULL);
25160f4a93eSriastradh alarm(0);
25260f4a93eSriastradh RL(rump_sys_chdir("/"));
25360f4a93eSriastradh
254ef09d380Sriastradh if (FSTYPE_UDF(tc))
255ef09d380Sriastradh atf_tc_fail("PR kern/56253 did not trigger this time");
256ab5267d5Sgson if (FSTYPE_P2K_FFS(tc))
257ab5267d5Sgson atf_tc_fail("did not fail this time");
258ab5267d5Sgson if (FSTYPE_PUFFS(tc))
259ab5267d5Sgson atf_tc_fail("did not fail this time");
260ab5267d5Sgson if (FSTYPE_NFS(tc))
261ab5267d5Sgson atf_tc_fail("did not fail this time");
26260f4a93eSriastradh }
26360f4a93eSriastradh
2643b5bc723Spooka ATF_TC_FSAPPLY(renamerace, "rename(2) race with file unlinked mid-operation");
2658206e1e6Spooka ATF_TC_FSAPPLY(renamerace_dirs, "rename(2) race with directories");
26660f4a93eSriastradh ATF_TC_FSAPPLY(renamerace_cycle, "rename(2) race making directory cycles");
2673b5bc723Spooka
ATF_TP_ADD_TCS(tp)2683b5bc723Spooka ATF_TP_ADD_TCS(tp)
2693b5bc723Spooka {
2703b5bc723Spooka
2713b5bc723Spooka ATF_TP_FSAPPLY(renamerace); /* PR kern/41128 */
2728206e1e6Spooka ATF_TP_FSAPPLY(renamerace_dirs);
27360f4a93eSriastradh ATF_TP_FSAPPLY(renamerace_cycle);
2743b5bc723Spooka
2753b5bc723Spooka return atf_no_error();
2763b5bc723Spooka }
277