1/*- 2 * Copyright (c) 2012 Advanced Computing Technologies LLC 3 * Written by George Neville-Neil gnn@freebsd.org 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 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 the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD$"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/conf.h> 34#include <sys/kernel.h> 35#include <sys/malloc.h> 36#include <sys/module.h> 37 38#include <sys/dtrace.h> 39#include "../sys/dtrace_bsd.h" 40 41 42static int dtio_unload(void); 43static void dtio_getargdesc(void *, dtrace_id_t, void *, 44 dtrace_argdesc_t *); 45static void dtio_provide(void *, dtrace_probedesc_t *); 46static void dtio_destroy(void *, dtrace_id_t, void *); 47static void dtio_enable(void *, dtrace_id_t, void *); 48static void dtio_disable(void *, dtrace_id_t, void *); 49static void dtio_load(void *); 50 51static dtrace_pattr_t dtio_attr = { 52{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 53{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 54{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 55{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 56{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 57}; 58 59static char *kernel = "kernel"; 60 61/* 62 * Name strings. 63 */ 64static char *dtio_start_str = "start"; 65static char *dtio_done_str = "done"; 66static char *dtio_wait_start_str = "wait-start"; 67static char *dtio_wait_done_str = "wait-done"; 68 69static dtrace_pops_t dtio_pops = { 70 dtio_provide, 71 NULL, 72 dtio_enable, 73 dtio_disable, 74 NULL, 75 NULL, 76 dtio_getargdesc, 77 NULL, 78 NULL, 79 dtio_destroy 80}; 81 82static dtrace_provider_id_t dtio_id; 83 84extern uint32_t dtio_start_id; 85extern uint32_t dtio_done_id; 86extern uint32_t dtio_wait_start_id; 87extern uint32_t dtio_wait_done_id; 88 89static void 90dtio_getargdesc(void *arg, dtrace_id_t id, void *parg, 91 dtrace_argdesc_t *desc) 92{ 93 const char *p = NULL; 94 95 switch (desc->dtargd_ndx) { 96 case 0: 97 p = "struct bio *"; 98 break; 99 case 1: 100 p = "struct devstat *"; 101 break; 102 default: 103 desc->dtargd_ndx = DTRACE_ARGNONE; 104 } 105 106 if (p != NULL) 107 strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native)); 108} 109 110static void 111dtio_provide(void *arg, dtrace_probedesc_t *desc) 112{ 113 if (desc != NULL) 114 return; 115 116 if (dtrace_probe_lookup(dtio_id, kernel, NULL, 117 dtio_start_str) == 0) { 118 dtio_start_id = dtrace_probe_create(dtio_id, kernel, NULL, 119 dtio_start_str, 0, NULL); 120 } 121 if (dtrace_probe_lookup(dtio_id, kernel, NULL, dtio_done_str) == 0) { 122 dtio_done_id = dtrace_probe_create(dtio_id, kernel, NULL, 123 dtio_done_str, 0, NULL); 124 } 125 if (dtrace_probe_lookup(dtio_id, kernel, NULL, 126 dtio_wait_start_str) == 0) { 127 dtio_wait_start_id = dtrace_probe_create(dtio_id, kernel, 128 NULL, 129 dtio_wait_start_str, 130 0, NULL); 131 } 132 if (dtrace_probe_lookup(dtio_id, kernel, NULL, 133 dtio_wait_done_str) == 0) { 134 dtio_wait_done_id = dtrace_probe_create(dtio_id, kernel, NULL, 135 dtio_wait_done_str, 0, NULL); 136 } 137 138} 139 140static void 141dtio_destroy(void *arg, dtrace_id_t id, void *parg) 142{ 143} 144 145static void 146dtio_enable(void *arg, dtrace_id_t id, void *parg) 147{ 148 if (id == dtio_start_id) 149 dtrace_io_start_probe = 150 (dtrace_io_start_probe_func_t)dtrace_probe; 151 else if (id == dtio_done_id) 152 dtrace_io_done_probe = 153 (dtrace_io_done_probe_func_t)dtrace_probe; 154 else if (id == dtio_wait_start_id) 155 dtrace_io_wait_start_probe = 156 (dtrace_io_wait_start_probe_func_t)dtrace_probe; 157 else if (id == dtio_wait_done_id) 158 dtrace_io_wait_done_probe = 159 (dtrace_io_wait_done_probe_func_t)dtrace_probe; 160 else 161 printf("dtrace io provider: unknown ID\n"); 162 163} 164 165static void 166dtio_disable(void *arg, dtrace_id_t id, void *parg) 167{ 168 if (id == dtio_start_id) 169 dtrace_io_start_probe = NULL; 170 else if (id == dtio_done_id) 171 dtrace_io_done_probe = NULL; 172 else if (id == dtio_wait_start_id) 173 dtrace_io_wait_start_probe = NULL; 174 else if (id == dtio_wait_done_id) 175 dtrace_io_wait_done_probe = NULL; 176 else 177 printf("dtrace io provider: unknown ID\n"); 178 179} 180 181static void 182dtio_load(void *dummy) 183{ 184 if (dtrace_register("io", &dtio_attr, DTRACE_PRIV_USER, NULL, 185 &dtio_pops, NULL, &dtio_id) != 0) 186 return; 187} 188 189 190static int 191dtio_unload() 192{ 193 dtrace_io_start_probe = NULL; 194 dtrace_io_done_probe = NULL; 195 dtrace_io_wait_start_probe = NULL; 196 dtrace_io_wait_done_probe = NULL; 197 198 return (dtrace_unregister(dtio_id)); 199} 200 201static int 202dtio_modevent(module_t mod __unused, int type, void *data __unused) 203{ 204 int error = 0; 205 206 switch (type) { 207 case MOD_LOAD: 208 break; 209 210 case MOD_UNLOAD: 211 break; 212 213 case MOD_SHUTDOWN: 214 break; 215 216 default: 217 error = EOPNOTSUPP; 218 break; 219 } 220 221 return (error); 222} 223 224SYSINIT(dtio_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, 225 dtio_load, NULL); 226SYSUNINIT(dtio_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, 227 dtio_unload, NULL); 228 229DEV_MODULE(dtio, dtio_modevent, NULL); 230MODULE_VERSION(dtio, 1); 231MODULE_DEPEND(dtio, dtrace, 1, 1, 1); 232MODULE_DEPEND(dtio, opensolaris, 1, 1, 1); 233