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