xref: /netbsd-src/tests/fs/vfs/t_rwtoro.c (revision 8012ca3f0e0935df89028ef98e60992407bddc93)
1*8012ca3fSmsaitoh /*	$NetBSD: t_rwtoro.c,v 1.2 2020/05/14 08:34:18 msaitoh Exp $	*/
2a9f23b81Shannken 
3a9f23b81Shannken /*-
4a9f23b81Shannken  * Copyright (c) 2017 The NetBSD Foundation, Inc.
5a9f23b81Shannken  * All rights reserved.
6a9f23b81Shannken  *
7a9f23b81Shannken  * Redistribution and use in source and binary forms, with or without
8a9f23b81Shannken  * modification, are permitted provided that the following conditions
9a9f23b81Shannken  * are met:
10a9f23b81Shannken  * 1. Redistributions of source code must retain the above copyright
11a9f23b81Shannken  *    notice, this list of conditions and the following disclaimer.
12a9f23b81Shannken  * 2. Redistributions in binary form must reproduce the above copyright
13a9f23b81Shannken  *    notice, this list of conditions and the following disclaimer in the
14a9f23b81Shannken  *    documentation and/or other materials provided with the distribution.
15a9f23b81Shannken  *
16a9f23b81Shannken  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17a9f23b81Shannken  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18a9f23b81Shannken  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19a9f23b81Shannken  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20a9f23b81Shannken  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21a9f23b81Shannken  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22a9f23b81Shannken  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23a9f23b81Shannken  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24a9f23b81Shannken  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25a9f23b81Shannken  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26a9f23b81Shannken  * POSSIBILITY OF SUCH DAMAGE.
27a9f23b81Shannken  */
28a9f23b81Shannken 
29a9f23b81Shannken #include <sys/types.h>
30a9f23b81Shannken #include <sys/mount.h>
31a9f23b81Shannken #include <sys/stat.h>
32a9f23b81Shannken #include <sys/statvfs.h>
33a9f23b81Shannken 
34a9f23b81Shannken #include <atf-c.h>
35a9f23b81Shannken #include <fcntl.h>
36a9f23b81Shannken #include <libgen.h>
37a9f23b81Shannken #include <stdlib.h>
38a9f23b81Shannken #include <unistd.h>
39a9f23b81Shannken 
40a9f23b81Shannken #include <rump/rump_syscalls.h>
41a9f23b81Shannken #include <rump/rump.h>
42a9f23b81Shannken 
43a9f23b81Shannken #include <miscfs/nullfs/null.h>
44a9f23b81Shannken #include <fs/tmpfs/tmpfs_args.h>
45a9f23b81Shannken 
46a9f23b81Shannken #include "../common/h_fsmacros.h"
47a9f23b81Shannken #include "../../h_macros.h"
48a9f23b81Shannken 
49a9f23b81Shannken static const char *unsupported = "fs does not support r/o remount";
50a9f23b81Shannken static char file_path[MAXPATHLEN];
51a9f23b81Shannken static int file_fd;
52a9f23b81Shannken 
53a9f23b81Shannken /*
54a9f23b81Shannken  * Remount the filesystem read-only and test errno.
55a9f23b81Shannken  * Skip filesystems that don't implement read-write -> read-only.
56a9f23b81Shannken  */
57a9f23b81Shannken static void
remount_ro(const atf_tc_t * tc,const char * mp,int expected_errno)58a9f23b81Shannken remount_ro(const atf_tc_t *tc, const char *mp, int expected_errno)
59a9f23b81Shannken {
60a9f23b81Shannken 	int error;
61a9f23b81Shannken 	union {
62a9f23b81Shannken 		struct tmpfs_args tmpfs;
63a9f23b81Shannken 		char data[4095];
64a9f23b81Shannken 	} mount_args;
65a9f23b81Shannken 	int mount_args_length;
66a9f23b81Shannken 	struct statvfs sbuf;
67a9f23b81Shannken 
68a9f23b81Shannken 	if (FSTYPE_ZFS(tc))
69a9f23b81Shannken 		atf_tc_skip("%s", unsupported);
70a9f23b81Shannken 
71a9f23b81Shannken 	/* Prepare mount arguments. */
72a9f23b81Shannken 	RL(rump_sys_statvfs1(mp, &sbuf, ST_WAIT));
73a9f23b81Shannken 	mount_args_length = sizeof(mount_args);
74a9f23b81Shannken 	memset(&mount_args, 0, mount_args_length);
75a9f23b81Shannken 	if (FSTYPE_TMPFS(tc))
76a9f23b81Shannken 		mount_args.tmpfs.ta_version = TMPFS_ARGS_VERSION;
77a9f23b81Shannken 	mount_args_length = rump_sys_mount(sbuf.f_fstypename, mp, MNT_GETARGS,
78a9f23b81Shannken 	    &mount_args, mount_args_length);
79a9f23b81Shannken 	ATF_CHECK(mount_args_length >= 0);
80a9f23b81Shannken 
81a9f23b81Shannken 	/* Remount and test result. */
82a9f23b81Shannken 	error = rump_sys_mount(sbuf.f_fstypename, mp, MNT_UPDATE | MNT_RDONLY,
83a9f23b81Shannken 	    &mount_args, mount_args_length);
84a9f23b81Shannken 	if (errno == EOPNOTSUPP)
85a9f23b81Shannken 		atf_tc_skip("%s", unsupported);
86a9f23b81Shannken 	if (expected_errno == 0)
87a9f23b81Shannken 		ATF_CHECK(error == 0);
88a9f23b81Shannken 	else
89a9f23b81Shannken 		ATF_CHECK_ERRNO(expected_errno, error == -1);
90a9f23b81Shannken }
91a9f23b81Shannken 
92a9f23b81Shannken static void
open_file_ro(const char * prefix)93a9f23b81Shannken open_file_ro(const char *prefix)
94a9f23b81Shannken {
95a9f23b81Shannken 
96a9f23b81Shannken 	snprintf(file_path, sizeof(file_path), "%s/file", prefix);
97a9f23b81Shannken 	RL(file_fd = rump_sys_open(file_path, O_CREAT | O_RDWR, 0777));
98a9f23b81Shannken 	RL(rump_sys_close(file_fd));
99a9f23b81Shannken 	RL(file_fd = rump_sys_open(file_path, O_RDONLY));
100a9f23b81Shannken }
101a9f23b81Shannken 
102a9f23b81Shannken static void
open_file_ro_unlink(const char * prefix)103a9f23b81Shannken open_file_ro_unlink(const char *prefix)
104a9f23b81Shannken {
105a9f23b81Shannken 
106a9f23b81Shannken 	snprintf(file_path, sizeof(file_path), "%s/file", prefix);
107a9f23b81Shannken 	RL(file_fd = rump_sys_open(file_path, O_CREAT | O_RDWR, 0777));
108a9f23b81Shannken 	RL(rump_sys_close(file_fd));
109a9f23b81Shannken 	RL(file_fd = rump_sys_open(file_path, O_RDONLY));
110a9f23b81Shannken 	RL(rump_sys_unlink(file_path));
111a9f23b81Shannken }
112a9f23b81Shannken 
113a9f23b81Shannken static void
open_file_rw(const char * prefix)114a9f23b81Shannken open_file_rw(const char *prefix)
115a9f23b81Shannken {
116a9f23b81Shannken 
117a9f23b81Shannken 	snprintf(file_path, sizeof(file_path), "%s/file", prefix);
118a9f23b81Shannken 	RL(file_fd = rump_sys_open(file_path, O_CREAT | O_RDWR, 0777));
119a9f23b81Shannken }
120a9f23b81Shannken 
121a9f23b81Shannken static void
close_file(const char * unused)122a9f23b81Shannken close_file(const char *unused)
123a9f23b81Shannken {
124a9f23b81Shannken 
125a9f23b81Shannken 	RL(rump_sys_close(file_fd));
126a9f23b81Shannken }
127a9f23b81Shannken 
128a9f23b81Shannken static void
basic_test(const atf_tc_t * tc,const char * mp,int expected_errno,bool use_layer,void (* pre)(const char *),void (* post)(const char *))129a9f23b81Shannken basic_test(const atf_tc_t *tc, const char *mp, int expected_errno,
130a9f23b81Shannken     bool use_layer, void (*pre)(const char *), void (*post)(const char *))
131a9f23b81Shannken {
132a9f23b81Shannken 	const char *null_mount = "/nullm";
133a9f23b81Shannken 	struct null_args nargs;
134a9f23b81Shannken 
135a9f23b81Shannken 	if (use_layer) {
136a9f23b81Shannken 		RL(rump_sys_mkdir(null_mount, 0777));
137a9f23b81Shannken 		memset(&nargs, 0, sizeof(nargs));
138*8012ca3fSmsaitoh 		nargs.nulla_target = __UNCONST(mp);
139a9f23b81Shannken 		RL(rump_sys_mount(MOUNT_NULL, null_mount, 0,
140a9f23b81Shannken 		    &nargs, sizeof(nargs)));
141a9f23b81Shannken 	}
142a9f23b81Shannken 	if (pre)
143a9f23b81Shannken 		(*pre)(use_layer ? null_mount : mp);
144a9f23b81Shannken 	remount_ro(tc, mp, expected_errno);
145a9f23b81Shannken 	if (post)
146a9f23b81Shannken 		(*post)(use_layer ? null_mount : mp);
147a9f23b81Shannken 	if (use_layer)
148a9f23b81Shannken 		RL(rump_sys_unmount(null_mount, 0));
149a9f23b81Shannken }
150a9f23b81Shannken 
151a9f23b81Shannken static void
noneopen(const atf_tc_t * tc,const char * mp)152a9f23b81Shannken noneopen(const atf_tc_t *tc, const char *mp)
153a9f23b81Shannken {
154a9f23b81Shannken 
155a9f23b81Shannken 	basic_test(tc, mp, 0, false, NULL, NULL);
156a9f23b81Shannken }
157a9f23b81Shannken 
158a9f23b81Shannken static void
readopen(const atf_tc_t * tc,const char * mp)159a9f23b81Shannken readopen(const atf_tc_t *tc, const char *mp)
160a9f23b81Shannken {
161a9f23b81Shannken 
162a9f23b81Shannken 	basic_test(tc, mp, 0, false, open_file_ro, close_file);
163a9f23b81Shannken }
164a9f23b81Shannken 
165a9f23b81Shannken static void
writeopen(const atf_tc_t * tc,const char * mp)166a9f23b81Shannken writeopen(const atf_tc_t *tc, const char *mp)
167a9f23b81Shannken {
168a9f23b81Shannken 
169a9f23b81Shannken 	basic_test(tc, mp, EBUSY, false, open_file_rw, close_file);
170a9f23b81Shannken }
171a9f23b81Shannken 
172a9f23b81Shannken static void
read_unlinked(const atf_tc_t * tc,const char * mp)173a9f23b81Shannken read_unlinked(const atf_tc_t *tc, const char *mp)
174a9f23b81Shannken {
175a9f23b81Shannken 
176a9f23b81Shannken 	basic_test(tc, mp, EBUSY, false, open_file_ro_unlink, close_file);
177a9f23b81Shannken }
178a9f23b81Shannken 
179a9f23b81Shannken static void
layer_noneopen(const atf_tc_t * tc,const char * mp)180a9f23b81Shannken layer_noneopen(const atf_tc_t *tc, const char *mp)
181a9f23b81Shannken {
182a9f23b81Shannken 
183a9f23b81Shannken 	basic_test(tc, mp, 0, true, NULL, NULL);
184a9f23b81Shannken }
185a9f23b81Shannken 
186a9f23b81Shannken static void
layer_readopen(const atf_tc_t * tc,const char * mp)187a9f23b81Shannken layer_readopen(const atf_tc_t *tc, const char *mp)
188a9f23b81Shannken {
189a9f23b81Shannken 
190a9f23b81Shannken 	basic_test(tc, mp, 0, true, open_file_ro, close_file);
191a9f23b81Shannken }
192a9f23b81Shannken 
193a9f23b81Shannken static void
layer_writeopen(const atf_tc_t * tc,const char * mp)194a9f23b81Shannken layer_writeopen(const atf_tc_t *tc, const char *mp)
195a9f23b81Shannken {
196a9f23b81Shannken 
197a9f23b81Shannken 	basic_test(tc, mp, EBUSY, true, open_file_rw, close_file);
198a9f23b81Shannken }
199a9f23b81Shannken 
200a9f23b81Shannken static void
layer_read_unlinked(const atf_tc_t * tc,const char * mp)201a9f23b81Shannken layer_read_unlinked(const atf_tc_t *tc, const char *mp)
202a9f23b81Shannken {
203a9f23b81Shannken 
204a9f23b81Shannken 	basic_test(tc, mp, EBUSY, true, open_file_ro_unlink, close_file);
205a9f23b81Shannken }
206a9f23b81Shannken 
207a9f23b81Shannken ATF_TC_FSAPPLY(noneopen, "remount r/o with no file open");
208a9f23b81Shannken ATF_TC_FSAPPLY(readopen, "remount r/o with file open for reading");
209a9f23b81Shannken ATF_TC_FSAPPLY(writeopen, "remount r/o with file open for writing");
210a9f23b81Shannken ATF_TC_FSAPPLY(read_unlinked,
211a9f23b81Shannken     "remount r/o with unlinked file open for reading");
212a9f23b81Shannken ATF_TC_FSAPPLY(layer_noneopen, "remount r/o with no file open on layer");
213a9f23b81Shannken ATF_TC_FSAPPLY(layer_readopen,
214a9f23b81Shannken     "remount r/o with file open for reading on layer");
215a9f23b81Shannken ATF_TC_FSAPPLY(layer_writeopen,
216a9f23b81Shannken     "remount r/o with file open for writing on layer");
217a9f23b81Shannken ATF_TC_FSAPPLY(layer_read_unlinked,
218a9f23b81Shannken     "remount r/o with unlinked file open for reading on layer");
219a9f23b81Shannken 
ATF_TP_ADD_TCS(tp)220a9f23b81Shannken ATF_TP_ADD_TCS(tp)
221a9f23b81Shannken {
222a9f23b81Shannken 
223a9f23b81Shannken 	ATF_TP_FSAPPLY(noneopen);
224a9f23b81Shannken 	ATF_TP_FSAPPLY(readopen);
225a9f23b81Shannken 	ATF_TP_FSAPPLY(writeopen);
226a9f23b81Shannken 	ATF_TP_FSAPPLY(read_unlinked);
227a9f23b81Shannken 	ATF_TP_FSAPPLY(layer_noneopen);
228a9f23b81Shannken 	ATF_TP_FSAPPLY(layer_readopen);
229a9f23b81Shannken 	ATF_TP_FSAPPLY(layer_writeopen);
230a9f23b81Shannken 	ATF_TP_FSAPPLY(layer_read_unlinked);
231a9f23b81Shannken 
232a9f23b81Shannken 	return atf_no_error();
233a9f23b81Shannken }
234