xref: /netbsd-src/tests/fs/vfs/t_io.c (revision fbf9c51ff31b50a380600523a9ce6327bc306f98)
1*fbf9c51fSchristos /*	$NetBSD: t_io.c,v 1.19 2019/07/16 21:13:28 christos Exp $	*/
2909673cfSpooka 
3909673cfSpooka /*-
4909673cfSpooka  * Copyright (c) 2010 The NetBSD Foundation, Inc.
5909673cfSpooka  * All rights reserved.
6909673cfSpooka  *
7909673cfSpooka  * Redistribution and use in source and binary forms, with or without
8909673cfSpooka  * modification, are permitted provided that the following conditions
9909673cfSpooka  * are met:
10909673cfSpooka  * 1. Redistributions of source code must retain the above copyright
11909673cfSpooka  *    notice, this list of conditions and the following disclaimer.
12909673cfSpooka  * 2. Redistributions in binary form must reproduce the above copyright
13909673cfSpooka  *    notice, this list of conditions and the following disclaimer in the
14909673cfSpooka  *    documentation and/or other materials provided with the distribution.
15909673cfSpooka  *
16909673cfSpooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17909673cfSpooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18909673cfSpooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19909673cfSpooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20909673cfSpooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21909673cfSpooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22909673cfSpooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23909673cfSpooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24909673cfSpooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25909673cfSpooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26909673cfSpooka  * POSSIBILITY OF SUCH DAMAGE.
27909673cfSpooka  */
28909673cfSpooka 
29909673cfSpooka #include <sys/stat.h>
30909673cfSpooka #include <sys/statvfs.h>
31909673cfSpooka 
32909673cfSpooka #include <atf-c.h>
33909673cfSpooka #include <fcntl.h>
34909673cfSpooka #include <libgen.h>
35909673cfSpooka #include <stdlib.h>
36909673cfSpooka #include <unistd.h>
37909673cfSpooka 
38909673cfSpooka #include <rump/rump_syscalls.h>
39909673cfSpooka #include <rump/rump.h>
40909673cfSpooka 
41909673cfSpooka #include "../common/h_fsmacros.h"
42c54cb811Schristos #include "h_macros.h"
43909673cfSpooka 
4469eba09fSpooka #define TESTSTR "this is a string.  collect enough and you'll have Em"
4569eba09fSpooka #define TESTSZ sizeof(TESTSTR)
4669eba09fSpooka 
47909673cfSpooka static void
holywrite(const atf_tc_t * tc,const char * mp)48909673cfSpooka holywrite(const atf_tc_t *tc, const char *mp)
49909673cfSpooka {
50909673cfSpooka 	char buf[1024];
51909673cfSpooka 	char *b2, *b3;
52909673cfSpooka 	size_t therange = getpagesize()+1;
53909673cfSpooka 	int fd;
54909673cfSpooka 
5569eba09fSpooka 	FSTEST_ENTER();
56909673cfSpooka 
57909673cfSpooka 	RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666));
58909673cfSpooka 
59909673cfSpooka 	memset(buf, 'A', sizeof(buf));
60909673cfSpooka 	RL(rump_sys_pwrite(fd, buf, 1, getpagesize()));
61909673cfSpooka 
62909673cfSpooka 	memset(buf, 'B', sizeof(buf));
633f6d82acSpooka 	RL(rump_sys_pwrite(fd, buf, 2, getpagesize()-1));
64909673cfSpooka 
65909673cfSpooka 	REQUIRE_LIBC(b2 = malloc(2 * getpagesize()), NULL);
66909673cfSpooka 	REQUIRE_LIBC(b3 = malloc(2 * getpagesize()), NULL);
67909673cfSpooka 
68909673cfSpooka 	RL(rump_sys_pread(fd, b2, therange, 0));
69909673cfSpooka 
70909673cfSpooka 	memset(b3, 0, therange);
71909673cfSpooka 	memset(b3 + getpagesize() - 1, 'B', 2);
72909673cfSpooka 
731a160862Spooka 	ATF_REQUIRE_EQ(memcmp(b2, b3, therange), 0);
74909673cfSpooka 
75909673cfSpooka 	rump_sys_close(fd);
7669eba09fSpooka 	FSTEST_EXIT();
7769eba09fSpooka }
7869eba09fSpooka 
7969eba09fSpooka static void
extendbody(const atf_tc_t * tc,off_t seekcnt)8069eba09fSpooka extendbody(const atf_tc_t *tc, off_t seekcnt)
8169eba09fSpooka {
8269eba09fSpooka 	char buf[TESTSZ+1];
8369eba09fSpooka 	struct stat sb;
8469eba09fSpooka 	int fd;
8569eba09fSpooka 
8669eba09fSpooka 	FSTEST_ENTER();
8769eba09fSpooka 	RL(fd = rump_sys_open("testfile",
88*fbf9c51fSchristos 	    O_CREAT | O_RDWR | (seekcnt ? O_APPEND : 0), 0600));
8969eba09fSpooka 	RL(rump_sys_ftruncate(fd, seekcnt));
9069eba09fSpooka 	RL(rump_sys_fstat(fd, &sb));
9169eba09fSpooka 	ATF_REQUIRE_EQ(sb.st_size, seekcnt);
9269eba09fSpooka 
9369eba09fSpooka 	ATF_REQUIRE_EQ(rump_sys_write(fd, TESTSTR, TESTSZ), TESTSZ);
9469eba09fSpooka 	ATF_REQUIRE_EQ(rump_sys_pread(fd, buf, TESTSZ, seekcnt), TESTSZ);
9569eba09fSpooka 	ATF_REQUIRE_STREQ(buf, TESTSTR);
9669eba09fSpooka 
9769eba09fSpooka 	RL(rump_sys_fstat(fd, &sb));
987dce2920Spooka 	ATF_REQUIRE_EQ(sb.st_size, (off_t)TESTSZ + seekcnt);
9969eba09fSpooka 	RL(rump_sys_close(fd));
10069eba09fSpooka 	FSTEST_EXIT();
10169eba09fSpooka }
10269eba09fSpooka 
10369eba09fSpooka static void
extendfile(const atf_tc_t * tc,const char * mp)10469eba09fSpooka extendfile(const atf_tc_t *tc, const char *mp)
10569eba09fSpooka {
10669eba09fSpooka 
10769eba09fSpooka 	extendbody(tc, 0);
10869eba09fSpooka }
10969eba09fSpooka 
11069eba09fSpooka static void
extendfile_append(const atf_tc_t * tc,const char * mp)11169eba09fSpooka extendfile_append(const atf_tc_t *tc, const char *mp)
11269eba09fSpooka {
11369eba09fSpooka 
11469eba09fSpooka 	extendbody(tc, 37);
115909673cfSpooka }
116909673cfSpooka 
1176ebb7d53Spooka static void
overwritebody(const atf_tc_t * tc,off_t count,bool dotrunc)1186ebb7d53Spooka overwritebody(const atf_tc_t *tc, off_t count, bool dotrunc)
1196ebb7d53Spooka {
1206ebb7d53Spooka 	char *buf;
1216ebb7d53Spooka 	int fd;
1226ebb7d53Spooka 
1236ebb7d53Spooka 	REQUIRE_LIBC(buf = malloc(count), NULL);
1246ebb7d53Spooka 	FSTEST_ENTER();
12516eee230Spooka 	RL(fd = rump_sys_open("testi", O_CREAT | O_RDWR, 0666));
1266ebb7d53Spooka 	ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count);
1276ebb7d53Spooka 	RL(rump_sys_close(fd));
1286ebb7d53Spooka 
12916eee230Spooka 	RL(fd = rump_sys_open("testi", O_RDWR));
1306ebb7d53Spooka 	if (dotrunc)
1316ebb7d53Spooka 		RL(rump_sys_ftruncate(fd, 0));
1326ebb7d53Spooka 	ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count);
1336ebb7d53Spooka 	RL(rump_sys_close(fd));
1346ebb7d53Spooka 	FSTEST_EXIT();
1356ebb7d53Spooka }
1366ebb7d53Spooka 
1376ebb7d53Spooka static void
overwrite512(const atf_tc_t * tc,const char * mp)1386ebb7d53Spooka overwrite512(const atf_tc_t *tc, const char *mp)
1396ebb7d53Spooka {
1406ebb7d53Spooka 
1416ebb7d53Spooka 	overwritebody(tc, 512, false);
1426ebb7d53Spooka }
1436ebb7d53Spooka 
1446ebb7d53Spooka static void
overwrite64k(const atf_tc_t * tc,const char * mp)1456ebb7d53Spooka overwrite64k(const atf_tc_t *tc, const char *mp)
1466ebb7d53Spooka {
1476ebb7d53Spooka 
1486ebb7d53Spooka 	overwritebody(tc, 1<<16, false);
1496ebb7d53Spooka }
1506ebb7d53Spooka 
1516ebb7d53Spooka static void
overwrite_trunc(const atf_tc_t * tc,const char * mp)1526ebb7d53Spooka overwrite_trunc(const atf_tc_t *tc, const char *mp)
1536ebb7d53Spooka {
1546ebb7d53Spooka 
1556ebb7d53Spooka 	overwritebody(tc, 1<<16, true);
1566ebb7d53Spooka }
1576ebb7d53Spooka 
1583b61a87bSnjoly static void
shrinkfile(const atf_tc_t * tc,const char * mp)1593b61a87bSnjoly shrinkfile(const atf_tc_t *tc, const char *mp)
1603b61a87bSnjoly {
1613b61a87bSnjoly 	int fd;
1623b61a87bSnjoly 
1633b61a87bSnjoly 	FSTEST_ENTER();
1643b61a87bSnjoly 	RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666));
1653b61a87bSnjoly 	RL(rump_sys_ftruncate(fd, 2));
1663b61a87bSnjoly 	RL(rump_sys_ftruncate(fd, 1));
1673b61a87bSnjoly 	rump_sys_close(fd);
1683b61a87bSnjoly 	FSTEST_EXIT();
1693b61a87bSnjoly }
1703b61a87bSnjoly 
17140df3663Spooka #define TBSIZE 9000
17240df3663Spooka static void
read_after_unlink(const atf_tc_t * tc,const char * mp)17340df3663Spooka read_after_unlink(const atf_tc_t *tc, const char *mp)
17440df3663Spooka {
17540df3663Spooka 	char buf[TBSIZE], buf2[TBSIZE];
17640df3663Spooka 	int fd;
17740df3663Spooka 
17840df3663Spooka 	FSTEST_ENTER();
17940df3663Spooka 
18040df3663Spooka 	/* create file and put some content into it */
18140df3663Spooka 	RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666));
18240df3663Spooka 	memset(buf, 'D', TBSIZE);
18340df3663Spooka 	ATF_REQUIRE_EQ(rump_sys_write(fd, buf, TBSIZE), TBSIZE);
18440df3663Spooka 	rump_sys_close(fd);
18540df3663Spooka 
18640df3663Spooka 	/* flush buffers from UBC to file system */
18740df3663Spooka 	ATF_REQUIRE_ERRNO(EBUSY, rump_sys_unmount(mp, 0) == -1);
18840df3663Spooka 
18940df3663Spooka 	RL(fd = rump_sys_open("file", O_RDWR));
19040df3663Spooka 	RL(rump_sys_unlink("file"));
19140df3663Spooka 
19240df3663Spooka 	ATF_REQUIRE_EQ(rump_sys_read(fd, buf2, TBSIZE), TBSIZE);
19340df3663Spooka 	ATF_REQUIRE_EQ(memcmp(buf, buf2, TBSIZE), 0);
19440df3663Spooka 	rump_sys_close(fd);
19540df3663Spooka 
19640df3663Spooka 	FSTEST_EXIT();
19740df3663Spooka }
19840df3663Spooka 
19940df3663Spooka static void
wrrd_after_unlink(const atf_tc_t * tc,const char * mp)20040df3663Spooka wrrd_after_unlink(const atf_tc_t *tc, const char *mp)
20140df3663Spooka {
20240df3663Spooka 	int value = 0x11;
20340df3663Spooka 	int v2;
20440df3663Spooka 	int fd;
20540df3663Spooka 
20640df3663Spooka 	FSTEST_ENTER();
20740df3663Spooka 
20840df3663Spooka 	RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666));
20940df3663Spooka 	RL(rump_sys_unlink("file"));
21040df3663Spooka 
21140df3663Spooka 	RL(rump_sys_pwrite(fd, &value, sizeof(value), 654321));
21240df3663Spooka 
21340df3663Spooka 	/*
21440df3663Spooka 	 * We can't easily invalidate the buffer since we hold a
21540df3663Spooka 	 * reference, but try to get them to flush anyway.
21640df3663Spooka 	 */
21740df3663Spooka 	RL(rump_sys_fsync(fd));
21840df3663Spooka 	RL(rump_sys_pread(fd, &v2, sizeof(v2), 654321));
21940df3663Spooka 	rump_sys_close(fd);
22040df3663Spooka 
22140df3663Spooka 	ATF_REQUIRE_EQ(value, v2);
22240df3663Spooka 	FSTEST_EXIT();
22340df3663Spooka }
22440df3663Spooka 
2259707ebf6Sriastradh static void
read_fault(const atf_tc_t * tc,const char * mp)2269707ebf6Sriastradh read_fault(const atf_tc_t *tc, const char *mp)
2279707ebf6Sriastradh {
2289707ebf6Sriastradh 	char ch = 123;
2299707ebf6Sriastradh 	int fd;
2309707ebf6Sriastradh 
2319707ebf6Sriastradh 	FSTEST_ENTER();
2329707ebf6Sriastradh 	RL(fd = rump_sys_open("file", O_CREAT | O_RDWR, 0777));
2339707ebf6Sriastradh 	ATF_REQUIRE_EQ(rump_sys_write(fd, &ch, 1), 1);
2349707ebf6Sriastradh 	RL(rump_sys_close(fd));
2359707ebf6Sriastradh 	RL(fd = rump_sys_open("file", O_RDONLY | O_SYNC | O_RSYNC));
2369707ebf6Sriastradh 	ATF_REQUIRE_ERRNO(EFAULT, rump_sys_read(fd, NULL, 1) == -1);
2379707ebf6Sriastradh 	RL(rump_sys_close(fd));
2389707ebf6Sriastradh 	FSTEST_EXIT();
2399707ebf6Sriastradh }
2409707ebf6Sriastradh 
241909673cfSpooka ATF_TC_FSAPPLY(holywrite, "create a sparse file and fill hole");
24269eba09fSpooka ATF_TC_FSAPPLY(extendfile, "check that extending a file works");
24369eba09fSpooka ATF_TC_FSAPPLY(extendfile_append, "check that extending a file works "
244128cf913Sjruoho 				  "with a append-only fd (PR kern/44307)");
2456ebb7d53Spooka ATF_TC_FSAPPLY(overwrite512, "write a 512 byte file twice");
2466ebb7d53Spooka ATF_TC_FSAPPLY(overwrite64k, "write a 64k byte file twice");
2476ebb7d53Spooka ATF_TC_FSAPPLY(overwrite_trunc, "write 64k + truncate + rewrite");
2483b61a87bSnjoly ATF_TC_FSAPPLY(shrinkfile, "shrink file");
24940df3663Spooka ATF_TC_FSAPPLY(read_after_unlink, "contents can be read off disk after unlink");
25040df3663Spooka ATF_TC_FSAPPLY(wrrd_after_unlink, "file can be written and read after unlink");
2519707ebf6Sriastradh ATF_TC_FSAPPLY(read_fault, "read at bad address must return EFAULT");
252909673cfSpooka 
ATF_TP_ADD_TCS(tp)253909673cfSpooka ATF_TP_ADD_TCS(tp)
254909673cfSpooka {
255909673cfSpooka 
256909673cfSpooka 	ATF_TP_FSAPPLY(holywrite);
25769eba09fSpooka 	ATF_TP_FSAPPLY(extendfile);
25869eba09fSpooka 	ATF_TP_FSAPPLY(extendfile_append);
2596ebb7d53Spooka 	ATF_TP_FSAPPLY(overwrite512);
2606ebb7d53Spooka 	ATF_TP_FSAPPLY(overwrite64k);
2616ebb7d53Spooka 	ATF_TP_FSAPPLY(overwrite_trunc);
2623b61a87bSnjoly 	ATF_TP_FSAPPLY(shrinkfile);
26340df3663Spooka 	ATF_TP_FSAPPLY(read_after_unlink);
26440df3663Spooka 	ATF_TP_FSAPPLY(wrrd_after_unlink);
2659707ebf6Sriastradh 	ATF_TP_FSAPPLY(read_fault);
266909673cfSpooka 
267909673cfSpooka 	return atf_no_error();
268909673cfSpooka }
269