t_vfsops.c revision 314817
1/*	$NetBSD: t_vfsops.c,v 1.12 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 <dirent.h>
34#include <fcntl.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
44static void
45tmount(const atf_tc_t *tc, const char *path)
46{
47
48	return;
49}
50
51static void
52tstatvfs(const atf_tc_t *tc, const char *path)
53{
54	const char *fstype = atf_tc_get_md_var(tc, "X-fs.mntname");
55	struct statvfs svb;
56
57	if (rump_sys_statvfs1(path, &svb, ST_WAIT) == -1)
58		atf_tc_fail_errno("statvfs");
59
60	ATF_REQUIRE(svb.f_namemax > 0 && svb.f_namemax <= MAXNAMLEN);
61	if (!(FSTYPE_PUFFS(tc) || FSTYPE_P2K_FFS(tc)))
62		ATF_REQUIRE_STREQ(svb.f_fstypename, fstype);
63	ATF_REQUIRE_STREQ(svb.f_mntonname, path);
64}
65
66static void
67tsync(const atf_tc_t *tc, const char *path)
68{
69
70	rump_sys_sync();
71}
72
73#define MAGICSTR "just a string, I like A"
74static void
75tfilehandle(const atf_tc_t *tc, const char *path)
76{
77	char fpath[MAXPATHLEN];
78	char buf[sizeof(MAGICSTR)];
79	size_t fhsize;
80	void *fhp;
81	int fd;
82
83	sprintf(fpath, "%s/file", path);
84	fd = rump_sys_open(fpath, O_RDWR | O_CREAT, 0777);
85	if (fd == -1)
86		atf_tc_fail_errno("open");
87
88	if (rump_sys_write(fd, MAGICSTR, sizeof(MAGICSTR)) != sizeof(MAGICSTR))
89		atf_tc_fail("write to file");
90	rump_sys_close(fd);
91
92	/*
93	 * Get file handle size.
94	 * This also weeds out unsupported file systems.
95	 */
96	fhsize = 0;
97	if (rump_sys_getfh(fpath, NULL, &fhsize) == -1) {
98		if (errno == EOPNOTSUPP) {
99			atf_tc_skip("file handles not supported");
100		} else if (errno != E2BIG) {
101			atf_tc_fail_errno("getfh size");
102		}
103	}
104
105	fhp = malloc(fhsize);
106	if (rump_sys_getfh(fpath, fhp, &fhsize) == -1)
107		atf_tc_fail_errno("getfh");
108
109	/* open file based on file handle */
110	fd = rump_sys_fhopen(fhp, fhsize, O_RDONLY);
111	if (fd == -1) {
112		atf_tc_fail_errno("fhopen");
113	}
114
115	/* check that we got the same file */
116	if (rump_sys_read(fd, buf, sizeof(buf)) != sizeof(MAGICSTR))
117		atf_tc_fail("read fhopened file");
118
119	ATF_REQUIRE_STREQ(buf, MAGICSTR);
120
121	rump_sys_close(fd);
122}
123
124#define FNAME "a_file"
125static void
126tfhremove(const atf_tc_t *tc, const char *path)
127{
128	size_t fhsize;
129	void *fhp;
130	int fd;
131
132	RL(rump_sys_chdir(path));
133	RL(fd = rump_sys_open(FNAME, O_RDWR | O_CREAT, 0777));
134	RL(rump_sys_close(fd));
135
136	fhsize = 0;
137	if (rump_sys_getfh(FNAME, NULL, &fhsize) == -1) {
138		if (errno == EOPNOTSUPP) {
139			atf_tc_skip("file handles not supported");
140		} else if (errno != E2BIG) {
141			atf_tc_fail_errno("getfh size");
142		}
143	}
144
145	fhp = malloc(fhsize);
146	RL(rump_sys_getfh(FNAME, fhp, &fhsize));
147	RL(rump_sys_unlink(FNAME));
148
149	if (FSTYPE_LFS(tc))
150		atf_tc_expect_fail("fhopen() for removed file succeeds "
151		    "(PR kern/43745)");
152	ATF_REQUIRE_ERRNO(ESTALE, rump_sys_fhopen(fhp, fhsize, O_RDONLY) == -1);
153	atf_tc_expect_pass();
154
155	RL(rump_sys_chdir("/"));
156}
157#undef FNAME
158
159/*
160 * This test only checks the file system doesn't crash.  We *might*
161 * try a valid file handle.
162 */
163static void
164tfhinval(const atf_tc_t *tc, const char *path)
165{
166	size_t fhsize;
167	void *fhp;
168	unsigned long seed;
169	int fd;
170
171	srandom(seed = time(NULL));
172	printf("RNG seed %lu\n", seed);
173
174	RL(rump_sys_chdir(path));
175	fhsize = 0;
176	if (rump_sys_getfh(".", NULL, &fhsize) == -1) {
177		if (errno == EOPNOTSUPP) {
178			atf_tc_skip("file handles not supported");
179		} else if (errno != E2BIG) {
180			atf_tc_fail_errno("getfh size");
181		}
182	}
183
184	fhp = malloc(fhsize);
185	tests_makegarbage(fhp, fhsize);
186	fd = rump_sys_fhopen(fhp, fhsize, O_RDWR);
187	if (fd != -1)
188		rump_sys_close(fd);
189
190	RL(rump_sys_chdir("/"));
191}
192
193ATF_TC_FSAPPLY(tmount, "mount/unmount");
194ATF_TC_FSAPPLY(tstatvfs, "statvfs");
195ATF_TC_FSAPPLY(tsync, "sync");
196ATF_TC_FSAPPLY(tfilehandle, "file handles");
197ATF_TC_FSAPPLY(tfhremove, "fhtovp for removed file");
198ATF_TC_FSAPPLY(tfhinval, "fhopen invalid filehandle");
199
200ATF_TP_ADD_TCS(tp)
201{
202
203	ATF_TP_FSAPPLY(tmount);
204	ATF_TP_FSAPPLY(tstatvfs);
205	ATF_TP_FSAPPLY(tsync);
206	ATF_TP_FSAPPLY(tfilehandle);
207	ATF_TP_FSAPPLY(tfhremove);
208	ATF_TP_FSAPPLY(tfhinval);
209
210	return atf_no_error();
211}
212