xref: /netbsd-src/tests/fs/vfs/t_renamerace.c (revision aa60659cfafc0598237ebf9aa1119b4e741ea7c3)
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