| @@ -1,351 +1,361 @@ | | | @@ -1,351 +1,361 @@ |
1 | /* $NetBSD: fstest_puffs.c,v 1.3 2010/09/01 19:41:27 pooka Exp $ */ | | 1 | /* $NetBSD: fstest_puffs.c,v 1.4 2010/10/31 22:05:35 pooka Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
16 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | | 16 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | | 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 | * SUCH DAMAGE. | | 25 | * SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | #include <sys/types.h> | | 28 | #include <sys/types.h> |
29 | #include <sys/mount.h> | | 29 | #include <sys/mount.h> |
30 | #include <sys/socket.h> | | 30 | #include <sys/socket.h> |
31 | #include <sys/statvfs.h> | | 31 | #include <sys/statvfs.h> |
32 | #include <sys/wait.h> | | 32 | #include <sys/wait.h> |
33 | | | 33 | |
34 | #include <assert.h> | | 34 | #include <assert.h> |
35 | #include <atf-c.h> | | 35 | #include <atf-c.h> |
36 | #include <err.h> | | 36 | #include <err.h> |
37 | #include <errno.h> | | 37 | #include <errno.h> |
38 | #include <fcntl.h> | | 38 | #include <fcntl.h> |
39 | #include <pthread.h> | | 39 | #include <pthread.h> |
40 | #include <puffs.h> | | 40 | #include <puffs.h> |
41 | #include <puffsdump.h> | | 41 | #include <puffsdump.h> |
42 | #include <signal.h> | | 42 | #include <signal.h> |
43 | #include <stdio.h> | | 43 | #include <stdio.h> |
44 | #include <unistd.h> | | 44 | #include <unistd.h> |
45 | #include <string.h> | | 45 | #include <string.h> |
46 | #include <stdlib.h> | | 46 | #include <stdlib.h> |
47 | | | 47 | |
48 | #include <rump/rump.h> | | 48 | #include <rump/rump.h> |
49 | #include <rump/rump_syscalls.h> | | 49 | #include <rump/rump_syscalls.h> |
50 | | | 50 | |
51 | #include "h_fsmacros.h" | | 51 | #include "h_fsmacros.h" |
52 | | | 52 | |
53 | #define BUFSIZE (128*1024) | | 53 | #define BUFSIZE (128*1024) |
54 | #define DTFS_DUMP "-o","dump" | | 54 | #define DTFS_DUMP "-o","dump" |
55 | | | 55 | |
56 | /* | | 56 | /* |
57 | * Threads which shovel data between comfd and /dev/puffs. | | 57 | * Threads which shovel data between comfd and /dev/puffs. |
58 | * (cannot use polling since fd's are in different namespaces) | | 58 | * (cannot use polling since fd's are in different namespaces) |
59 | */ | | 59 | */ |
60 | static void * | | 60 | static void * |
61 | readshovel(void *arg) | | 61 | readshovel(void *arg) |
62 | { | | 62 | { |
63 | struct putter_hdr *phdr; | | 63 | struct putter_hdr *phdr; |
64 | struct puffs_req *preq; | | 64 | struct puffs_req *preq; |
65 | struct puffstestargs *args = arg; | | 65 | struct puffstestargs *args = arg; |
66 | char buf[BUFSIZE]; | | 66 | char buf[BUFSIZE]; |
67 | int comfd, puffsfd; | | 67 | int comfd, puffsfd; |
68 | | | 68 | |
69 | comfd = args->pta_servfd; | | 69 | comfd = args->pta_servfd; |
70 | puffsfd = args->pta_rumpfd; | | 70 | puffsfd = args->pta_rumpfd; |
71 | | | 71 | |
72 | phdr = (void *)buf; | | 72 | phdr = (void *)buf; |
73 | preq = (void *)buf; | | 73 | preq = (void *)buf; |
74 | | | 74 | |
75 | rump_pub_lwproc_newlwp(0); | | 75 | rump_pub_lwproc_newlwp(1); |
76 | | | 76 | |
77 | for (;;) { | | 77 | for (;;) { |
78 | ssize_t n; | | 78 | ssize_t n; |
79 | | | 79 | |
80 | n = rump_sys_read(puffsfd, buf, sizeof(*phdr)); | | 80 | n = rump_sys_read(puffsfd, buf, sizeof(*phdr)); |
81 | if (n <= 0) | | 81 | if (n <= 0) { |
| | | 82 | fprintf(stderr, "readshovel r1 %d / %d\n", n, errno); |
82 | break; | | 83 | break; |
| | | 84 | } |
83 | | | 85 | |
84 | assert(phdr->pth_framelen < BUFSIZE); | | 86 | assert(phdr->pth_framelen < BUFSIZE); |
85 | n = rump_sys_read(puffsfd, buf+sizeof(*phdr), | | 87 | n = rump_sys_read(puffsfd, buf+sizeof(*phdr), |
86 | phdr->pth_framelen - sizeof(*phdr)); | | 88 | phdr->pth_framelen - sizeof(*phdr)); |
87 | if (n <= 0) | | 89 | if (n <= 0) { |
| | | 90 | fprintf(stderr, "readshovel r2 %d / %d\n", n, errno); |
88 | break; | | 91 | break; |
| | | 92 | } |
89 | | | 93 | |
90 | /* Analyze request */ | | 94 | /* Analyze request */ |
91 | if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) { | | 95 | if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) { |
92 | assert(preq->preq_optype < PUFFS_VFS_MAX); | | 96 | assert(preq->preq_optype < PUFFS_VFS_MAX); |
93 | args->pta_vfs_toserv_ops[preq->preq_optype]++; | | 97 | args->pta_vfs_toserv_ops[preq->preq_optype]++; |
94 | } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) { | | 98 | } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) { |
95 | assert(preq->preq_optype < PUFFS_VN_MAX); | | 99 | assert(preq->preq_optype < PUFFS_VN_MAX); |
96 | args->pta_vn_toserv_ops[preq->preq_optype]++; | | 100 | args->pta_vn_toserv_ops[preq->preq_optype]++; |
97 | } | | 101 | } |
98 | | | 102 | |
99 | n = phdr->pth_framelen; | | 103 | n = phdr->pth_framelen; |
100 | if (write(comfd, buf, n) != n) | | 104 | if (write(comfd, buf, n) != n) { |
| | | 105 | fprintf(stderr, "readshovel write %d / %d\n", n, errno); |
101 | break; | | 106 | break; |
| | | 107 | } |
102 | } | | 108 | } |
103 | | | 109 | |
104 | return NULL; | | 110 | abort(); |
105 | } | | 111 | } |
106 | | | 112 | |
107 | static void * | | 113 | static void * |
108 | writeshovel(void *arg) | | 114 | writeshovel(void *arg) |
109 | { | | 115 | { |
110 | struct puffstestargs *args = arg; | | 116 | struct puffstestargs *args = arg; |
111 | struct putter_hdr *phdr; | | 117 | struct putter_hdr *phdr; |
112 | char buf[BUFSIZE]; | | 118 | char buf[BUFSIZE]; |
113 | size_t toread; | | 119 | size_t toread; |
114 | int comfd, puffsfd; | | 120 | int comfd, puffsfd; |
115 | | | 121 | |
116 | rump_pub_lwproc_newlwp(0); | | 122 | rump_pub_lwproc_newlwp(1); |
117 | | | 123 | |
118 | comfd = args->pta_servfd; | | 124 | comfd = args->pta_servfd; |
119 | puffsfd = args->pta_rumpfd; | | 125 | puffsfd = args->pta_rumpfd; |
120 | | | 126 | |
121 | phdr = (struct putter_hdr *)buf; | | 127 | phdr = (struct putter_hdr *)buf; |
122 | | | 128 | |
123 | for (;;) { | | 129 | for (;;) { |
124 | uint64_t off; | | 130 | uint64_t off; |
125 | ssize_t n; | | 131 | ssize_t n; |
126 | | | 132 | |
127 | /* | | 133 | /* |
128 | * Need to write everything to the "kernel" in one chunk, | | 134 | * Need to write everything to the "kernel" in one chunk, |
129 | * so make sure we have it here. | | 135 | * so make sure we have it here. |
130 | */ | | 136 | */ |
131 | off = 0; | | 137 | off = 0; |
132 | toread = sizeof(struct putter_hdr); | | 138 | toread = sizeof(struct putter_hdr); |
133 | assert(toread < BUFSIZE); | | 139 | assert(toread < BUFSIZE); |
134 | do { | | 140 | do { |
135 | n = read(comfd, buf+off, toread); | | 141 | n = read(comfd, buf+off, toread); |
136 | if (n <= 0) { | | 142 | if (n <= 0) { |
| | | 143 | fprintf(stderr, "writeshovel read %d / %d\n", |
| | | 144 | n, errno); |
137 | break; | | 145 | break; |
138 | } | | 146 | } |
139 | off += n; | | 147 | off += n; |
140 | if (off >= sizeof(struct putter_hdr)) | | 148 | if (off >= sizeof(struct putter_hdr)) |
141 | toread = phdr->pth_framelen - off; | | 149 | toread = phdr->pth_framelen - off; |
142 | else | | 150 | else |
143 | toread = off - sizeof(struct putter_hdr); | | 151 | toread = off - sizeof(struct putter_hdr); |
144 | } while (toread); | | 152 | } while (toread); |
145 | | | 153 | |
146 | n = rump_sys_write(puffsfd, buf, phdr->pth_framelen); | | 154 | n = rump_sys_write(puffsfd, buf, phdr->pth_framelen); |
147 | if ((size_t)n != phdr->pth_framelen) | | 155 | if ((size_t)n != phdr->pth_framelen) { |
| | | 156 | fprintf(stderr, "writeshovel wr %d / %d\n", n, errno); |
148 | break; | | 157 | break; |
| | | 158 | } |
149 | } | | 159 | } |
150 | | | 160 | |
151 | return NULL; | | 161 | abort(); |
152 | } | | 162 | } |
153 | | | 163 | |
154 | static void | | 164 | static void |
155 | rumpshovels(struct puffstestargs *args) | | 165 | rumpshovels(struct puffstestargs *args) |
156 | { | | 166 | { |
157 | pthread_t pt; | | 167 | pthread_t pt; |
158 | int rv; | | 168 | int rv; |
159 | | | 169 | |
160 | if ((rv = rump_init()) == -1) | | 170 | if ((rv = rump_init()) == -1) |
161 | err(1, "rump_init"); | | 171 | err(1, "rump_init"); |
162 | | | 172 | |
163 | if (pthread_create(&pt, NULL, readshovel, args) == -1) | | 173 | if (pthread_create(&pt, NULL, readshovel, args) == -1) |
164 | err(1, "read shovel"); | | 174 | err(1, "read shovel"); |
165 | pthread_detach(pt); | | 175 | pthread_detach(pt); |
166 | | | 176 | |
167 | if (pthread_create(&pt, NULL, writeshovel, args) == -1) | | 177 | if (pthread_create(&pt, NULL, writeshovel, args) == -1) |
168 | err(1, "write shovel"); | | 178 | err(1, "write shovel"); |
169 | pthread_detach(pt); | | 179 | pthread_detach(pt); |
170 | } | | 180 | } |
171 | | | 181 | |
172 | static void | | 182 | static void |
173 | childfail(int sign) | | 183 | childfail(int sign) |
174 | { | | 184 | { |
175 | | | 185 | |
176 | atf_tc_fail("child died"); /* almost signal-safe */ | | 186 | atf_tc_fail("child died"); /* almost signal-safe */ |
177 | } | | 187 | } |
178 | | | 188 | |
179 | struct puffstestargs *theargs; /* XXX */ | | 189 | struct puffstestargs *theargs; /* XXX */ |
180 | | | 190 | |
181 | /* XXX: we don't support size */ | | 191 | /* XXX: we don't support size */ |
182 | int | | 192 | int |
183 | puffs_fstest_newfs(const atf_tc_t *tc, void **argp, | | 193 | puffs_fstest_newfs(const atf_tc_t *tc, void **argp, |
184 | const char *image, off_t size, void *fspriv) | | 194 | const char *image, off_t size, void *fspriv) |
185 | { | | 195 | { |
186 | struct puffstestargs *args; | | 196 | struct puffstestargs *args; |
187 | char dtfs_path[MAXPATHLEN]; | | 197 | char dtfs_path[MAXPATHLEN]; |
188 | char *dtfsargv[6]; | | 198 | char *dtfsargv[6]; |
189 | char **theargv; | | 199 | char **theargv; |
190 | pid_t childpid; | | 200 | pid_t childpid; |
191 | int *pflags; | | 201 | int *pflags; |
192 | char comfd[16]; | | 202 | char comfd[16]; |
193 | int sv[2]; | | 203 | int sv[2]; |
194 | int mntflags; | | 204 | int mntflags; |
195 | size_t len; | | 205 | size_t len; |
196 | ssize_t n; | | 206 | ssize_t n; |
197 | | | 207 | |
198 | *argp = NULL; | | 208 | *argp = NULL; |
199 | | | 209 | |
200 | args = malloc(sizeof(*args)); | | 210 | args = malloc(sizeof(*args)); |
201 | if (args == NULL) | | 211 | if (args == NULL) |
202 | return errno; | | 212 | return errno; |
203 | | | 213 | |
204 | pflags = &args->pta_pflags; | | 214 | pflags = &args->pta_pflags; |
205 | | | 215 | |
206 | /* build dtfs exec path from atf test dir */ | | 216 | /* build dtfs exec path from atf test dir */ |
207 | sprintf(dtfs_path, "%s/../puffs/h_dtfs/h_dtfs", | | 217 | sprintf(dtfs_path, "%s/../puffs/h_dtfs/h_dtfs", |
208 | atf_tc_get_config_var(tc, "srcdir")); | | 218 | atf_tc_get_config_var(tc, "srcdir")); |
209 | | | 219 | |
210 | if (fspriv) { | | 220 | if (fspriv) { |
211 | theargv = fspriv; | | 221 | theargv = fspriv; |
212 | theargv[0] = dtfs_path; | | 222 | theargv[0] = dtfs_path; |
213 | } else { | | 223 | } else { |
214 | dtfsargv[0] = dtfs_path; | | 224 | dtfsargv[0] = dtfs_path; |
215 | dtfsargv[1] = __UNCONST("-i"); | | 225 | dtfsargv[1] = __UNCONST("-i"); |
216 | dtfsargv[2] = __UNCONST("-s"); | | 226 | dtfsargv[2] = __UNCONST("-s"); |
217 | dtfsargv[3] = __UNCONST("dtfs"); | | 227 | dtfsargv[3] = __UNCONST("dtfs"); |
218 | dtfsargv[4] = __UNCONST("fictional"); | | 228 | dtfsargv[4] = __UNCONST("fictional"); |
219 | dtfsargv[5] = NULL; | | 229 | dtfsargv[5] = NULL; |
220 | | | 230 | |
221 | theargv = dtfsargv; | | 231 | theargv = dtfsargv; |
222 | } | | 232 | } |
223 | | | 233 | |
224 | /* Create sucketpair for communication with the real file server */ | | 234 | /* Create sucketpair for communication with the real file server */ |
225 | if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) == -1) | | 235 | if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) == -1) |
226 | return errno; | | 236 | return errno; |
227 | | | 237 | |
228 | signal(SIGCHLD, childfail); | | 238 | signal(SIGCHLD, childfail); |
229 | | | 239 | |
230 | switch ((childpid = fork())) { | | 240 | switch ((childpid = fork())) { |
231 | case 0: | | 241 | case 0: |
232 | close(sv[1]); | | 242 | close(sv[1]); |
233 | snprintf(comfd, sizeof(sv[0]), "%d", sv[0]); | | 243 | snprintf(comfd, sizeof(sv[0]), "%d", sv[0]); |
234 | if (setenv("PUFFS_COMFD", comfd, 1) == -1) | | 244 | if (setenv("PUFFS_COMFD", comfd, 1) == -1) |
235 | return errno; | | 245 | return errno; |
236 | | | 246 | |
237 | if (execvp(theargv[0], theargv) == -1) | | 247 | if (execvp(theargv[0], theargv) == -1) |
238 | return errno; | | 248 | return errno; |
239 | case -1: | | 249 | case -1: |
240 | return errno; | | 250 | return errno; |
241 | default: | | 251 | default: |
242 | close(sv[0]); | | 252 | close(sv[0]); |
243 | break; | | 253 | break; |
244 | } | | 254 | } |
245 | | | 255 | |
246 | /* read args */ | | 256 | /* read args */ |
247 | if ((n = read(sv[1], &len, sizeof(len))) != sizeof(len)) | | 257 | if ((n = read(sv[1], &len, sizeof(len))) != sizeof(len)) |
248 | err(1, "mp 1 %zd", n); | | 258 | err(1, "mp 1 %zd", n); |
249 | if (len > MAXPATHLEN) | | 259 | if (len > MAXPATHLEN) |
250 | err(1, "mntpath > MAXPATHLEN"); | | 260 | err(1, "mntpath > MAXPATHLEN"); |
251 | if ((size_t)read(sv[1], args->pta_dir, len) != len) | | 261 | if ((size_t)read(sv[1], args->pta_dir, len) != len) |
252 | err(1, "mp 2"); | | 262 | err(1, "mp 2"); |
253 | if (read(sv[1], &len, sizeof(len)) != sizeof(len)) | | 263 | if (read(sv[1], &len, sizeof(len)) != sizeof(len)) |
254 | err(1, "fn 1"); | | 264 | err(1, "fn 1"); |
255 | if (len > MAXPATHLEN) | | 265 | if (len > MAXPATHLEN) |
256 | err(1, "devpath > MAXPATHLEN"); | | 266 | err(1, "devpath > MAXPATHLEN"); |
257 | if ((size_t)read(sv[1], args->pta_dev, len) != len) | | 267 | if ((size_t)read(sv[1], args->pta_dev, len) != len) |
258 | err(1, "fn 2"); | | 268 | err(1, "fn 2"); |
259 | if (read(sv[1], &mntflags, sizeof(mntflags)) != sizeof(mntflags)) | | 269 | if (read(sv[1], &mntflags, sizeof(mntflags)) != sizeof(mntflags)) |
260 | err(1, "mntflags"); | | 270 | err(1, "mntflags"); |
261 | if (read(sv[1], &args->pta_pargslen, sizeof(args->pta_pargslen)) | | 271 | if (read(sv[1], &args->pta_pargslen, sizeof(args->pta_pargslen)) |
262 | != sizeof(args->pta_pargslen)) | | 272 | != sizeof(args->pta_pargslen)) |
263 | err(1, "puffstest_args len"); | | 273 | err(1, "puffstest_args len"); |
264 | args->pta_pargs = malloc(args->pta_pargslen); | | 274 | args->pta_pargs = malloc(args->pta_pargslen); |
265 | if (args->pta_pargs == NULL) | | 275 | if (args->pta_pargs == NULL) |
266 | err(1, "malloc"); | | 276 | err(1, "malloc"); |
267 | if (read(sv[1], args->pta_pargs, args->pta_pargslen) | | 277 | if (read(sv[1], args->pta_pargs, args->pta_pargslen) |
268 | != (ssize_t)args->pta_pargslen) | | 278 | != (ssize_t)args->pta_pargslen) |
269 | err(1, "puffstest_args"); | | 279 | err(1, "puffstest_args"); |
270 | if (read(sv[1], pflags, sizeof(*pflags)) != sizeof(*pflags)) | | 280 | if (read(sv[1], pflags, sizeof(*pflags)) != sizeof(*pflags)) |
271 | err(1, "pflags"); | | 281 | err(1, "pflags"); |
272 | | | 282 | |
273 | args->pta_childpid = childpid; | | 283 | args->pta_childpid = childpid; |
274 | args->pta_servfd = sv[1]; | | 284 | args->pta_servfd = sv[1]; |
275 | strlcpy(args->pta_dev, image, sizeof(args->pta_dev)); | | 285 | strlcpy(args->pta_dev, image, sizeof(args->pta_dev)); |
276 | | | 286 | |
277 | *argp = theargs = args; | | 287 | *argp = theargs = args; |
278 | | | 288 | |
279 | return 0; | | 289 | return 0; |
280 | } | | 290 | } |
281 | | | 291 | |
282 | int | | 292 | int |
283 | puffs_fstest_mount(const atf_tc_t *tc, void *arg, const char *path, int flags) | | 293 | puffs_fstest_mount(const atf_tc_t *tc, void *arg, const char *path, int flags) |
284 | { | | 294 | { |
285 | struct puffstestargs *pargs = arg; | | 295 | struct puffstestargs *pargs = arg; |
286 | int fd; | | 296 | int fd; |
287 | | | 297 | |
288 | rump_init(); | | 298 | rump_init(); |
289 | fd = rump_sys_open("/dev/puffs", O_RDWR); | | 299 | fd = rump_sys_open("/dev/puffs", O_RDWR); |
290 | if (fd == -1) | | 300 | if (fd == -1) |
291 | return fd; | | 301 | return fd; |
292 | | | 302 | |
293 | #if 0 | | 303 | #if 0 |
294 | pa->pa_fd = fd; | | 304 | pa->pa_fd = fd; |
295 | #else | | 305 | #else |
296 | assert(fd == 0); /* XXX: FIXME */ | | 306 | assert(fd == 0); /* XXX: FIXME */ |
297 | #endif | | 307 | #endif |
298 | | | 308 | |
299 | if (rump_sys_mkdir(path, 0777) == -1) | | 309 | if (rump_sys_mkdir(path, 0777) == -1) |
300 | return -1; | | 310 | return -1; |
301 | | | 311 | |
302 | if (rump_sys_mount(MOUNT_PUFFS, path, flags, | | 312 | if (rump_sys_mount(MOUNT_PUFFS, path, flags, |
303 | pargs->pta_pargs, pargs->pta_pargslen) == -1) { | | 313 | pargs->pta_pargs, pargs->pta_pargslen) == -1) { |
304 | /* apply "to kill a child" to avoid atf hang (kludge) */ | | 314 | /* apply "to kill a child" to avoid atf hang (kludge) */ |
305 | kill(pargs->pta_childpid, SIGKILL); | | 315 | kill(pargs->pta_childpid, SIGKILL); |
306 | return -1; | | 316 | return -1; |
307 | } | | 317 | } |
308 | | | 318 | |
309 | pargs->pta_rumpfd = fd; | | 319 | pargs->pta_rumpfd = fd; |
310 | rumpshovels(pargs); | | 320 | rumpshovels(pargs); |
311 | | | 321 | |
312 | return 0; | | 322 | return 0; |
313 | } | | 323 | } |
314 | | | 324 | |
315 | int | | 325 | int |
316 | puffs_fstest_delfs(const atf_tc_t *tc, void *arg) | | 326 | puffs_fstest_delfs(const atf_tc_t *tc, void *arg) |
317 | { | | 327 | { |
318 | | | 328 | |
319 | /* useless ... */ | | 329 | /* useless ... */ |
320 | return 0; | | 330 | return 0; |
321 | } | | 331 | } |
322 | | | 332 | |
323 | int | | 333 | int |
324 | puffs_fstest_unmount(const atf_tc_t *tc, const char *path, int flags) | | 334 | puffs_fstest_unmount(const atf_tc_t *tc, const char *path, int flags) |
325 | { | | 335 | { |
326 | struct puffstestargs *pargs = theargs; | | 336 | struct puffstestargs *pargs = theargs; |
327 | int status; | | 337 | int status; |
328 | int rv; | | 338 | int rv; |
329 | | | 339 | |
330 | /* ok, child might exit here */ | | 340 | /* ok, child might exit here */ |
331 | signal(SIGCHLD, SIG_IGN); | | 341 | signal(SIGCHLD, SIG_IGN); |
332 | | | 342 | |
333 | rv = rump_sys_unmount(path, flags); | | 343 | rv = rump_sys_unmount(path, flags); |
334 | if (rv) | | 344 | if (rv) |
335 | return rv; | | 345 | return rv; |
336 | | | 346 | |
337 | if ((rv = rump_sys_rmdir(path)) != 0) | | 347 | if ((rv = rump_sys_rmdir(path)) != 0) |
338 | return rv; | | 348 | return rv; |
339 | | | 349 | |
340 | if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0) | | 350 | if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0) |
341 | return 0; | | 351 | return 0; |
342 | kill(pargs->pta_childpid, SIGTERM); | | 352 | kill(pargs->pta_childpid, SIGTERM); |
343 | usleep(10); | | 353 | usleep(10); |
344 | if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0) | | 354 | if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0) |
345 | return 0; | | 355 | return 0; |
346 | kill(pargs->pta_childpid, SIGKILL); | | 356 | kill(pargs->pta_childpid, SIGKILL); |
347 | usleep(500); | | 357 | usleep(500); |
348 | wait(&status); | | 358 | wait(&status); |
349 | | | 359 | |
350 | return 0; | | 360 | return 0; |
351 | } | | 361 | } |