1*84d9c625SLionel Sambuc /* $NetBSD: fstest_puffs.c,v 1.11 2013/09/09 19:47:38 pooka Exp $ */
211be35a1SLionel Sambuc
311be35a1SLionel Sambuc /*
411be35a1SLionel Sambuc * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
511be35a1SLionel Sambuc *
611be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
711be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
811be35a1SLionel Sambuc * are met:
911be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
1011be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1111be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
1211be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
1311be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
1411be35a1SLionel Sambuc *
1511be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
1611be35a1SLionel Sambuc * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1711be35a1SLionel Sambuc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1811be35a1SLionel Sambuc * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1911be35a1SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2011be35a1SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2111be35a1SLionel Sambuc * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2211be35a1SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2311be35a1SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2411be35a1SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2511be35a1SLionel Sambuc * SUCH DAMAGE.
2611be35a1SLionel Sambuc */
2711be35a1SLionel Sambuc
2811be35a1SLionel Sambuc #include <sys/types.h>
2911be35a1SLionel Sambuc #include <sys/mount.h>
3011be35a1SLionel Sambuc #include <sys/socket.h>
3111be35a1SLionel Sambuc #include <sys/statvfs.h>
3211be35a1SLionel Sambuc #include <sys/wait.h>
3311be35a1SLionel Sambuc
3411be35a1SLionel Sambuc #include <assert.h>
3511be35a1SLionel Sambuc #include <atf-c.h>
3611be35a1SLionel Sambuc #include <err.h>
3711be35a1SLionel Sambuc #include <errno.h>
3811be35a1SLionel Sambuc #include <fcntl.h>
3911be35a1SLionel Sambuc #include <pthread.h>
4011be35a1SLionel Sambuc #include <puffs.h>
4111be35a1SLionel Sambuc #include <puffsdump.h>
4211be35a1SLionel Sambuc #include <signal.h>
4311be35a1SLionel Sambuc #include <stdio.h>
4411be35a1SLionel Sambuc #include <unistd.h>
4511be35a1SLionel Sambuc #include <string.h>
4611be35a1SLionel Sambuc #include <stdlib.h>
4711be35a1SLionel Sambuc
4811be35a1SLionel Sambuc #include <rump/rump.h>
4911be35a1SLionel Sambuc #include <rump/rump_syscalls.h>
5011be35a1SLionel Sambuc
5111be35a1SLionel Sambuc #include "h_fsmacros.h"
5211be35a1SLionel Sambuc
5311be35a1SLionel Sambuc #define BUFSIZE (128*1024)
5411be35a1SLionel Sambuc #define DTFS_DUMP "-o","dump"
5511be35a1SLionel Sambuc
5611be35a1SLionel Sambuc static bool mayquit = false;
5711be35a1SLionel Sambuc
5811be35a1SLionel Sambuc static ssize_t
xread(int fd,void * vp,size_t n)5911be35a1SLionel Sambuc xread(int fd, void *vp, size_t n)
6011be35a1SLionel Sambuc {
6111be35a1SLionel Sambuc size_t left;
6211be35a1SLionel Sambuc
6311be35a1SLionel Sambuc left = n;
6411be35a1SLionel Sambuc do {
6511be35a1SLionel Sambuc ssize_t ssz;
6611be35a1SLionel Sambuc
6711be35a1SLionel Sambuc ssz = read(fd, vp, left);
6811be35a1SLionel Sambuc if (ssz == -1) {
6911be35a1SLionel Sambuc return ssz;
7011be35a1SLionel Sambuc }
7111be35a1SLionel Sambuc left -= ssz;
7211be35a1SLionel Sambuc vp = (char *)vp + ssz;
7311be35a1SLionel Sambuc } while (left > 0);
7411be35a1SLionel Sambuc return n;
7511be35a1SLionel Sambuc }
7611be35a1SLionel Sambuc
7711be35a1SLionel Sambuc static ssize_t
xwrite(int fd,const void * vp,size_t n)7811be35a1SLionel Sambuc xwrite(int fd, const void *vp, size_t n)
7911be35a1SLionel Sambuc {
8011be35a1SLionel Sambuc size_t left;
8111be35a1SLionel Sambuc
8211be35a1SLionel Sambuc left = n;
8311be35a1SLionel Sambuc do {
8411be35a1SLionel Sambuc ssize_t ssz;
8511be35a1SLionel Sambuc
8611be35a1SLionel Sambuc ssz = write(fd, vp, left);
8711be35a1SLionel Sambuc if (ssz == -1) {
8811be35a1SLionel Sambuc return ssz;
8911be35a1SLionel Sambuc }
9011be35a1SLionel Sambuc left -= ssz;
9111be35a1SLionel Sambuc vp = (const char *)vp + ssz;
9211be35a1SLionel Sambuc } while (left > 0);
9311be35a1SLionel Sambuc return n;
9411be35a1SLionel Sambuc }
9511be35a1SLionel Sambuc
9611be35a1SLionel Sambuc /*
9711be35a1SLionel Sambuc * Threads which shovel data between comfd and /dev/puffs.
9811be35a1SLionel Sambuc * (cannot use polling since fd's are in different namespaces)
9911be35a1SLionel Sambuc */
10011be35a1SLionel Sambuc static void *
readshovel(void * arg)10111be35a1SLionel Sambuc readshovel(void *arg)
10211be35a1SLionel Sambuc {
10311be35a1SLionel Sambuc struct putter_hdr *phdr;
10411be35a1SLionel Sambuc struct puffs_req *preq;
10511be35a1SLionel Sambuc struct puffstestargs *args = arg;
10611be35a1SLionel Sambuc char buf[BUFSIZE];
10711be35a1SLionel Sambuc ssize_t n;
10811be35a1SLionel Sambuc int comfd, puffsfd;
10911be35a1SLionel Sambuc
11011be35a1SLionel Sambuc comfd = args->pta_servfd;
11111be35a1SLionel Sambuc puffsfd = args->pta_rumpfd;
11211be35a1SLionel Sambuc
11311be35a1SLionel Sambuc phdr = (void *)buf;
11411be35a1SLionel Sambuc preq = (void *)buf;
11511be35a1SLionel Sambuc
11611be35a1SLionel Sambuc rump_pub_lwproc_newlwp(1);
11711be35a1SLionel Sambuc
11811be35a1SLionel Sambuc for (;;) {
11911be35a1SLionel Sambuc n = rump_sys_read(puffsfd, buf, sizeof(*phdr));
12011be35a1SLionel Sambuc if (n <= 0) {
12111be35a1SLionel Sambuc fprintf(stderr, "readshovel r1 %zd / %d\n", n, errno);
12211be35a1SLionel Sambuc break;
12311be35a1SLionel Sambuc }
12411be35a1SLionel Sambuc
12511be35a1SLionel Sambuc assert(phdr->pth_framelen < BUFSIZE);
12611be35a1SLionel Sambuc n = rump_sys_read(puffsfd, buf+sizeof(*phdr),
12711be35a1SLionel Sambuc phdr->pth_framelen - sizeof(*phdr));
12811be35a1SLionel Sambuc if (n <= 0) {
12911be35a1SLionel Sambuc fprintf(stderr, "readshovel r2 %zd / %d\n", n, errno);
13011be35a1SLionel Sambuc break;
13111be35a1SLionel Sambuc }
13211be35a1SLionel Sambuc
13311be35a1SLionel Sambuc /* Analyze request */
13411be35a1SLionel Sambuc if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
13511be35a1SLionel Sambuc assert(preq->preq_optype < PUFFS_VFS_MAX);
13611be35a1SLionel Sambuc args->pta_vfs_toserv_ops[preq->preq_optype]++;
13711be35a1SLionel Sambuc } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
13811be35a1SLionel Sambuc assert(preq->preq_optype < PUFFS_VN_MAX);
13911be35a1SLionel Sambuc args->pta_vn_toserv_ops[preq->preq_optype]++;
14011be35a1SLionel Sambuc }
14111be35a1SLionel Sambuc
14211be35a1SLionel Sambuc n = phdr->pth_framelen;
14311be35a1SLionel Sambuc if (xwrite(comfd, buf, n) != n) {
14411be35a1SLionel Sambuc fprintf(stderr, "readshovel write %zd / %d\n", n, errno);
14511be35a1SLionel Sambuc break;
14611be35a1SLionel Sambuc }
14711be35a1SLionel Sambuc }
14811be35a1SLionel Sambuc
14911be35a1SLionel Sambuc if (n != 0 && mayquit == false)
15011be35a1SLionel Sambuc abort();
15111be35a1SLionel Sambuc return NULL;
15211be35a1SLionel Sambuc }
15311be35a1SLionel Sambuc
15411be35a1SLionel Sambuc static void *
writeshovel(void * arg)15511be35a1SLionel Sambuc writeshovel(void *arg)
15611be35a1SLionel Sambuc {
15711be35a1SLionel Sambuc struct puffstestargs *args = arg;
15811be35a1SLionel Sambuc struct putter_hdr *phdr;
15911be35a1SLionel Sambuc struct puffs_req *preq;
16011be35a1SLionel Sambuc char buf[BUFSIZE];
16111be35a1SLionel Sambuc size_t toread;
16211be35a1SLionel Sambuc ssize_t n;
16311be35a1SLionel Sambuc int comfd, puffsfd;
16411be35a1SLionel Sambuc
16511be35a1SLionel Sambuc rump_pub_lwproc_newlwp(1);
16611be35a1SLionel Sambuc
16711be35a1SLionel Sambuc comfd = args->pta_servfd;
16811be35a1SLionel Sambuc puffsfd = args->pta_rumpfd;
16911be35a1SLionel Sambuc
17011be35a1SLionel Sambuc phdr = (struct putter_hdr *)buf;
17111be35a1SLionel Sambuc preq = (void *)buf;
17211be35a1SLionel Sambuc
17311be35a1SLionel Sambuc for (;;) {
17411be35a1SLionel Sambuc uint64_t off;
17511be35a1SLionel Sambuc
17611be35a1SLionel Sambuc /*
17711be35a1SLionel Sambuc * Need to write everything to the "kernel" in one chunk,
17811be35a1SLionel Sambuc * so make sure we have it here.
17911be35a1SLionel Sambuc */
18011be35a1SLionel Sambuc off = 0;
18111be35a1SLionel Sambuc toread = sizeof(struct putter_hdr);
18211be35a1SLionel Sambuc assert(toread < BUFSIZE);
18311be35a1SLionel Sambuc do {
18411be35a1SLionel Sambuc n = xread(comfd, buf+off, toread);
18511be35a1SLionel Sambuc if (n <= 0) {
18611be35a1SLionel Sambuc fprintf(stderr, "writeshovel read %zd / %d\n",
18711be35a1SLionel Sambuc n, errno);
18811be35a1SLionel Sambuc goto out;
18911be35a1SLionel Sambuc }
19011be35a1SLionel Sambuc off += n;
19111be35a1SLionel Sambuc if (off >= sizeof(struct putter_hdr))
19211be35a1SLionel Sambuc toread = phdr->pth_framelen - off;
19311be35a1SLionel Sambuc else
19411be35a1SLionel Sambuc toread = off - sizeof(struct putter_hdr);
19511be35a1SLionel Sambuc } while (toread);
19611be35a1SLionel Sambuc
19711be35a1SLionel Sambuc if (__predict_false(
19811be35a1SLionel Sambuc PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS
19911be35a1SLionel Sambuc && preq->preq_optype == PUFFS_VFS_UNMOUNT)) {
20011be35a1SLionel Sambuc if (preq->preq_rv == 0)
20111be35a1SLionel Sambuc mayquit = true;
20211be35a1SLionel Sambuc }
20311be35a1SLionel Sambuc
20411be35a1SLionel Sambuc n = rump_sys_write(puffsfd, buf, phdr->pth_framelen);
20511be35a1SLionel Sambuc if ((size_t)n != phdr->pth_framelen) {
20611be35a1SLionel Sambuc fprintf(stderr, "writeshovel wr %zd / %d\n", n, errno);
20711be35a1SLionel Sambuc break;
20811be35a1SLionel Sambuc }
20911be35a1SLionel Sambuc }
21011be35a1SLionel Sambuc
21111be35a1SLionel Sambuc out:
21211be35a1SLionel Sambuc if (n != 0)
21311be35a1SLionel Sambuc abort();
21411be35a1SLionel Sambuc return NULL;
21511be35a1SLionel Sambuc }
21611be35a1SLionel Sambuc
21711be35a1SLionel Sambuc static void
rumpshovels(struct puffstestargs * args)21811be35a1SLionel Sambuc rumpshovels(struct puffstestargs *args)
21911be35a1SLionel Sambuc {
22011be35a1SLionel Sambuc pthread_t pt;
22111be35a1SLionel Sambuc int rv;
22211be35a1SLionel Sambuc
22311be35a1SLionel Sambuc if ((rv = rump_init()) == -1)
22411be35a1SLionel Sambuc err(1, "rump_init");
22511be35a1SLionel Sambuc
22611be35a1SLionel Sambuc if (pthread_create(&pt, NULL, readshovel, args) == -1)
22711be35a1SLionel Sambuc err(1, "read shovel");
22811be35a1SLionel Sambuc pthread_detach(pt);
22911be35a1SLionel Sambuc
23011be35a1SLionel Sambuc if (pthread_create(&pt, NULL, writeshovel, args) == -1)
23111be35a1SLionel Sambuc err(1, "write shovel");
23211be35a1SLionel Sambuc pthread_detach(pt);
23311be35a1SLionel Sambuc }
23411be35a1SLionel Sambuc
23511be35a1SLionel Sambuc static void
childfail(int sign)23611be35a1SLionel Sambuc childfail(int sign)
23711be35a1SLionel Sambuc {
23811be35a1SLionel Sambuc
23911be35a1SLionel Sambuc atf_tc_fail("child died"); /* almost signal-safe */
24011be35a1SLionel Sambuc }
24111be35a1SLionel Sambuc
24211be35a1SLionel Sambuc struct puffstestargs *theargs; /* XXX */
24311be35a1SLionel Sambuc
24411be35a1SLionel Sambuc /* XXX: we don't support size */
24511be35a1SLionel Sambuc static int
donewfs(const atf_tc_t * tc,void ** argp,const char * image,off_t size,void * fspriv,char ** theargv)24611be35a1SLionel Sambuc donewfs(const atf_tc_t *tc, void **argp,
24711be35a1SLionel Sambuc const char *image, off_t size, void *fspriv, char **theargv)
24811be35a1SLionel Sambuc {
24911be35a1SLionel Sambuc struct puffstestargs *args;
25011be35a1SLionel Sambuc pid_t childpid;
25111be35a1SLionel Sambuc int *pflags;
25211be35a1SLionel Sambuc char comfd[16];
25311be35a1SLionel Sambuc int sv[2];
25411be35a1SLionel Sambuc int mntflags;
25511be35a1SLionel Sambuc size_t len;
25611be35a1SLionel Sambuc ssize_t n;
25711be35a1SLionel Sambuc
25811be35a1SLionel Sambuc *argp = NULL;
25911be35a1SLionel Sambuc
26011be35a1SLionel Sambuc args = malloc(sizeof(*args));
26111be35a1SLionel Sambuc if (args == NULL)
26211be35a1SLionel Sambuc return errno;
26311be35a1SLionel Sambuc memset(args, 0, sizeof(*args));
26411be35a1SLionel Sambuc
26511be35a1SLionel Sambuc pflags = &args->pta_pflags;
26611be35a1SLionel Sambuc
26711be35a1SLionel Sambuc /* Create sucketpair for communication with the real file server */
26811be35a1SLionel Sambuc if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) == -1)
26911be35a1SLionel Sambuc return errno;
27011be35a1SLionel Sambuc
27111be35a1SLionel Sambuc signal(SIGCHLD, childfail);
27211be35a1SLionel Sambuc
27311be35a1SLionel Sambuc switch ((childpid = fork())) {
27411be35a1SLionel Sambuc case 0:
27511be35a1SLionel Sambuc close(sv[1]);
27611be35a1SLionel Sambuc snprintf(comfd, sizeof(sv[0]), "%d", sv[0]);
27711be35a1SLionel Sambuc if (setenv("PUFFS_COMFD", comfd, 1) == -1)
27811be35a1SLionel Sambuc return errno;
27911be35a1SLionel Sambuc
28011be35a1SLionel Sambuc if (execvp(theargv[0], theargv) == -1)
28111be35a1SLionel Sambuc return errno;
28211be35a1SLionel Sambuc case -1:
28311be35a1SLionel Sambuc return errno;
28411be35a1SLionel Sambuc default:
28511be35a1SLionel Sambuc close(sv[0]);
28611be35a1SLionel Sambuc break;
28711be35a1SLionel Sambuc }
28811be35a1SLionel Sambuc
28911be35a1SLionel Sambuc /* read args */
29011be35a1SLionel Sambuc if ((n = xread(sv[1], &len, sizeof(len))) != sizeof(len))
29111be35a1SLionel Sambuc err(1, "mp 1 %zd", n);
29211be35a1SLionel Sambuc if (len > MAXPATHLEN)
29311be35a1SLionel Sambuc err(1, "mntpath > MAXPATHLEN");
29411be35a1SLionel Sambuc if ((size_t)xread(sv[1], args->pta_dir, len) != len)
29511be35a1SLionel Sambuc err(1, "mp 2");
29611be35a1SLionel Sambuc if (xread(sv[1], &len, sizeof(len)) != sizeof(len))
29711be35a1SLionel Sambuc err(1, "fn 1");
29811be35a1SLionel Sambuc if (len > MAXPATHLEN)
29911be35a1SLionel Sambuc err(1, "devpath > MAXPATHLEN");
30011be35a1SLionel Sambuc if ((size_t)xread(sv[1], args->pta_dev, len) != len)
30111be35a1SLionel Sambuc err(1, "fn 2");
30211be35a1SLionel Sambuc if (xread(sv[1], &mntflags, sizeof(mntflags)) != sizeof(mntflags))
30311be35a1SLionel Sambuc err(1, "mntflags");
30411be35a1SLionel Sambuc if (xread(sv[1], &args->pta_pargslen, sizeof(args->pta_pargslen))
30511be35a1SLionel Sambuc != sizeof(args->pta_pargslen))
30611be35a1SLionel Sambuc err(1, "puffstest_args len");
30711be35a1SLionel Sambuc args->pta_pargs = malloc(args->pta_pargslen);
30811be35a1SLionel Sambuc if (args->pta_pargs == NULL)
30911be35a1SLionel Sambuc err(1, "malloc");
31011be35a1SLionel Sambuc if (xread(sv[1], args->pta_pargs, args->pta_pargslen)
31111be35a1SLionel Sambuc != (ssize_t)args->pta_pargslen)
31211be35a1SLionel Sambuc err(1, "puffstest_args");
31311be35a1SLionel Sambuc if (xread(sv[1], pflags, sizeof(*pflags)) != sizeof(*pflags))
31411be35a1SLionel Sambuc err(1, "pflags");
31511be35a1SLionel Sambuc
31611be35a1SLionel Sambuc args->pta_childpid = childpid;
31711be35a1SLionel Sambuc args->pta_servfd = sv[1];
31811be35a1SLionel Sambuc strlcpy(args->pta_dev, image, sizeof(args->pta_dev));
31911be35a1SLionel Sambuc
32011be35a1SLionel Sambuc *argp = theargs = args;
32111be35a1SLionel Sambuc
32211be35a1SLionel Sambuc return 0;
32311be35a1SLionel Sambuc }
32411be35a1SLionel Sambuc
32511be35a1SLionel Sambuc int
puffs_fstest_newfs(const atf_tc_t * tc,void ** argp,const char * image,off_t size,void * fspriv)32611be35a1SLionel Sambuc puffs_fstest_newfs(const atf_tc_t *tc, void **argp,
32711be35a1SLionel Sambuc const char *image, off_t size, void *fspriv)
32811be35a1SLionel Sambuc {
32911be35a1SLionel Sambuc char dtfs_path[MAXPATHLEN];
33011be35a1SLionel Sambuc char *dtfsargv[6];
33111be35a1SLionel Sambuc char **theargv;
33211be35a1SLionel Sambuc
33311be35a1SLionel Sambuc /* build dtfs exec path from atf test dir */
33411be35a1SLionel Sambuc sprintf(dtfs_path, "%s/../puffs/h_dtfs/h_dtfs",
33511be35a1SLionel Sambuc atf_tc_get_config_var(tc, "srcdir"));
33611be35a1SLionel Sambuc
33711be35a1SLionel Sambuc if (fspriv) {
33811be35a1SLionel Sambuc theargv = fspriv;
33911be35a1SLionel Sambuc theargv[0] = dtfs_path;
34011be35a1SLionel Sambuc } else {
34111be35a1SLionel Sambuc dtfsargv[0] = dtfs_path;
34211be35a1SLionel Sambuc dtfsargv[1] = __UNCONST("-i");
34311be35a1SLionel Sambuc dtfsargv[2] = __UNCONST("-s");
34411be35a1SLionel Sambuc dtfsargv[3] = __UNCONST("dtfs");
34511be35a1SLionel Sambuc dtfsargv[4] = __UNCONST("fictional");
34611be35a1SLionel Sambuc dtfsargv[5] = NULL;
34711be35a1SLionel Sambuc
34811be35a1SLionel Sambuc theargv = dtfsargv;
34911be35a1SLionel Sambuc }
35011be35a1SLionel Sambuc
35111be35a1SLionel Sambuc return donewfs(tc, argp, image, size, fspriv, theargv);
35211be35a1SLionel Sambuc }
35311be35a1SLionel Sambuc
35411be35a1SLionel Sambuc int
p2k_ffs_fstest_newfs(const atf_tc_t * tc,void ** argp,const char * image,off_t size,void * fspriv)35511be35a1SLionel Sambuc p2k_ffs_fstest_newfs(const atf_tc_t *tc, void **argp,
35611be35a1SLionel Sambuc const char *image, off_t size, void *fspriv)
35711be35a1SLionel Sambuc {
35811be35a1SLionel Sambuc char *rumpffs_argv[5];
35911be35a1SLionel Sambuc int rv;
36011be35a1SLionel Sambuc
36111be35a1SLionel Sambuc rump_init();
36211be35a1SLionel Sambuc if ((rv = ffs_fstest_newfs(tc, argp, image, size, fspriv)) != 0)
36311be35a1SLionel Sambuc return rv;
36411be35a1SLionel Sambuc if (mkdir("p2kffsfake", 0777) == -1 && errno != EEXIST)
36511be35a1SLionel Sambuc return errno;
36611be35a1SLionel Sambuc
36711be35a1SLionel Sambuc setenv("P2K_NODETACH", "1", 1);
36811be35a1SLionel Sambuc rumpffs_argv[0] = __UNCONST("rump_ffs");
36911be35a1SLionel Sambuc rumpffs_argv[1] = __UNCONST(image);
37011be35a1SLionel Sambuc rumpffs_argv[2] = __UNCONST("p2kffsfake"); /* NOTUSED */
37111be35a1SLionel Sambuc rumpffs_argv[3] = NULL;
37211be35a1SLionel Sambuc
37311be35a1SLionel Sambuc if ((rv = donewfs(tc, argp, image, size, fspriv, rumpffs_argv)) != 0)
37411be35a1SLionel Sambuc ffs_fstest_delfs(tc, argp);
37511be35a1SLionel Sambuc return rv;
37611be35a1SLionel Sambuc }
37711be35a1SLionel Sambuc
37811be35a1SLionel Sambuc int
puffs_fstest_mount(const atf_tc_t * tc,void * arg,const char * path,int flags)37911be35a1SLionel Sambuc puffs_fstest_mount(const atf_tc_t *tc, void *arg, const char *path, int flags)
38011be35a1SLionel Sambuc {
38111be35a1SLionel Sambuc struct puffstestargs *pargs = arg;
38211be35a1SLionel Sambuc int fd;
38311be35a1SLionel Sambuc
38411be35a1SLionel Sambuc rump_init();
38511be35a1SLionel Sambuc fd = rump_sys_open("/dev/puffs", O_RDWR);
38611be35a1SLionel Sambuc if (fd == -1)
38711be35a1SLionel Sambuc return fd;
38811be35a1SLionel Sambuc
38911be35a1SLionel Sambuc if (rump_sys_mkdir(path, 0777) == -1)
39011be35a1SLionel Sambuc return -1;
39111be35a1SLionel Sambuc
39211be35a1SLionel Sambuc if (rump_sys_mount(MOUNT_PUFFS, path, flags,
39311be35a1SLionel Sambuc pargs->pta_pargs, pargs->pta_pargslen) == -1) {
39411be35a1SLionel Sambuc /* apply "to kill a child" to avoid atf hang (kludge) */
39511be35a1SLionel Sambuc kill(pargs->pta_childpid, SIGKILL);
39611be35a1SLionel Sambuc return -1;
39711be35a1SLionel Sambuc }
39811be35a1SLionel Sambuc
39911be35a1SLionel Sambuc pargs->pta_rumpfd = fd;
40011be35a1SLionel Sambuc rumpshovels(pargs);
40111be35a1SLionel Sambuc
40211be35a1SLionel Sambuc return 0;
40311be35a1SLionel Sambuc }
40411be35a1SLionel Sambuc __strong_alias(p2k_ffs_fstest_mount,puffs_fstest_mount);
40511be35a1SLionel Sambuc
40611be35a1SLionel Sambuc int
puffs_fstest_delfs(const atf_tc_t * tc,void * arg)40711be35a1SLionel Sambuc puffs_fstest_delfs(const atf_tc_t *tc, void *arg)
40811be35a1SLionel Sambuc {
40911be35a1SLionel Sambuc
41011be35a1SLionel Sambuc /* useless ... */
41111be35a1SLionel Sambuc return 0;
41211be35a1SLionel Sambuc }
41311be35a1SLionel Sambuc
41411be35a1SLionel Sambuc int
p2k_ffs_fstest_delfs(const atf_tc_t * tc,void * arg)41511be35a1SLionel Sambuc p2k_ffs_fstest_delfs(const atf_tc_t *tc, void *arg)
41611be35a1SLionel Sambuc {
41711be35a1SLionel Sambuc
41811be35a1SLionel Sambuc return ffs_fstest_delfs(tc, arg);
41911be35a1SLionel Sambuc }
42011be35a1SLionel Sambuc
42111be35a1SLionel Sambuc int
puffs_fstest_unmount(const atf_tc_t * tc,const char * path,int flags)42211be35a1SLionel Sambuc puffs_fstest_unmount(const atf_tc_t *tc, const char *path, int flags)
42311be35a1SLionel Sambuc {
42411be35a1SLionel Sambuc struct puffstestargs *pargs = theargs;
42511be35a1SLionel Sambuc int status;
42611be35a1SLionel Sambuc int rv;
42711be35a1SLionel Sambuc
42811be35a1SLionel Sambuc /* ok, child might exit here */
42911be35a1SLionel Sambuc signal(SIGCHLD, SIG_IGN);
43011be35a1SLionel Sambuc
43111be35a1SLionel Sambuc rv = rump_sys_unmount(path, flags);
43211be35a1SLionel Sambuc if (rv)
43311be35a1SLionel Sambuc return rv;
43411be35a1SLionel Sambuc
43511be35a1SLionel Sambuc if ((rv = rump_sys_rmdir(path)) != 0)
43611be35a1SLionel Sambuc return rv;
43711be35a1SLionel Sambuc
43811be35a1SLionel Sambuc if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0)
43911be35a1SLionel Sambuc return 0;
44011be35a1SLionel Sambuc kill(pargs->pta_childpid, SIGTERM);
44111be35a1SLionel Sambuc usleep(10);
44211be35a1SLionel Sambuc if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0)
44311be35a1SLionel Sambuc return 0;
44411be35a1SLionel Sambuc kill(pargs->pta_childpid, SIGKILL);
44511be35a1SLionel Sambuc usleep(500);
44611be35a1SLionel Sambuc wait(&status);
44711be35a1SLionel Sambuc
44811be35a1SLionel Sambuc rmdir("p2kffsfake");
44911be35a1SLionel Sambuc
45011be35a1SLionel Sambuc return 0;
45111be35a1SLionel Sambuc }
45211be35a1SLionel Sambuc __strong_alias(p2k_ffs_fstest_unmount,puffs_fstest_unmount);
453