175584Sru/* $NetBSD: t_basic.c,v 1.3 2010/06/09 08:37:16 pooka Exp $ */ 275584Sru 375584Sru#include <sys/types.h> 475584Sru#include <sys/mount.h> 575584Sru 675584Sru#include <atf-c.h> 775584Sru#include <err.h> 875584Sru#include <errno.h> 975584Sru#include <fcntl.h> 1075584Sru#include <stdio.h> 1175584Sru#include <unistd.h> 1275584Sru#include <string.h> 1375584Sru#include <stdlib.h> 1475584Sru 1575584Sru#include <rump/rump.h> 1675584Sru#include <rump/rump_syscalls.h> 1775584Sru 1875584Sru#include <miscfs/nullfs/null.h> 1975584Sru#include <fs/tmpfs/tmpfs_args.h> 2075584Sru 2175584Sru#include "../../h_macros.h" 2275584Sru 2375584SruATF_TC(basic); 2475584SruATF_TC_HEAD(basic, tc) 2575584Sru{ 2675584Sru atf_tc_set_md_var(tc, "descr", "basic nullfs functionality"); 2775584Sru} 2875584Sru 2975584Sru#define MSTR "magic bus" 3075584Sru 3175584Srustatic void 3275584Sruxput_tfile(const char *path, const char *mstr) 3375584Sru{ 3475584Sru int fd; 3575584Sru 3675584Sru fd = rump_sys_open(path, O_CREAT | O_RDWR, 0777); 3775584Sru if (fd == -1) 3875584Sru atf_tc_fail_errno("create %s", path); 3975584Sru if (rump_sys_write(fd, MSTR, sizeof(MSTR)) != sizeof(MSTR)) 4075584Sru atf_tc_fail_errno("write to testfile"); 4175584Sru rump_sys_close(fd); 4275584Sru} 4375584Sru 4475584Srustatic int 4575584Sruxread_tfile(const char *path, const char *mstr) 4675584Sru{ 4775584Sru char buf[128]; 4875584Sru int fd; 4975584Sru 5075584Sru fd = rump_sys_open(path, O_RDONLY); 5175584Sru if (fd == -1) 5275584Sru return errno; 5375584Sru if (rump_sys_read(fd, buf, sizeof(buf)) == -1) 5475584Sru atf_tc_fail_errno("read tfile"); 5575584Sru rump_sys_close(fd); 5675584Sru if (strcmp(buf, MSTR) == 0) 5775584Sru return 0; 5875584Sru return EPROGMISMATCH; 5975584Sru} 6075584Sru 6175584Srustatic void 6275584Srumountnull(const char *what, const char *mp, int flags) 6375584Sru{ 6475584Sru struct null_args nargs; 6575584Sru 6675584Sru memset(&nargs, 0, sizeof(nargs)); 6775584Sru nargs.nulla_target = __UNCONST(what); 6875584Sru if (rump_sys_mount(MOUNT_NULL, mp, flags, &nargs, sizeof(nargs)) == -1) 6975584Sru atf_tc_fail_errno("could not mount nullfs"); 7075584Sru 7175584Sru} 7275584Sru 7375584SruATF_TC_BODY(basic, tc) 7475584Sru{ 7575584Sru struct tmpfs_args targs; 7675584Sru struct stat sb; 7775584Sru int error; 7875584Sru 7975584Sru rump_init(); 8075584Sru if (rump_sys_mkdir("/td1", 0777) == -1) 8175584Sru atf_tc_fail_errno("mp1"); 8275584Sru if (rump_sys_mkdir("/td2", 0777) == -1) 8375584Sru atf_tc_fail_errno("mp1"); 8475584Sru 8575584Sru /* use tmpfs because rumpfs doesn't support regular files */ 8675584Sru memset(&targs, 0, sizeof(targs)); 8775584Sru targs.ta_version = TMPFS_ARGS_VERSION; 8875584Sru targs.ta_root_mode = 0777; 8975584Sru if (rump_sys_mount(MOUNT_TMPFS, "/td1", 0, &targs, sizeof(targs)) == -1) 9075584Sru atf_tc_fail_errno("could not mount tmpfs td1"); 9175584Sru 9275584Sru mountnull("/td1", "/td2", 0); 9375584Sru 9475584Sru /* test unnull -> null */ 9575584Sru xput_tfile("/td1/tensti", "jeppe"); 9675584Sru error = xread_tfile("/td2/tensti", "jeppe"); 9775584Sru if (error != 0) 9875584Sru atf_tc_fail("null compare failed: %d (%s)", 9975584Sru error, strerror(error)); 10075584Sru 10175584Sru /* test null -> unnull */ 10275584Sru xput_tfile("/td2/kiekko", "keppi"); 10375584Sru error = xread_tfile("/td1/kiekko", "keppi"); 10475584Sru if (error != 0) 10575584Sru atf_tc_fail("unnull compare failed: %d (%s)", 10675584Sru error, strerror(error)); 10775584Sru 10875584Sru /* test unnull -> null overwrite */ 10975584Sru xput_tfile("/td1/tensti", "se oolannin sota"); 11075584Sru error = xread_tfile("/td2/tensti", "se oolannin sota"); 11175584Sru if (error != 0) 11275584Sru atf_tc_fail("unnull compare failed: %d (%s)", 11375584Sru error, strerror(error)); 11475584Sru 11575584Sru /* test that /td2 is unaffected in "real life" */ 11675584Sru if (rump_sys_unmount("/td2", 0) == -1) 11775584Sru atf_tc_fail_errno("cannot unmount nullfs"); 11875584Sru if ((error = rump_sys_stat("/td2/tensti", &sb)) != -1 11975584Sru || errno != ENOENT) { 12075584Sru atf_tc_fail("stat tensti should return ENOENT, got %d", error); 12175584Sru } 12275584Sru if ((error = rump_sys_stat("/td2/kiekko", &sb)) != -1 12375584Sru || errno != ENOENT) { 12475584Sru atf_tc_fail("stat kiekko should return ENOENT, got %d", error); 12575584Sru } 12675584Sru 12775584Sru /* done */ 12875584Sru} 12975584Sru 13075584SruATF_TC(twistymount); 13175584SruATF_TC_HEAD(twistymount, tc) 13275584Sru{ 13375584Sru 13475584Sru /* this is expected to fail until the PR is fixed */ 13575584Sru atf_tc_set_md_var(tc, "descr", "\"recursive\" mounts deadlock" 13675584Sru " (kern/43439)"); 13775584Sru} 13875584Sru 13975584Sru/* 14075584Sru * Mapping to identifiers in kern/43439: 14175584Sru * /td = /home/current/pkgsrc 14275584Sru * /td/dist = /home/current/pkgsrc/distiles 14375584Sru * /mp = /usr/pkgsrc 14475584Sru * /mp/dist = /usr/pkgsrc/distfiles -- "created" by first null mount 14575584Sru */ 14675584Sru 14775584SruATF_TC_BODY(twistymount, tc) 14875584Sru{ 14975584Sru int mkd = 0; 15075584Sru 15175584Sru rump_init(); 15275584Sru 15375584Sru if (rump_sys_mkdir("/td", 0777) == -1) 15475584Sru atf_tc_fail_errno("mkdir %d", mkd++); 15575584Sru if (rump_sys_mkdir("/td/dist", 0777) == -1) 15675584Sru atf_tc_fail_errno("mkdir %d", mkd++); 15775584Sru if (rump_sys_mkdir("/mp", 0777) == -1) 15875584Sru atf_tc_fail_errno("mkdir %d", mkd++); 15975584Sru 16075584Sru /* MNT_RDONLY doesn't matter, but just for compat with the PR */ 16175584Sru mountnull("/td", "/mp", MNT_RDONLY); 16275584Sru mountnull("/td/dist", "/mp/dist", 0); 16375584Sru 16475584Sru /* if we didn't get a locking-against-meself panic, we passed */ 16575584Sru} 16675584Sru 16775584SruATF_TP_ADD_TCS(tp) 16875584Sru{ 16975584Sru 17075584Sru ATF_TP_ADD_TC(tp, basic); 17175584Sru ATF_TP_ADD_TC(tp, twistymount); 17275584Sru 17375584Sru return atf_no_error(); 17475584Sru} 17575584Sru