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/stat.h> 37 #include <sys/ioctl.h> 38 #include <sys/wait.h> 39 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <signal.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <stdint.h> 46 #include <string.h> 47 #include <unistd.h> 48 #include <pwd.h> 49 50 #include <err.h> 51 52 #include <libprop/proplib.h> 53 54 #include "parser.h" 55 #include "testcase.h" 56 #include "runlist.h" 57 #include "config.h" 58 #include "kernel.h" 59 #include <dfregress.h> 60 #include <sys/tbridge.h> 61 62 63 int 64 run_kernel(const char *kmod, prop_dictionary_t testcase) 65 { 66 char errmsg[1024]; 67 prop_dictionary_t tkcase = NULL; 68 struct stat sb; 69 int fd, r, kmod_id, ret = 0; 70 71 if ((r = stat("/dev/tbridge", &sb)) != 0) { 72 sprintf(errmsg, "Kernel bridge module probably not loaded: %s", 73 strerror(errno)); 74 testcase_set_sys_buf(testcase, errmsg); 75 testcase_set_result(testcase, RESULT_PREFAIL); 76 77 return -1; 78 } 79 80 /* First kldload the testcase */ 81 kmod_id = kldload(kmod); 82 if (kmod_id < 0) { 83 sprintf(errmsg, "Could not load testcase kmod %s: %s", kmod, 84 strerror(errno)); 85 testcase_set_sys_buf(testcase, errmsg); 86 testcase_set_result(testcase, RESULT_PREFAIL); 87 88 return -1; 89 } 90 91 /* Open control device */ 92 fd = open("/dev/tbridge", O_RDWR); 93 if (fd < 0) { 94 sprintf(errmsg, "Could not open kernel bridge interface: %s", 95 strerror(errno)); 96 testcase_set_sys_buf(testcase, errmsg); 97 testcase_set_result(testcase, RESULT_PREFAIL); 98 99 ret = -1; 100 goto unload; 101 } 102 103 /* Then load the testcase description into the kernel */ 104 r = prop_dictionary_send_ioctl(testcase, fd, TBRIDGE_LOADTEST); 105 if (r < 0) { 106 sprintf(errmsg, "sending testcase to kernel failed: %s", 107 strerror(errno)); 108 testcase_set_sys_buf(testcase, errmsg); 109 testcase_set_result(testcase, RESULT_PREFAIL); 110 111 ret = -1; 112 goto unload; 113 } 114 115 /* Then wait for the result */ 116 r = prop_dictionary_recv_ioctl(fd, TBRIDGE_GETRESULT, &tkcase); 117 if (r < 0) { 118 sprintf(errmsg, "receiving test results from kernel failed: %s", 119 strerror(errno)); 120 testcase_set_sys_buf(testcase, errmsg); 121 testcase_set_result(testcase, RESULT_PREFAIL); 122 123 ret = -1; 124 goto unload; 125 } 126 127 /* Copy over the values of interest */ 128 testcase_set_result(testcase, testcase_get_result(tkcase)); 129 testcase_set_stdout_buf(testcase, testcase_get_stdout_buf(tkcase)); 130 131 /* Release copy received from kernel */ 132 prop_object_release(tkcase); 133 134 unload: 135 r = kldunload(kmod_id); 136 if (r < 0) { 137 sprintf(errmsg, "kldunload for %s failed: %s", kmod, 138 strerror(errno)); 139 testcase_set_sys_buf(testcase, errmsg); 140 141 ret = -1; 142 } 143 144 return ret; 145 } 146