xref: /freebsd/contrib/netbsd-tests/fs/vfs/t_io.c (revision 43a5ec4eb41567cc92586503212743d89686d78f)
1 /*	$NetBSD: t_io.c,v 1.17 2017/01/13 21:30:40 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2010 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/stat.h>
30 #include <sys/statvfs.h>
31 
32 #include <atf-c.h>
33 #include <fcntl.h>
34 #include <libgen.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 
38 #include <rump/rump_syscalls.h>
39 #include <rump/rump.h>
40 
41 #include "../common/h_fsmacros.h"
42 #include "h_macros.h"
43 
44 #define TESTSTR "this is a string.  collect enough and you'll have Em"
45 #define TESTSZ sizeof(TESTSTR)
46 
47 static void
48 holywrite(const atf_tc_t *tc, const char *mp)
49 {
50 	char buf[1024];
51 	char *b2, *b3;
52 	size_t therange = getpagesize()+1;
53 	int fd;
54 
55 	FSTEST_ENTER();
56 
57 	RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666));
58 
59 	memset(buf, 'A', sizeof(buf));
60 	RL(rump_sys_pwrite(fd, buf, 1, getpagesize()));
61 
62 	memset(buf, 'B', sizeof(buf));
63 	RL(rump_sys_pwrite(fd, buf, 2, getpagesize()-1));
64 
65 	REQUIRE_LIBC(b2 = malloc(2 * getpagesize()), NULL);
66 	REQUIRE_LIBC(b3 = malloc(2 * getpagesize()), NULL);
67 
68 	RL(rump_sys_pread(fd, b2, therange, 0));
69 
70 	memset(b3, 0, therange);
71 	memset(b3 + getpagesize() - 1, 'B', 2);
72 
73 	ATF_REQUIRE_EQ(memcmp(b2, b3, therange), 0);
74 
75 	rump_sys_close(fd);
76 	FSTEST_EXIT();
77 }
78 
79 static void
80 extendbody(const atf_tc_t *tc, off_t seekcnt)
81 {
82 	char buf[TESTSZ+1];
83 	struct stat sb;
84 	int fd;
85 
86 	FSTEST_ENTER();
87 	RL(fd = rump_sys_open("testfile",
88 	    O_CREAT | O_RDWR | (seekcnt ? O_APPEND : 0)));
89 	RL(rump_sys_ftruncate(fd, seekcnt));
90 	RL(rump_sys_fstat(fd, &sb));
91 	ATF_REQUIRE_EQ(sb.st_size, seekcnt);
92 
93 	ATF_REQUIRE_EQ(rump_sys_write(fd, TESTSTR, TESTSZ), TESTSZ);
94 	ATF_REQUIRE_EQ(rump_sys_pread(fd, buf, TESTSZ, seekcnt), TESTSZ);
95 	ATF_REQUIRE_STREQ(buf, TESTSTR);
96 
97 	RL(rump_sys_fstat(fd, &sb));
98 	ATF_REQUIRE_EQ(sb.st_size, (off_t)TESTSZ + seekcnt);
99 	RL(rump_sys_close(fd));
100 	FSTEST_EXIT();
101 }
102 
103 static void
104 extendfile(const atf_tc_t *tc, const char *mp)
105 {
106 
107 	extendbody(tc, 0);
108 }
109 
110 static void
111 extendfile_append(const atf_tc_t *tc, const char *mp)
112 {
113 
114 	extendbody(tc, 37);
115 }
116 
117 static void
118 overwritebody(const atf_tc_t *tc, off_t count, bool dotrunc)
119 {
120 	char *buf;
121 	int fd;
122 
123 	REQUIRE_LIBC(buf = malloc(count), NULL);
124 	FSTEST_ENTER();
125 	RL(fd = rump_sys_open("testi", O_CREAT | O_RDWR, 0666));
126 	ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count);
127 	RL(rump_sys_close(fd));
128 
129 	RL(fd = rump_sys_open("testi", O_RDWR));
130 	if (dotrunc)
131 		RL(rump_sys_ftruncate(fd, 0));
132 	ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count);
133 	RL(rump_sys_close(fd));
134 	FSTEST_EXIT();
135 }
136 
137 static void
138 overwrite512(const atf_tc_t *tc, const char *mp)
139 {
140 
141 	overwritebody(tc, 512, false);
142 }
143 
144 static void
145 overwrite64k(const atf_tc_t *tc, const char *mp)
146 {
147 
148 	overwritebody(tc, 1<<16, false);
149 }
150 
151 static void
152 overwrite_trunc(const atf_tc_t *tc, const char *mp)
153 {
154 
155 	overwritebody(tc, 1<<16, true);
156 }
157 
158 static void
159 shrinkfile(const atf_tc_t *tc, const char *mp)
160 {
161 	int fd;
162 
163 	FSTEST_ENTER();
164 	RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666));
165 	RL(rump_sys_ftruncate(fd, 2));
166 	RL(rump_sys_ftruncate(fd, 1));
167 	rump_sys_close(fd);
168 	FSTEST_EXIT();
169 }
170 
171 #define TBSIZE 9000
172 static void
173 read_after_unlink(const atf_tc_t *tc, const char *mp)
174 {
175 	char buf[TBSIZE], buf2[TBSIZE];
176 	int fd;
177 
178 	FSTEST_ENTER();
179 
180 	/* create file and put some content into it */
181 	RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666));
182 	memset(buf, 'D', TBSIZE);
183 	ATF_REQUIRE_EQ(rump_sys_write(fd, buf, TBSIZE), TBSIZE);
184 	rump_sys_close(fd);
185 
186 	/* flush buffers from UBC to file system */
187 	ATF_REQUIRE_ERRNO(EBUSY, rump_sys_unmount(mp, 0) == -1);
188 
189 	RL(fd = rump_sys_open("file", O_RDWR));
190 	RL(rump_sys_unlink("file"));
191 
192 	ATF_REQUIRE_EQ(rump_sys_read(fd, buf2, TBSIZE), TBSIZE);
193 	ATF_REQUIRE_EQ(memcmp(buf, buf2, TBSIZE), 0);
194 	rump_sys_close(fd);
195 
196 	FSTEST_EXIT();
197 }
198 
199 static void
200 wrrd_after_unlink(const atf_tc_t *tc, const char *mp)
201 {
202 	int value = 0x11;
203 	int v2;
204 	int fd;
205 
206 	FSTEST_ENTER();
207 
208 	RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666));
209 	RL(rump_sys_unlink("file"));
210 
211 	RL(rump_sys_pwrite(fd, &value, sizeof(value), 654321));
212 
213 	/*
214 	 * We can't easily invalidate the buffer since we hold a
215 	 * reference, but try to get them to flush anyway.
216 	 */
217 	RL(rump_sys_fsync(fd));
218 	RL(rump_sys_pread(fd, &v2, sizeof(v2), 654321));
219 	rump_sys_close(fd);
220 
221 	ATF_REQUIRE_EQ(value, v2);
222 	FSTEST_EXIT();
223 }
224 
225 static void
226 read_fault(const atf_tc_t *tc, const char *mp)
227 {
228 	char ch = 123;
229 	int fd;
230 
231 	FSTEST_ENTER();
232 	RL(fd = rump_sys_open("file", O_CREAT | O_RDWR, 0777));
233 	ATF_REQUIRE_EQ(rump_sys_write(fd, &ch, 1), 1);
234 	RL(rump_sys_close(fd));
235 	RL(fd = rump_sys_open("file", O_RDONLY | O_SYNC | O_RSYNC));
236 	ATF_REQUIRE_ERRNO(EFAULT, rump_sys_read(fd, NULL, 1) == -1);
237 	RL(rump_sys_close(fd));
238 	FSTEST_EXIT();
239 }
240 
241 ATF_TC_FSAPPLY(holywrite, "create a sparse file and fill hole");
242 ATF_TC_FSAPPLY(extendfile, "check that extending a file works");
243 ATF_TC_FSAPPLY(extendfile_append, "check that extending a file works "
244 				  "with a append-only fd (PR kern/44307)");
245 ATF_TC_FSAPPLY(overwrite512, "write a 512 byte file twice");
246 ATF_TC_FSAPPLY(overwrite64k, "write a 64k byte file twice");
247 ATF_TC_FSAPPLY(overwrite_trunc, "write 64k + truncate + rewrite");
248 ATF_TC_FSAPPLY(shrinkfile, "shrink file");
249 ATF_TC_FSAPPLY(read_after_unlink, "contents can be read off disk after unlink");
250 ATF_TC_FSAPPLY(wrrd_after_unlink, "file can be written and read after unlink");
251 ATF_TC_FSAPPLY(read_fault, "read at bad address must return EFAULT");
252 
253 ATF_TP_ADD_TCS(tp)
254 {
255 
256 	ATF_TP_FSAPPLY(holywrite);
257 	ATF_TP_FSAPPLY(extendfile);
258 	ATF_TP_FSAPPLY(extendfile_append);
259 	ATF_TP_FSAPPLY(overwrite512);
260 	ATF_TP_FSAPPLY(overwrite64k);
261 	ATF_TP_FSAPPLY(overwrite_trunc);
262 	ATF_TP_FSAPPLY(shrinkfile);
263 	ATF_TP_FSAPPLY(read_after_unlink);
264 	ATF_TP_FSAPPLY(wrrd_after_unlink);
265 	ATF_TP_FSAPPLY(read_fault);
266 
267 	return atf_no_error();
268 }
269