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