1*cdf297bbSpooka /* $NetBSD: t_modcmd.c,v 1.6 2010/05/01 11:20:21 pooka Exp $ */ 280be26daSpooka 380be26daSpooka /* 480be26daSpooka * Copyright (c) 2009 The NetBSD Foundation, Inc. 580be26daSpooka * All rights reserved. 680be26daSpooka * 780be26daSpooka * Redistribution and use in source and binary forms, with or without 880be26daSpooka * modification, are permitted provided that the following conditions 980be26daSpooka * are met: 1080be26daSpooka * 1. Redistributions of source code must retain the above copyright 1180be26daSpooka * notice, this list of conditions and the following disclaimer. 1280be26daSpooka * 2. Redistributions in binary form must reproduce the above copyright 1380be26daSpooka * notice, this list of conditions and the following disclaimer in the 1480be26daSpooka * documentation and/or other materials provided with the distribution. 1580be26daSpooka * 1680be26daSpooka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 1780be26daSpooka * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 1880be26daSpooka * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1980be26daSpooka * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2080be26daSpooka * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 2180be26daSpooka * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2280be26daSpooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 2380be26daSpooka * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2480be26daSpooka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2580be26daSpooka * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2680be26daSpooka * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 2780be26daSpooka * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2880be26daSpooka */ 2980be26daSpooka 3080be26daSpooka #include <sys/types.h> 3180be26daSpooka #include <sys/mount.h> 32*cdf297bbSpooka #include <sys/sysctl.h> 3380be26daSpooka 3480be26daSpooka #include <rump/rump.h> 3580be26daSpooka #include <rump/rump_syscalls.h> 3680be26daSpooka 3780be26daSpooka #include <fs/tmpfs/tmpfs_args.h> 3880be26daSpooka 3980be26daSpooka #include <atf-c.h> 4080be26daSpooka #include <dlfcn.h> 4180be26daSpooka #include <err.h> 4280be26daSpooka #include <errno.h> 4380be26daSpooka #include <stdio.h> 4480be26daSpooka #include <stdlib.h> 4580be26daSpooka #include <string.h> 4680be26daSpooka #include <unistd.h> 4780be26daSpooka #include <util.h> 4880be26daSpooka 4980be26daSpooka #include "../../h_macros.h" 5080be26daSpooka 5180be26daSpooka /* 5280be26daSpooka * We verify that modules can be loaded and unloaded. 5380be26daSpooka * tmpfs was chosen because it does not depend on an image. 5480be26daSpooka */ 5580be26daSpooka 5680be26daSpooka ATF_TC(cmsg_modcmd); 5780be26daSpooka ATF_TC_HEAD(cmsg_modcmd, tc) 5880be26daSpooka { 5980be26daSpooka atf_tc_set_md_var(tc, "descr", "Checks that loading and unloading " 6080be26daSpooka "a module (vfs/tmpfs) is possible"); 6180be26daSpooka } 6280be26daSpooka 63*cdf297bbSpooka static int 64*cdf297bbSpooka disable_autoload(void) 65*cdf297bbSpooka { 66*cdf297bbSpooka struct sysctlnode q, ans[256]; 67*cdf297bbSpooka int mib[3]; 68*cdf297bbSpooka size_t alen; 69*cdf297bbSpooka unsigned i; 70*cdf297bbSpooka bool no; 71*cdf297bbSpooka 72*cdf297bbSpooka mib[0] = CTL_KERN; 73*cdf297bbSpooka mib[1] = CTL_QUERY; 74*cdf297bbSpooka alen = sizeof(ans); 75*cdf297bbSpooka 76*cdf297bbSpooka memset(&q, 0, sizeof(q)); 77*cdf297bbSpooka q.sysctl_flags = SYSCTL_VERSION; 78*cdf297bbSpooka 79*cdf297bbSpooka if (rump_sys___sysctl(mib, 2, ans, &alen, &q, sizeof(q)) == -1) 80*cdf297bbSpooka return -1; 81*cdf297bbSpooka 82*cdf297bbSpooka for (i = 0; i < __arraycount(ans); i++) 83*cdf297bbSpooka if (strcmp("module", ans[i].sysctl_name) == 0) 84*cdf297bbSpooka break; 85*cdf297bbSpooka if (i == __arraycount(ans)) { 86*cdf297bbSpooka errno = ENOENT; 87*cdf297bbSpooka return -1; 88*cdf297bbSpooka } 89*cdf297bbSpooka 90*cdf297bbSpooka mib[1] = ans[i].sysctl_num; 91*cdf297bbSpooka mib[2] = CTL_QUERY; 92*cdf297bbSpooka 93*cdf297bbSpooka if (rump_sys___sysctl(mib, 3, ans, &alen, &q, sizeof(q)) == -1) 94*cdf297bbSpooka return errno; 95*cdf297bbSpooka 96*cdf297bbSpooka for (i = 0; i < __arraycount(ans); i++) 97*cdf297bbSpooka if (strcmp("autoload", ans[i].sysctl_name) == 0) 98*cdf297bbSpooka break; 99*cdf297bbSpooka if (i == __arraycount(ans)) { 100*cdf297bbSpooka errno = ENOENT; 101*cdf297bbSpooka return -1; 102*cdf297bbSpooka } 103*cdf297bbSpooka 104*cdf297bbSpooka mib[2] = ans[i].sysctl_num; 105*cdf297bbSpooka 106*cdf297bbSpooka no = false; 107*cdf297bbSpooka alen = 0; 108*cdf297bbSpooka if (rump_sys___sysctl(mib, 3, NULL, &alen, &no, sizeof(no)) == -1) 109*cdf297bbSpooka return errno; 110*cdf297bbSpooka 111*cdf297bbSpooka return 0; 112*cdf297bbSpooka 113*cdf297bbSpooka } 114*cdf297bbSpooka 115863335f9Spooka #define TMPFSMODULE "librumpfs_tmpfs.so" 11680be26daSpooka ATF_TC_BODY(cmsg_modcmd, tc) 11780be26daSpooka { 11880be26daSpooka struct tmpfs_args args; 11905e0f1dbSpooka const struct modinfo *const *mi_start, *const *mi_end; 12080be26daSpooka void *handle; 12105e0f1dbSpooka int i, rv, loop = 0; 12280be26daSpooka 12380be26daSpooka rump_init(); 124*cdf297bbSpooka 125*cdf297bbSpooka if (disable_autoload() == -1) 126*cdf297bbSpooka atf_tc_fail_errno("count not disable module autoload"); 127*cdf297bbSpooka 12880be26daSpooka memset(&args, 0, sizeof(args)); 12980be26daSpooka args.ta_version = TMPFS_ARGS_VERSION; 13080be26daSpooka args.ta_root_mode = 0777; 13180be26daSpooka 13280be26daSpooka if (rump_sys_mkdir("/mp", 0777) == -1) 13380be26daSpooka atf_tc_fail_errno("mkdir mountpoint"); 13480be26daSpooka if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) != -1) 13580be26daSpooka atf_tc_fail("mount unexpectedly succeeded"); 13680be26daSpooka 13780be26daSpooka handle = dlopen(TMPFSMODULE, RTLD_GLOBAL); 13880be26daSpooka if (handle == NULL) { 13980be26daSpooka const char *dlmsg = dlerror(); 14080be26daSpooka atf_tc_fail("cannot open %s: %s", TMPFSMODULE, dlmsg); 14180be26daSpooka } 14205e0f1dbSpooka 14305e0f1dbSpooka again: 14405e0f1dbSpooka mi_start = dlsym(handle, "__start_link_set_modules"); 14505e0f1dbSpooka mi_end = dlsym(handle, "__stop_link_set_modules"); 14605e0f1dbSpooka if (mi_start == NULL || mi_end == NULL) 14780be26daSpooka atf_tc_fail("cannot find module info"); 14805e0f1dbSpooka if ((rv = rump_pub_module_init(mi_start, (size_t)(mi_end-mi_start)))!=0) 14980be26daSpooka atf_tc_fail("module init failed: %d (%s)", rv, strerror(rv)); 15005e0f1dbSpooka if ((rv = rump_pub_module_init(mi_start, (size_t)(mi_end-mi_start)))==0) 15105e0f1dbSpooka atf_tc_fail("module double init succeeded"); 15280be26daSpooka 15380be26daSpooka if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) == -1) 15480be26daSpooka atf_tc_fail_errno("still cannot mount"); 15580be26daSpooka if (rump_sys_unmount("/mp", 0) == -1) 15680be26daSpooka atf_tc_fail("cannot unmount"); 15705e0f1dbSpooka for (i = 0; i < (int)(mi_end-mi_start); i++) { 15805e0f1dbSpooka if ((rv = rump_pub_module_fini(mi_start[i])) != 0) 15905e0f1dbSpooka atf_tc_fail("module fini failed: %d (%s)", 16005e0f1dbSpooka rv, strerror(rv)); 16105e0f1dbSpooka } 16205e0f1dbSpooka for (i = 0; i < (int)(mi_end-mi_start); i++) { 16305e0f1dbSpooka if ((rv = rump_pub_module_fini(mi_start[i])) == 0) 16405e0f1dbSpooka atf_tc_fail("module double fini succeeded"); 16505e0f1dbSpooka } 16605e0f1dbSpooka if (loop++ == 0) 16705e0f1dbSpooka goto again; 16805e0f1dbSpooka 16980be26daSpooka if (dlclose(handle)) { 17080be26daSpooka const char *dlmsg = dlerror(); 17180be26daSpooka atf_tc_fail("cannot close %s: %s", TMPFSMODULE, dlmsg); 17280be26daSpooka } 17380be26daSpooka 17480be26daSpooka if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) != -1) 17580be26daSpooka atf_tc_fail("mount unexpectedly succeeded"); 17680be26daSpooka } 17780be26daSpooka 17880be26daSpooka ATF_TP_ADD_TCS(tp) 17980be26daSpooka { 18080be26daSpooka ATF_TP_ADD_TC(tp, cmsg_modcmd); 181aebec17aSpooka 182aebec17aSpooka return atf_no_error(); 18380be26daSpooka } 184