11.6Sbad/* $NetBSD: t_basic.c,v 1.6 2024/07/28 12:55:59 bad Exp $ */ 21.1Spooka 31.1Spooka#include <sys/types.h> 41.1Spooka#include <sys/mount.h> 51.1Spooka 61.1Spooka#include <atf-c.h> 71.1Spooka#include <err.h> 81.1Spooka#include <errno.h> 91.1Spooka#include <fcntl.h> 101.1Spooka#include <stdio.h> 111.1Spooka#include <unistd.h> 121.1Spooka#include <string.h> 131.1Spooka#include <stdlib.h> 141.1Spooka 151.1Spooka#include <rump/rump.h> 161.1Spooka#include <rump/rump_syscalls.h> 171.1Spooka 181.1Spooka#include <miscfs/nullfs/null.h> 191.1Spooka#include <fs/tmpfs/tmpfs_args.h> 201.1Spooka 211.4Schristos#include "h_macros.h" 221.1Spooka 231.1SpookaATF_TC(basic); 241.1SpookaATF_TC_HEAD(basic, tc) 251.1Spooka{ 261.1Spooka atf_tc_set_md_var(tc, "descr", "basic nullfs functionality"); 271.1Spooka} 281.1Spooka 291.1Spooka#define MSTR "magic bus" 301.1Spooka 311.1Spookastatic void 321.1Spookaxput_tfile(const char *path, const char *mstr) 331.1Spooka{ 341.1Spooka int fd; 351.1Spooka 361.1Spooka fd = rump_sys_open(path, O_CREAT | O_RDWR, 0777); 371.1Spooka if (fd == -1) 381.1Spooka atf_tc_fail_errno("create %s", path); 391.1Spooka if (rump_sys_write(fd, MSTR, sizeof(MSTR)) != sizeof(MSTR)) 401.1Spooka atf_tc_fail_errno("write to testfile"); 411.1Spooka rump_sys_close(fd); 421.1Spooka} 431.1Spooka 441.1Spookastatic int 451.1Spookaxread_tfile(const char *path, const char *mstr) 461.1Spooka{ 471.1Spooka char buf[128]; 481.1Spooka int fd; 491.1Spooka 501.1Spooka fd = rump_sys_open(path, O_RDONLY); 511.1Spooka if (fd == -1) 521.1Spooka return errno; 531.1Spooka if (rump_sys_read(fd, buf, sizeof(buf)) == -1) 541.1Spooka atf_tc_fail_errno("read tfile"); 551.1Spooka rump_sys_close(fd); 561.1Spooka if (strcmp(buf, MSTR) == 0) 571.1Spooka return 0; 581.1Spooka return EPROGMISMATCH; 591.1Spooka} 601.1Spooka 611.3Spookastatic void 621.3Spookamountnull(const char *what, const char *mp, int flags) 631.3Spooka{ 641.3Spooka struct null_args nargs; 651.3Spooka 661.3Spooka memset(&nargs, 0, sizeof(nargs)); 671.3Spooka nargs.nulla_target = __UNCONST(what); 681.3Spooka if (rump_sys_mount(MOUNT_NULL, mp, flags, &nargs, sizeof(nargs)) == -1) 691.3Spooka atf_tc_fail_errno("could not mount nullfs"); 701.3Spooka 711.3Spooka} 721.3Spooka 731.1SpookaATF_TC_BODY(basic, tc) 741.1Spooka{ 751.1Spooka struct tmpfs_args targs; 761.1Spooka struct stat sb; 771.1Spooka int error; 781.1Spooka 791.1Spooka rump_init(); 801.1Spooka if (rump_sys_mkdir("/td1", 0777) == -1) 811.6Sbad atf_tc_fail_errno("mkdir /td1"); 821.1Spooka if (rump_sys_mkdir("/td2", 0777) == -1) 831.6Sbad atf_tc_fail_errno("mkdir /td2"); 841.1Spooka 851.1Spooka /* use tmpfs because rumpfs doesn't support regular files */ 861.1Spooka memset(&targs, 0, sizeof(targs)); 871.1Spooka targs.ta_version = TMPFS_ARGS_VERSION; 881.1Spooka targs.ta_root_mode = 0777; 891.1Spooka if (rump_sys_mount(MOUNT_TMPFS, "/td1", 0, &targs, sizeof(targs)) == -1) 901.1Spooka atf_tc_fail_errno("could not mount tmpfs td1"); 911.1Spooka 921.3Spooka mountnull("/td1", "/td2", 0); 931.1Spooka 941.1Spooka /* test unnull -> null */ 951.1Spooka xput_tfile("/td1/tensti", "jeppe"); 961.1Spooka error = xread_tfile("/td2/tensti", "jeppe"); 971.1Spooka if (error != 0) 981.1Spooka atf_tc_fail("null compare failed: %d (%s)", 991.1Spooka error, strerror(error)); 1001.1Spooka 1011.1Spooka /* test null -> unnull */ 1021.1Spooka xput_tfile("/td2/kiekko", "keppi"); 1031.1Spooka error = xread_tfile("/td1/kiekko", "keppi"); 1041.1Spooka if (error != 0) 1051.1Spooka atf_tc_fail("unnull compare failed: %d (%s)", 1061.1Spooka error, strerror(error)); 1071.1Spooka 1081.1Spooka /* test unnull -> null overwrite */ 1091.1Spooka xput_tfile("/td1/tensti", "se oolannin sota"); 1101.1Spooka error = xread_tfile("/td2/tensti", "se oolannin sota"); 1111.1Spooka if (error != 0) 1121.1Spooka atf_tc_fail("unnull compare failed: %d (%s)", 1131.1Spooka error, strerror(error)); 1141.1Spooka 1151.1Spooka /* test that /td2 is unaffected in "real life" */ 1161.1Spooka if (rump_sys_unmount("/td2", 0) == -1) 1171.1Spooka atf_tc_fail_errno("cannot unmount nullfs"); 1181.1Spooka if ((error = rump_sys_stat("/td2/tensti", &sb)) != -1 1191.1Spooka || errno != ENOENT) { 1201.1Spooka atf_tc_fail("stat tensti should return ENOENT, got %d", error); 1211.1Spooka } 1221.1Spooka if ((error = rump_sys_stat("/td2/kiekko", &sb)) != -1 1231.1Spooka || errno != ENOENT) { 1241.1Spooka atf_tc_fail("stat kiekko should return ENOENT, got %d", error); 1251.1Spooka } 1261.1Spooka 1271.1Spooka /* done */ 1281.1Spooka} 1291.1Spooka 1301.3SpookaATF_TC(twistymount); 1311.3SpookaATF_TC_HEAD(twistymount, tc) 1321.3Spooka{ 1331.3Spooka 1341.3Spooka /* this is expected to fail until the PR is fixed */ 1351.3Spooka atf_tc_set_md_var(tc, "descr", "\"recursive\" mounts deadlock" 1361.5Sjruoho " (PR kern/43439)"); 1371.3Spooka} 1381.3Spooka 1391.3Spooka/* 1401.5Sjruoho * Mapping to identifiers in PR kern/43439: 1411.3Spooka * /td = /home/current/pkgsrc 1421.3Spooka * /td/dist = /home/current/pkgsrc/distiles 1431.3Spooka * /mp = /usr/pkgsrc 1441.3Spooka * /mp/dist = /usr/pkgsrc/distfiles -- "created" by first null mount 1451.3Spooka */ 1461.3Spooka 1471.3SpookaATF_TC_BODY(twistymount, tc) 1481.3Spooka{ 1491.3Spooka rump_init(); 1501.3Spooka 1511.3Spooka if (rump_sys_mkdir("/td", 0777) == -1) 1521.6Sbad atf_tc_fail_errno("mkdir /td"); 1531.3Spooka if (rump_sys_mkdir("/td/dist", 0777) == -1) 1541.6Sbad atf_tc_fail_errno("mkdir /td/dist"); 1551.3Spooka if (rump_sys_mkdir("/mp", 0777) == -1) 1561.6Sbad atf_tc_fail_errno("mkdir /mp"); 1571.3Spooka 1581.3Spooka /* MNT_RDONLY doesn't matter, but just for compat with the PR */ 1591.3Spooka mountnull("/td", "/mp", MNT_RDONLY); 1601.3Spooka mountnull("/td/dist", "/mp/dist", 0); 1611.3Spooka 1621.3Spooka /* if we didn't get a locking-against-meself panic, we passed */ 1631.3Spooka} 1641.3Spooka 1651.1SpookaATF_TP_ADD_TCS(tp) 1661.1Spooka{ 1671.3Spooka 1681.1Spooka ATF_TP_ADD_TC(tp, basic); 1691.3Spooka ATF_TP_ADD_TC(tp, twistymount); 1701.3Spooka 1711.3Spooka return atf_no_error(); 1721.1Spooka} 173