Home | History | Annotate | Line # | Download | only in puffs
t_basic.c revision 1.4
      1  1.4  pooka /*	$NetBSD: t_basic.c,v 1.4 2010/07/11 12:26:19 pooka Exp $	*/
      2  1.1  pooka 
      3  1.1  pooka #include <sys/types.h>
      4  1.1  pooka #include <sys/mount.h>
      5  1.1  pooka #include <sys/socket.h>
      6  1.1  pooka 
      7  1.1  pooka #include <assert.h>
      8  1.1  pooka #include <atf-c.h>
      9  1.1  pooka #include <err.h>
     10  1.1  pooka #include <errno.h>
     11  1.1  pooka #include <fcntl.h>
     12  1.3  pooka #include <pthread.h>
     13  1.1  pooka #include <puffs.h>
     14  1.4  pooka #include <puffsdump.h>
     15  1.1  pooka #include <stdio.h>
     16  1.1  pooka #include <unistd.h>
     17  1.1  pooka #include <string.h>
     18  1.1  pooka #include <stdlib.h>
     19  1.1  pooka 
     20  1.1  pooka #include <rump/rump.h>
     21  1.1  pooka #include <rump/rump_syscalls.h>
     22  1.1  pooka 
     23  1.1  pooka #include "../../h_macros.h"
     24  1.1  pooka 
     25  1.1  pooka struct puffs_args {
     26  1.1  pooka 	uint8_t			*us_pargs;
     27  1.1  pooka 	size_t			us_pargslen;
     28  1.1  pooka 
     29  1.1  pooka 	int			us_pflags;
     30  1.1  pooka 	int			us_servfd;
     31  1.1  pooka 	pid_t			us_childpid;
     32  1.1  pooka };
     33  1.1  pooka 
     34  1.1  pooka #define BUFSIZE (64*1024)
     35  1.4  pooka #define DTFS_DUMP "-o","dump"
     36  1.1  pooka 
     37  1.1  pooka struct thefds {
     38  1.1  pooka 	int rumpfd;
     39  1.1  pooka 	int servfd;
     40  1.1  pooka };
     41  1.1  pooka 
     42  1.4  pooka int vfs_toserv_ops[PUFFS_VFS_MAX];
     43  1.4  pooka int vn_toserv_ops[PUFFS_VN_MAX];
     44  1.4  pooka 
     45  1.4  pooka /*
     46  1.4  pooka  * Do a synchronous operation.  When this returns, all FAF operations
     47  1.4  pooka  * have at least been delivered to the file system.
     48  1.4  pooka  *
     49  1.4  pooka  * XXX: is this really good enough considering puffs(9)-issued
     50  1.4  pooka  * callback operations?
     51  1.4  pooka  */
     52  1.4  pooka static void
     53  1.4  pooka syncbar(const char *fs)
     54  1.4  pooka {
     55  1.4  pooka 	struct statvfs svb;
     56  1.4  pooka 
     57  1.4  pooka 	rump_sys_statvfs1(fs, &svb, ST_WAIT);
     58  1.4  pooka }
     59  1.4  pooka 
     60  1.4  pooka static void
     61  1.4  pooka dumpopcount(void)
     62  1.4  pooka {
     63  1.4  pooka 	size_t i;
     64  1.4  pooka 
     65  1.4  pooka 	printf("VFS OPS:\n");
     66  1.4  pooka 	for (i = 0; i < MIN(puffsdump_vfsop_count, PUFFS_VFS_MAX); i++) {
     67  1.4  pooka 		printf("\t%s: %d\n",
     68  1.4  pooka 		    puffsdump_vfsop_revmap[i], vfs_toserv_ops[i]);
     69  1.4  pooka 	}
     70  1.4  pooka 
     71  1.4  pooka 	printf("VN OPS:\n");
     72  1.4  pooka 	for (i = 0; i < MIN(puffsdump_vnop_count, PUFFS_VN_MAX); i++) {
     73  1.4  pooka 		printf("\t%s: %d\n",
     74  1.4  pooka 		    puffsdump_vnop_revmap[i], vn_toserv_ops[i]);
     75  1.4  pooka 	}
     76  1.4  pooka }
     77  1.4  pooka 
     78  1.1  pooka /*
     79  1.1  pooka  * Threads which shovel data between comfd and /dev/puffs.
     80  1.1  pooka  * (cannot use polling since fd's are in different namespaces)
     81  1.1  pooka  */
     82  1.1  pooka static void *
     83  1.1  pooka readshovel(void *arg)
     84  1.1  pooka {
     85  1.4  pooka 	struct putter_hdr *phdr;
     86  1.4  pooka 	struct puffs_req *preq;
     87  1.1  pooka 	struct thefds *fds = arg;
     88  1.1  pooka 	char buf[BUFSIZE];
     89  1.1  pooka 	ssize_t n;
     90  1.1  pooka 	int error, comfd, puffsfd;
     91  1.1  pooka 
     92  1.1  pooka 	comfd = fds->servfd;
     93  1.1  pooka 	puffsfd = fds->rumpfd;
     94  1.1  pooka 
     95  1.4  pooka 	phdr = (void *)buf;
     96  1.4  pooka 	preq = (void *)buf;
     97  1.4  pooka 
     98  1.1  pooka 	/* use static thread id */
     99  1.4  pooka 	rump_pub_lwp_alloc_and_switch(0, 10);
    100  1.1  pooka 
    101  1.1  pooka 	for (;;) {
    102  1.1  pooka 		ssize_t n, n2;
    103  1.1  pooka 
    104  1.4  pooka 		n = rump_sys_read(puffsfd, buf, sizeof(*phdr));
    105  1.4  pooka 		if (n <= 0)
    106  1.4  pooka 			break;
    107  1.4  pooka 
    108  1.4  pooka 		assert(phdr->pth_framelen < BUFSIZE);
    109  1.4  pooka 		n = rump_sys_read(puffsfd, buf+sizeof(*phdr),
    110  1.4  pooka 		    phdr->pth_framelen - sizeof(*phdr));
    111  1.4  pooka 		if (n <= 0)
    112  1.1  pooka 			break;
    113  1.4  pooka 
    114  1.4  pooka 		/* Analyze request */
    115  1.4  pooka 		if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
    116  1.4  pooka 			assert(preq->preq_optype < PUFFS_VFS_MAX);
    117  1.4  pooka 			vfs_toserv_ops[preq->preq_optype]++;
    118  1.4  pooka 		} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
    119  1.4  pooka 			assert(preq->preq_optype < PUFFS_VN_MAX);
    120  1.4  pooka 			vn_toserv_ops[preq->preq_optype]++;
    121  1.1  pooka 		}
    122  1.1  pooka 
    123  1.4  pooka 		n = phdr->pth_framelen;
    124  1.4  pooka 		if (write(comfd, buf, n) != n)
    125  1.4  pooka 			break;
    126  1.1  pooka 	}
    127  1.1  pooka 
    128  1.1  pooka 	return NULL;
    129  1.1  pooka }
    130  1.1  pooka 
    131  1.1  pooka static void *
    132  1.1  pooka writeshovel(void *arg)
    133  1.1  pooka {
    134  1.1  pooka 	struct thefds *fds = arg;
    135  1.1  pooka 	struct putter_hdr *phdr;
    136  1.1  pooka 	char buf[BUFSIZE];
    137  1.1  pooka 	size_t toread;
    138  1.1  pooka 	int error, comfd, puffsfd;
    139  1.1  pooka 
    140  1.1  pooka 	/* use static thread id */
    141  1.4  pooka 	rump_pub_lwp_alloc_and_switch(0, 11);
    142  1.1  pooka 
    143  1.1  pooka 	comfd = fds->servfd;
    144  1.1  pooka 	puffsfd = fds->rumpfd;
    145  1.1  pooka 
    146  1.1  pooka 	phdr = (struct putter_hdr *)buf;
    147  1.1  pooka 
    148  1.1  pooka 	for (;;) {
    149  1.1  pooka 		off_t off;
    150  1.1  pooka 		ssize_t n;
    151  1.1  pooka 
    152  1.1  pooka 		/*
    153  1.1  pooka 		 * Need to write everything to the "kernel" in one chunk,
    154  1.1  pooka 		 * so make sure we have it here.
    155  1.1  pooka 		 */
    156  1.1  pooka 		off = 0;
    157  1.1  pooka 		toread = sizeof(struct putter_hdr);
    158  1.4  pooka 		assert(toread < BUFSIZE);
    159  1.1  pooka 		do {
    160  1.1  pooka 			n = read(comfd, buf+off, toread);
    161  1.1  pooka 			if (n <= 0) {
    162  1.1  pooka 				break;
    163  1.1  pooka 			}
    164  1.1  pooka 			off += n;
    165  1.1  pooka 			if (off >= sizeof(struct putter_hdr))
    166  1.1  pooka 				toread = phdr->pth_framelen - off;
    167  1.1  pooka 			else
    168  1.1  pooka 				toread = off - sizeof(struct putter_hdr);
    169  1.1  pooka 		} while (toread);
    170  1.1  pooka 
    171  1.1  pooka 		n = rump_sys_write(puffsfd, buf, phdr->pth_framelen);
    172  1.1  pooka 		if (n != phdr->pth_framelen)
    173  1.4  pooka 			break;
    174  1.1  pooka 	}
    175  1.1  pooka 
    176  1.1  pooka 	return NULL;
    177  1.1  pooka }
    178  1.1  pooka 
    179  1.1  pooka static void
    180  1.1  pooka rumpshovels(int rumpfd, int servfd)
    181  1.1  pooka {
    182  1.1  pooka 	struct thefds *fds;
    183  1.1  pooka 	pthread_t pt;
    184  1.1  pooka 	int rv;
    185  1.1  pooka 
    186  1.1  pooka 	if ((rv = rump_init()) == -1)
    187  1.1  pooka 		err(1, "rump_init");
    188  1.1  pooka 
    189  1.1  pooka 	fds = malloc(sizeof(*fds));
    190  1.1  pooka 	fds->rumpfd = rumpfd;
    191  1.1  pooka 	fds->servfd = servfd;
    192  1.1  pooka 	if (pthread_create(&pt, NULL, readshovel, fds) == -1)
    193  1.1  pooka 		err(1, "read shovel");
    194  1.1  pooka 	pthread_detach(pt);
    195  1.1  pooka 	if (pthread_create(&pt, NULL, writeshovel, fds) == -1)
    196  1.1  pooka 		err(1, "write shovel");
    197  1.1  pooka 	pthread_detach(pt);
    198  1.1  pooka }
    199  1.1  pooka 
    200  1.1  pooka static int
    201  1.1  pooka parseargs(int argc, char *argv[],
    202  1.1  pooka 	struct puffs_args *args, int *mntflags,
    203  1.1  pooka 	char *canon_dev, char *canon_dir)
    204  1.1  pooka {
    205  1.1  pooka 	pid_t childpid;
    206  1.1  pooka 	pthread_t pt;
    207  1.1  pooka 	int *pflags = &args->us_pflags;
    208  1.1  pooka 	char comfd[16];
    209  1.1  pooka 	int sv[2];
    210  1.1  pooka 	size_t len;
    211  1.1  pooka 	ssize_t n;
    212  1.1  pooka 	int rv;
    213  1.1  pooka 
    214  1.1  pooka 	/* Create sucketpair for communication with the real file server */
    215  1.1  pooka 	if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) == -1)
    216  1.1  pooka 		err(1, "socketpair");
    217  1.1  pooka 
    218  1.1  pooka 	switch ((childpid = fork())) {
    219  1.1  pooka 	case 0:
    220  1.1  pooka 		close(sv[1]);
    221  1.1  pooka 		snprintf(comfd, sizeof(sv[0]), "%d", sv[0]);
    222  1.1  pooka 		if (setenv("PUFFS_COMFD", comfd, 1) == -1)
    223  1.3  pooka 			atf_tc_fail_errno("setenv");
    224  1.1  pooka 
    225  1.1  pooka 		if (execvp(argv[0], argv) == -1)
    226  1.3  pooka 			atf_tc_fail_errno("execvp");
    227  1.1  pooka 		/*NOTREACHED*/
    228  1.1  pooka 	case -1:
    229  1.3  pooka 		atf_tc_fail_errno("fork");
    230  1.1  pooka 		/*NOTREACHED*/
    231  1.1  pooka 	default:
    232  1.1  pooka 		close(sv[0]);
    233  1.1  pooka 		break;
    234  1.1  pooka 	}
    235  1.1  pooka 
    236  1.1  pooka 	/* read args */
    237  1.1  pooka 	if ((n = read(sv[1], &len, sizeof(len))) != sizeof(len))
    238  1.1  pooka 		err(1, "mp 1 %zd", n);
    239  1.1  pooka 	if (len > MAXPATHLEN)
    240  1.1  pooka 		err(1, "mntpath > MAXPATHLEN");
    241  1.1  pooka 	if ((size_t)read(sv[1], canon_dir, len) != len)
    242  1.1  pooka 		err(1, "mp 2");
    243  1.1  pooka 	if (read(sv[1], &len, sizeof(len)) != sizeof(len))
    244  1.1  pooka 		err(1, "fn 1");
    245  1.1  pooka 	if (len > MAXPATHLEN)
    246  1.1  pooka 		err(1, "devpath > MAXPATHLEN");
    247  1.1  pooka 	if ((size_t)read(sv[1], canon_dev, len) != len)
    248  1.1  pooka 		err(1, "fn 2");
    249  1.1  pooka 	if (read(sv[1], mntflags, sizeof(*mntflags)) != sizeof(*mntflags))
    250  1.1  pooka 		err(1, "mntflags");
    251  1.1  pooka 	if (read(sv[1], &args->us_pargslen, sizeof(args->us_pargslen)) != sizeof(args->us_pargslen))
    252  1.1  pooka 		err(1, "puffs_args len");
    253  1.1  pooka 	args->us_pargs = malloc(args->us_pargslen);
    254  1.1  pooka 	if (args->us_pargs == NULL)
    255  1.1  pooka 		err(1, "malloc");
    256  1.1  pooka 	if (read(sv[1], args->us_pargs, args->us_pargslen) != args->us_pargslen)
    257  1.1  pooka 		err(1, "puffs_args");
    258  1.1  pooka 	if (read(sv[1], pflags, sizeof(*pflags)) != sizeof(*pflags))
    259  1.1  pooka 		err(1, "pflags");
    260  1.1  pooka 
    261  1.1  pooka 	args->us_childpid = childpid;
    262  1.1  pooka 	args->us_servfd = sv[1];
    263  1.1  pooka 
    264  1.1  pooka 	return 0;
    265  1.1  pooka }
    266  1.1  pooka 
    267  1.3  pooka #define dtfsmountv(a, b)						\
    268  1.3  pooka     struct puffs_args pa;						\
    269  1.3  pooka     dtfsmount1(a, __arraycount(b), b, atf_tc_get_config_var(tc, "srcdir"), &pa)
    270  1.3  pooka static void
    271  1.3  pooka dtfsmount1(const char *mp, int optcount, char *opts[], const char *srcdir,
    272  1.3  pooka 	struct puffs_args *pa)
    273  1.1  pooka {
    274  1.1  pooka 	char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
    275  1.3  pooka 	char dtfs_path[MAXPATHLEN], mountpath[MAXPATHLEN];
    276  1.3  pooka 	char **dtfsargv;
    277  1.1  pooka 	int mntflag;
    278  1.3  pooka 	int rv, i;
    279  1.1  pooka 	int fd;
    280  1.1  pooka 
    281  1.3  pooka 	dtfsargv = malloc(sizeof(char *) * (optcount+3));
    282  1.3  pooka 
    283  1.1  pooka 	/* build dtfs exec path for atf */
    284  1.3  pooka 	sprintf(dtfs_path, "%s/h_dtfs/h_dtfs", srcdir);
    285  1.3  pooka 	dtfsargv[0] = dtfs_path;
    286  1.3  pooka 
    287  1.3  pooka 	for (i = 0; i < optcount; i++) {
    288  1.3  pooka 		dtfsargv[i+1] = opts[i];
    289  1.3  pooka 	}
    290  1.1  pooka 
    291  1.3  pooka 	strlcpy(mountpath, mp, sizeof(mountpath));
    292  1.3  pooka 	dtfsargv[optcount+1] = mountpath;
    293  1.3  pooka 	dtfsargv[optcount+2] = NULL;
    294  1.3  pooka 
    295  1.3  pooka 	rv = parseargs(optcount+3, dtfsargv,
    296  1.3  pooka 	    pa, &mntflag, canon_dev, canon_dir);
    297  1.1  pooka 	if (rv)
    298  1.1  pooka 		atf_tc_fail("comfd parseargs");
    299  1.1  pooka 
    300  1.2  pooka 	rump_init();
    301  1.1  pooka 	fd = rump_sys_open("/dev/puffs", O_RDWR);
    302  1.1  pooka 	if (fd == -1)
    303  1.1  pooka 		atf_tc_fail_errno("open puffs fd");
    304  1.1  pooka #if 0
    305  1.3  pooka 	pa->pa_fd = fd;
    306  1.1  pooka #else
    307  1.1  pooka 	assert(fd == 0); /* XXX: FIXME */
    308  1.1  pooka #endif
    309  1.1  pooka 
    310  1.3  pooka 	if (rump_sys_mkdir(mp, 0777) == -1)
    311  1.1  pooka 		atf_tc_fail_errno("mkdir mountpoint");
    312  1.1  pooka 
    313  1.3  pooka 	if (rump_sys_mount(MOUNT_PUFFS, mp, 0,
    314  1.3  pooka 	    pa->us_pargs, pa->us_pargslen) == -1)
    315  1.1  pooka 		atf_tc_fail_errno("mount");
    316  1.1  pooka 
    317  1.3  pooka 	rumpshovels(fd, pa->us_servfd);
    318  1.3  pooka }
    319  1.3  pooka 
    320  1.3  pooka ATF_TC(mount);
    321  1.3  pooka ATF_TC_HEAD(mount, tc)
    322  1.3  pooka {
    323  1.3  pooka 
    324  1.3  pooka 	atf_tc_set_md_var(tc, "descr", "puffs+dtfs un/mount test");
    325  1.3  pooka }
    326  1.3  pooka 
    327  1.3  pooka ATF_TC_BODY(mount, tc)
    328  1.3  pooka {
    329  1.3  pooka 	char *myopts[] = {
    330  1.3  pooka 		"dtfs",
    331  1.3  pooka 	};
    332  1.3  pooka 
    333  1.3  pooka 	dtfsmountv("/mp", myopts);
    334  1.3  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    335  1.3  pooka 		atf_tc_fail_errno("unmount");
    336  1.3  pooka }
    337  1.3  pooka 
    338  1.3  pooka ATF_TC(root_reg);
    339  1.3  pooka ATF_TC_HEAD(root_reg, tc)
    340  1.3  pooka {
    341  1.3  pooka 	atf_tc_set_md_var(tc, "descr", "root is a regular file");
    342  1.3  pooka }
    343  1.3  pooka 
    344  1.3  pooka ATF_TC_BODY(root_reg, tc)
    345  1.3  pooka {
    346  1.3  pooka 	char *myopts[] = {
    347  1.3  pooka 		"-r","reg",
    348  1.3  pooka 		"dtfs",
    349  1.3  pooka 	};
    350  1.3  pooka 	int fd, rv;
    351  1.3  pooka 
    352  1.3  pooka 	dtfsmountv("/mp", myopts);
    353  1.3  pooka 
    354  1.3  pooka 	fd = rump_sys_open("/mp", O_RDWR);
    355  1.3  pooka 	if (fd == -1)
    356  1.3  pooka 		atf_tc_fail_errno("open root");
    357  1.3  pooka 	if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd))
    358  1.3  pooka 		atf_tc_fail_errno("write to root");
    359  1.3  pooka 	rv = rump_sys_mkdir("/mp/test", 0777);
    360  1.3  pooka 	ATF_REQUIRE(errno == ENOTDIR);
    361  1.3  pooka 	ATF_REQUIRE(rv == -1);
    362  1.3  pooka 	rump_sys_close(fd);
    363  1.1  pooka 
    364  1.1  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    365  1.1  pooka 		atf_tc_fail_errno("unmount");
    366  1.1  pooka }
    367  1.1  pooka 
    368  1.3  pooka ATF_TC(root_lnk);
    369  1.3  pooka ATF_TC_HEAD(root_lnk, tc)
    370  1.3  pooka {
    371  1.3  pooka 
    372  1.3  pooka 	atf_tc_set_md_var(tc, "descr", "root is a symbolic link");
    373  1.3  pooka }
    374  1.3  pooka 
    375  1.3  pooka #define LINKSTR "/path/to/nowhere"
    376  1.3  pooka ATF_TC_BODY(root_lnk, tc)
    377  1.3  pooka {
    378  1.3  pooka 	char *myopts[] = {
    379  1.3  pooka 		"-r", "lnk " LINKSTR,
    380  1.3  pooka 		"-s",
    381  1.3  pooka 		"dtfs",
    382  1.3  pooka 	};
    383  1.3  pooka 	char buf[PATH_MAX];
    384  1.3  pooka 	ssize_t len;
    385  1.3  pooka 	int rv;
    386  1.3  pooka 
    387  1.3  pooka 	dtfsmountv("/mp", myopts);
    388  1.3  pooka 
    389  1.3  pooka 	if ((len = rump_sys_readlink("/mp", buf, sizeof(buf)-1)) == -1)
    390  1.3  pooka 		atf_tc_fail_errno("readlink");
    391  1.3  pooka 	buf[len] = '\0';
    392  1.3  pooka 
    393  1.3  pooka 	ATF_REQUIRE_STREQ(buf, LINKSTR);
    394  1.3  pooka 
    395  1.3  pooka #if 0 /* XXX: unmount uses FOLLOW */
    396  1.3  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    397  1.3  pooka 		atf_tc_fail_errno("unmount");
    398  1.3  pooka #endif
    399  1.3  pooka 
    400  1.3  pooka 	/*
    401  1.3  pooka 	 * XXX2: due to atf issue #53, we must make sure the child dies
    402  1.3  pooka 	 * before we exit.
    403  1.3  pooka 	 */
    404  1.3  pooka 	if (kill(pa.us_childpid, SIGTERM) == -1)
    405  1.3  pooka 		err(1, "kill");
    406  1.3  pooka }
    407  1.3  pooka 
    408  1.3  pooka ATF_TC(root_fifo);
    409  1.3  pooka ATF_TC_HEAD(root_fifo, tc)
    410  1.3  pooka {
    411  1.3  pooka 
    412  1.3  pooka 	atf_tc_set_md_var(tc, "descr", "root is a symbolic link");
    413  1.3  pooka }
    414  1.3  pooka 
    415  1.3  pooka #define MAGICSTR "nakit ja muusiperunat maustevoilla"
    416  1.3  pooka static void *
    417  1.3  pooka dofifow(void *arg)
    418  1.3  pooka {
    419  1.3  pooka 	int fd = (int)(uintptr_t)arg;
    420  1.3  pooka 	char buf[512];
    421  1.3  pooka 
    422  1.3  pooka 	printf("writing\n");
    423  1.3  pooka 	strcpy(buf, MAGICSTR);
    424  1.3  pooka 	if (rump_sys_write(fd, buf, strlen(buf)+1) != strlen(buf)+1)
    425  1.3  pooka 		atf_tc_fail_errno("write to fifo");
    426  1.3  pooka 
    427  1.3  pooka 	return NULL;
    428  1.3  pooka }
    429  1.3  pooka 
    430  1.3  pooka ATF_TC_BODY(root_fifo, tc)
    431  1.3  pooka {
    432  1.3  pooka 	char *myopts[] = {
    433  1.3  pooka 		"-r", "fifo",
    434  1.3  pooka 		"dtfs",
    435  1.3  pooka 	};
    436  1.3  pooka 	pthread_t pt;
    437  1.3  pooka 	char buf[512];
    438  1.3  pooka 	ssize_t len;
    439  1.3  pooka 	int fd;
    440  1.3  pooka 
    441  1.3  pooka 	dtfsmountv("/mp", myopts);
    442  1.3  pooka 	fd = rump_sys_open("/mp", O_RDWR);
    443  1.3  pooka 	if (fd == -1)
    444  1.3  pooka 		atf_tc_fail_errno("open fifo");
    445  1.3  pooka 
    446  1.3  pooka 	pthread_create(&pt, NULL, dofifow, (void *)(uintptr_t)fd);
    447  1.3  pooka 
    448  1.3  pooka 	printf("reading\n");
    449  1.3  pooka 	memset(buf, 0, sizeof(buf));
    450  1.3  pooka 	if (rump_sys_read(fd, buf, sizeof(buf)) == -1)
    451  1.3  pooka 		atf_tc_fail_errno("read fifo");
    452  1.3  pooka 
    453  1.3  pooka 	ATF_REQUIRE_STREQ(buf, MAGICSTR);
    454  1.3  pooka 
    455  1.3  pooka 	rump_sys_close(fd);
    456  1.3  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    457  1.3  pooka 		atf_tc_fail_errno("unmount");
    458  1.3  pooka }
    459  1.3  pooka 
    460  1.3  pooka ATF_TC(root_chrdev);
    461  1.3  pooka ATF_TC_HEAD(root_chrdev, tc)
    462  1.3  pooka {
    463  1.3  pooka 
    464  1.3  pooka 	atf_tc_set_md_var(tc, "descr", "root is /dev/null");
    465  1.3  pooka }
    466  1.3  pooka 
    467  1.3  pooka ATF_TC_BODY(root_chrdev, tc)
    468  1.3  pooka {
    469  1.3  pooka 	char *myopts[] = {
    470  1.3  pooka 		"-r", "chr 2 0",
    471  1.3  pooka 		"dtfs",
    472  1.3  pooka 	};
    473  1.3  pooka 	ssize_t rv;
    474  1.3  pooka 	char buf[512];
    475  1.3  pooka 	int fd;
    476  1.3  pooka 
    477  1.3  pooka 	dtfsmountv("/mp", myopts);
    478  1.3  pooka 	fd = rump_sys_open("/mp", O_RDWR);
    479  1.3  pooka 	if (fd == -1)
    480  1.3  pooka 		atf_tc_fail_errno("open null");
    481  1.3  pooka 
    482  1.3  pooka 	rv = rump_sys_write(fd, buf, sizeof(buf));
    483  1.3  pooka 	ATF_REQUIRE(rv == sizeof(buf));
    484  1.3  pooka 
    485  1.3  pooka 	rv = rump_sys_read(fd, buf, sizeof(buf));
    486  1.3  pooka 	ATF_REQUIRE(rv == 0);
    487  1.3  pooka 
    488  1.3  pooka 	rump_sys_close(fd);
    489  1.3  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    490  1.3  pooka 		atf_tc_fail_errno("unmount");
    491  1.3  pooka }
    492  1.3  pooka 
    493  1.4  pooka /*
    494  1.4  pooka  * Inactive/reclaim tests
    495  1.4  pooka  */
    496  1.4  pooka 
    497  1.4  pooka ATF_TC(inactive_basic);
    498  1.4  pooka ATF_TC_HEAD(inactive_basic, tc)
    499  1.4  pooka {
    500  1.4  pooka 
    501  1.4  pooka 	atf_tc_set_md_var(tc, "descr", "inactive gets called");
    502  1.4  pooka }
    503  1.4  pooka 
    504  1.4  pooka ATF_TC_BODY(inactive_basic, tc)
    505  1.4  pooka {
    506  1.4  pooka 	char *myopts[] = {
    507  1.4  pooka 		"-i",
    508  1.4  pooka 		"dtfs",
    509  1.4  pooka 	};
    510  1.4  pooka 	int fd;
    511  1.4  pooka 
    512  1.4  pooka 	dtfsmountv("/mp", myopts);
    513  1.4  pooka 	fd = rump_sys_open("/mp/file", O_CREAT | O_RDWR, 0777);
    514  1.4  pooka 	if (fd == -1)
    515  1.4  pooka 		atf_tc_fail_errno("create");
    516  1.4  pooka 
    517  1.4  pooka 	/* one for /mp */
    518  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_INACTIVE], 1);
    519  1.4  pooka 
    520  1.4  pooka 	rump_sys_close(fd);
    521  1.4  pooka 
    522  1.4  pooka 	/* one for /mp/file */
    523  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_INACTIVE], 2);
    524  1.4  pooka 
    525  1.4  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    526  1.4  pooka 		atf_tc_fail_errno("unmount");
    527  1.4  pooka 
    528  1.4  pooka 	/* one for /mp again */
    529  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_INACTIVE], 3);
    530  1.4  pooka }
    531  1.4  pooka 
    532  1.4  pooka ATF_TC(inactive_reclaim);
    533  1.4  pooka ATF_TC_HEAD(inactive_reclaim, tc)
    534  1.4  pooka {
    535  1.4  pooka 
    536  1.4  pooka 	atf_tc_set_md_var(tc, "descr", "inactive/reclaim gets called");
    537  1.4  pooka }
    538  1.4  pooka 
    539  1.4  pooka ATF_TC_BODY(inactive_reclaim, tc)
    540  1.4  pooka {
    541  1.4  pooka 	char *myopts[] = {
    542  1.4  pooka 		"-i",
    543  1.4  pooka 		"dtfs",
    544  1.4  pooka 	};
    545  1.4  pooka 	int fd;
    546  1.4  pooka 
    547  1.4  pooka 	dtfsmountv("/mp", myopts);
    548  1.4  pooka 	fd = rump_sys_open("/mp/file", O_CREAT | O_RDWR, 0777);
    549  1.4  pooka 	if (fd == -1)
    550  1.4  pooka 		atf_tc_fail_errno("create");
    551  1.4  pooka 
    552  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_INACTIVE], 1);
    553  1.4  pooka 
    554  1.4  pooka 	if (rump_sys_unlink("/mp/file") == -1)
    555  1.4  pooka 		atf_tc_fail_errno("remove");
    556  1.4  pooka 
    557  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_INACTIVE], 2);
    558  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_RECLAIM], 0);
    559  1.4  pooka 
    560  1.4  pooka 	rump_sys_close(fd);
    561  1.4  pooka 	syncbar("/mp");
    562  1.4  pooka 
    563  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_INACTIVE], 4);
    564  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_RECLAIM], 1);
    565  1.4  pooka 
    566  1.4  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    567  1.4  pooka 		atf_tc_fail_errno("unmount");
    568  1.4  pooka }
    569  1.4  pooka 
    570  1.4  pooka ATF_TC(reclaim_hardlink);
    571  1.4  pooka ATF_TC_HEAD(reclaim_hardlink, tc)
    572  1.4  pooka {
    573  1.4  pooka 
    574  1.4  pooka 	atf_tc_set_md_var(tc, "descr", "reclaim gets called only after "
    575  1.4  pooka 	    "final link is gone");
    576  1.4  pooka }
    577  1.4  pooka 
    578  1.4  pooka ATF_TC_BODY(reclaim_hardlink, tc)
    579  1.4  pooka {
    580  1.4  pooka 	char *myopts[] = {
    581  1.4  pooka 		"-i",
    582  1.4  pooka 		"dtfs",
    583  1.4  pooka 	};
    584  1.4  pooka 	int fd;
    585  1.4  pooka 	int ianow;
    586  1.4  pooka 
    587  1.4  pooka 	dtfsmountv("/mp", myopts);
    588  1.4  pooka 	fd = rump_sys_open("/mp/file", O_CREAT | O_RDWR, 0777);
    589  1.4  pooka 	if (fd == -1)
    590  1.4  pooka 		atf_tc_fail_errno("create");
    591  1.4  pooka 
    592  1.4  pooka 	if (rump_sys_link("/mp/file", "/mp/anotherfile") == -1)
    593  1.4  pooka 		atf_tc_fail_errno("create link");
    594  1.4  pooka 	rump_sys_close(fd);
    595  1.4  pooka 
    596  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_RECLAIM], 0);
    597  1.4  pooka 
    598  1.4  pooka 	/* unlink first hardlink */
    599  1.4  pooka 	if (rump_sys_unlink("/mp/file") == -1)
    600  1.4  pooka 		atf_tc_fail_errno("unlink 1");
    601  1.4  pooka 
    602  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_RECLAIM], 0);
    603  1.4  pooka 	ianow = vn_toserv_ops[PUFFS_VN_INACTIVE];
    604  1.4  pooka 
    605  1.4  pooka 	/* unlink second hardlink */
    606  1.4  pooka 	if (rump_sys_unlink("/mp/anotherfile") == -1)
    607  1.4  pooka 		atf_tc_fail_errno("unlink 2");
    608  1.4  pooka 
    609  1.4  pooka 	syncbar("/mp");
    610  1.4  pooka 
    611  1.4  pooka 	ATF_REQUIRE(ianow < vn_toserv_ops[PUFFS_VN_INACTIVE]);
    612  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_RECLAIM], 1);
    613  1.4  pooka 
    614  1.4  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    615  1.4  pooka 		atf_tc_fail_errno("unmount");
    616  1.4  pooka }
    617  1.4  pooka 
    618  1.4  pooka ATF_TC(unlink_accessible);
    619  1.4  pooka ATF_TC_HEAD(unlink_accessible, tc)
    620  1.4  pooka {
    621  1.4  pooka 
    622  1.4  pooka 	atf_tc_set_md_var(tc, "descr", "open file is accessible after "
    623  1.4  pooka 	    "having been unlinked");
    624  1.4  pooka }
    625  1.4  pooka 
    626  1.4  pooka ATF_TC_BODY(unlink_accessible, tc)
    627  1.4  pooka {
    628  1.4  pooka 	char *myopts[] = {
    629  1.4  pooka 		"-i",
    630  1.4  pooka 		"-o","nopagecache",
    631  1.4  pooka 		"dtfs",
    632  1.4  pooka 	};
    633  1.4  pooka 	char buf[512];
    634  1.4  pooka 	int fd, ianow;
    635  1.4  pooka 
    636  1.4  pooka 	assert(sizeof(buf) > sizeof(MAGICSTR));
    637  1.4  pooka 
    638  1.4  pooka 	dtfsmountv("/mp", myopts);
    639  1.4  pooka 	fd = rump_sys_open("/mp/file", O_CREAT | O_RDWR, 0777);
    640  1.4  pooka 	if (fd == -1)
    641  1.4  pooka 		atf_tc_fail_errno("create");
    642  1.4  pooka 
    643  1.4  pooka 	if (rump_sys_write(fd, MAGICSTR, sizeof(MAGICSTR)) != sizeof(MAGICSTR))
    644  1.4  pooka 		atf_tc_fail_errno("write");
    645  1.4  pooka 	if (rump_sys_unlink("/mp/file") == -1)
    646  1.4  pooka 		atf_tc_fail_errno("unlink");
    647  1.4  pooka 
    648  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_RECLAIM], 0);
    649  1.4  pooka 	ianow = vn_toserv_ops[PUFFS_VN_INACTIVE];
    650  1.4  pooka 
    651  1.4  pooka 	if (rump_sys_pread(fd, buf, sizeof(buf), 0) == -1)
    652  1.4  pooka 		atf_tc_fail_errno("read");
    653  1.4  pooka 	rump_sys_close(fd);
    654  1.4  pooka 
    655  1.4  pooka 	syncbar("/mp");
    656  1.4  pooka 
    657  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_RECLAIM], 1);
    658  1.4  pooka 	ATF_REQUIRE_EQ(vn_toserv_ops[PUFFS_VN_INACTIVE], ianow+2);
    659  1.4  pooka 
    660  1.4  pooka 	ATF_REQUIRE_STREQ(buf, MAGICSTR);
    661  1.4  pooka 
    662  1.4  pooka 	if (rump_sys_unmount("/mp", 0) == -1)
    663  1.4  pooka 		atf_tc_fail_errno("unmount");
    664  1.4  pooka }
    665  1.4  pooka 
    666  1.1  pooka ATF_TP_ADD_TCS(tp)
    667  1.1  pooka {
    668  1.3  pooka 
    669  1.1  pooka 	ATF_TP_ADD_TC(tp, mount);
    670  1.1  pooka 
    671  1.3  pooka 	ATF_TP_ADD_TC(tp, root_fifo);
    672  1.3  pooka 	ATF_TP_ADD_TC(tp, root_lnk);
    673  1.3  pooka 	ATF_TP_ADD_TC(tp, root_reg);
    674  1.3  pooka 	ATF_TP_ADD_TC(tp, root_chrdev);
    675  1.3  pooka 
    676  1.4  pooka 	ATF_TP_ADD_TC(tp, inactive_basic);
    677  1.4  pooka 	ATF_TP_ADD_TC(tp, inactive_reclaim);
    678  1.4  pooka 	ATF_TP_ADD_TC(tp, reclaim_hardlink);
    679  1.4  pooka 	ATF_TP_ADD_TC(tp, unlink_accessible);
    680  1.4  pooka 
    681  1.1  pooka 	return atf_no_error();
    682  1.1  pooka }
    683