1 /* 2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/resource.h> 31 #include <sys/time.h> 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/stat.h> 35 #include <sys/linker.h> 36 #include <sys/ioctl.h> 37 #include <sys/wait.h> 38 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <signal.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <stdint.h> 45 #include <string.h> 46 #include <unistd.h> 47 #include <pwd.h> 48 49 #include <err.h> 50 51 #include <libprop/proplib.h> 52 53 #include "parser.h" 54 #include "testcase.h" 55 #include "runlist.h" 56 #include "config.h" 57 #include "kernel.h" 58 #include <dfregress.h> 59 #include <sys/tbridge.h> 60 61 62 int 63 run_kernel(const char *kmod, prop_dictionary_t testcase) 64 { 65 char errmsg[1024]; 66 prop_dictionary_t tkcase = NULL; 67 struct stat sb; 68 int fd, r, kmod_id, ret = 0; 69 70 if ((r = stat("/dev/tbridge", &sb)) != 0) { 71 sprintf(errmsg, "Kernel bridge module probably not loaded: %s", 72 strerror(errno)); 73 testcase_set_sys_buf(testcase, errmsg); 74 testcase_set_result(testcase, RESULT_PREFAIL); 75 76 return -1; 77 } 78 79 /* First kldload the testcase */ 80 kmod_id = kldload(kmod); 81 if (kmod_id < 0) { 82 sprintf(errmsg, "Could not load testcase kmod %s: %s", kmod, 83 strerror(errno)); 84 testcase_set_sys_buf(testcase, errmsg); 85 testcase_set_result(testcase, RESULT_PREFAIL); 86 87 return -1; 88 } 89 90 /* Open control device */ 91 fd = open("/dev/tbridge", O_RDWR); 92 if (fd < 0) { 93 sprintf(errmsg, "Could not open kernel bridge interface: %s", 94 strerror(errno)); 95 testcase_set_sys_buf(testcase, errmsg); 96 testcase_set_result(testcase, RESULT_PREFAIL); 97 98 ret = -1; 99 goto unload; 100 } 101 102 /* Then load the testcase description into the kernel */ 103 r = prop_dictionary_send_ioctl(testcase, fd, TBRIDGE_LOADTEST); 104 if (r < 0) { 105 sprintf(errmsg, "sending testcase to kernel failed: %s", 106 strerror(errno)); 107 testcase_set_sys_buf(testcase, errmsg); 108 testcase_set_result(testcase, RESULT_PREFAIL); 109 110 ret = -1; 111 goto unload; 112 } 113 114 /* Then wait for the result */ 115 r = prop_dictionary_recv_ioctl(fd, TBRIDGE_GETRESULT, &tkcase); 116 if (r < 0) { 117 sprintf(errmsg, "receiving test results from kernel failed: %s", 118 strerror(errno)); 119 testcase_set_sys_buf(testcase, errmsg); 120 testcase_set_result(testcase, RESULT_PREFAIL); 121 122 ret = -1; 123 goto unload; 124 } 125 126 /* Copy over the values of interest */ 127 testcase_set_result(testcase, testcase_get_result(tkcase)); 128 testcase_set_stdout_buf(testcase, testcase_get_stdout_buf(tkcase)); 129 130 /* Release copy received from kernel */ 131 prop_object_release(tkcase); 132 133 unload: 134 r = kldunload(kmod_id); 135 if (r < 0) { 136 sprintf(errmsg, "kldunload for %s failed: %s", kmod, 137 strerror(errno)); 138 testcase_set_sys_buf(testcase, errmsg); 139 140 ret = -1; 141 } 142 143 return ret; 144 } 145