geom_kern.c revision 110523
1/*- 2 * Copyright (c) 2002 Poul-Henning Kamp 3 * Copyright (c) 2002 Networks Associates Technology, Inc. 4 * All rights reserved. 5 * 6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7 * and NAI Labs, the Security Research Division of Network Associates, Inc. 8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9 * DARPA CHATS research program. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The names of the authors may not be used to endorse or promote 20 * products derived from this software without specific prior written 21 * permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $FreeBSD: head/sys/geom/geom_kern.c 110523 2003-02-07 23:08:24Z phk $ 36 */ 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/malloc.h> 42#include <sys/bio.h> 43#include <sys/sysctl.h> 44#include <sys/proc.h> 45#include <sys/kthread.h> 46#include <sys/lock.h> 47#include <sys/mutex.h> 48#include <sys/sx.h> 49#include <sys/sbuf.h> 50#include <geom/geom.h> 51#include <geom/geom_int.h> 52 53MALLOC_DEFINE(M_GEOM, "GEOM", "Geom data structures"); 54 55struct sx topology_lock; 56 57static struct proc *g_up_proc; 58 59int g_debugflags; 60int g_collectstats; 61 62/* 63 * G_UP and G_DOWN are the two threads which push I/O through the 64 * stack. 65 * 66 * Things are procesed in a FIFO order, but these threads could be 67 * part of I/O prioritization by deciding which bios/bioqs to service 68 * in what order. 69 * 70 * We have only one thread in each direction, it is belived that until 71 * a very non-trivial workload in the UP/DOWN path this will be enough, 72 * but more than one can actually be run without problems. 73 * 74 * Holding the "mymutex" is a debugging feature: It prevents people 75 * from sleeping in the UP/DOWN I/O path by mistake or design (doing 76 * so almost invariably result in deadlocks since it stalls all I/O 77 * processing in the given direction. 78 */ 79 80static void 81g_up_procbody(void) 82{ 83 struct proc *p = g_up_proc; 84 struct thread *tp = FIRST_THREAD_IN_PROC(p); 85 struct mtx mymutex; 86 87 mtx_assert(&Giant, MA_NOTOWNED); 88 bzero(&mymutex, sizeof mymutex); 89 mtx_init(&mymutex, "g_up", MTX_DEF, 0); 90 mtx_lock(&mymutex); 91 tp->td_base_pri = PRIBIO; 92 for(;;) { 93 g_io_schedule_up(tp); 94 msleep(&g_wait_up, &mymutex, PRIBIO, "g_up", hz/10); 95 } 96} 97 98struct kproc_desc g_up_kp = { 99 "g_up", 100 g_up_procbody, 101 &g_up_proc, 102}; 103 104static struct proc *g_down_proc; 105 106static void 107g_down_procbody(void) 108{ 109 struct proc *p = g_down_proc; 110 struct thread *tp = FIRST_THREAD_IN_PROC(p); 111 struct mtx mymutex; 112 113 mtx_assert(&Giant, MA_NOTOWNED); 114 bzero(&mymutex, sizeof mymutex); 115 mtx_init(&mymutex, "g_down", MTX_DEF, 0); 116 mtx_lock(&mymutex); 117 tp->td_base_pri = PRIBIO; 118 for(;;) { 119 g_io_schedule_down(tp); 120 msleep(&g_wait_down, &mymutex, PRIBIO, "g_down", hz/10); 121 } 122} 123 124struct kproc_desc g_down_kp = { 125 "g_down", 126 g_down_procbody, 127 &g_down_proc, 128}; 129 130static struct proc *g_event_proc; 131 132static void 133g_event_procbody(void) 134{ 135 struct proc *p = g_event_proc; 136 struct thread *tp = FIRST_THREAD_IN_PROC(p); 137 138 mtx_assert(&Giant, MA_NOTOWNED); 139 tp->td_base_pri = PRIBIO; 140 for(;;) { 141 g_run_events(); 142 tsleep(&g_wait_event, PRIBIO, "g_events", hz/10); 143 } 144} 145 146struct kproc_desc g_event_kp = { 147 "g_event", 148 g_event_procbody, 149 &g_event_proc, 150}; 151 152void 153g_init(void) 154{ 155 printf("Initializing GEOMetry subsystem\n"); 156 sx_init(&topology_lock, "GEOM topology"); 157 g_io_init(); 158 g_event_init(); 159 mtx_lock(&Giant); 160 kproc_start(&g_event_kp); 161 kproc_start(&g_up_kp); 162 kproc_start(&g_down_kp); 163 mtx_unlock(&Giant); 164} 165 166static int 167sysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS) 168{ 169 int error; 170 struct sbuf *sb; 171 172 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 173 sbuf_clear(sb); 174 g_call_me(g_conftxt, sb); 175 do { 176 tsleep(sb, PZERO, "g_conftxt", hz); 177 } while(!sbuf_done(sb)); 178 error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); 179 sbuf_delete(sb); 180 return error; 181} 182 183static int 184sysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS) 185{ 186 int error; 187 struct sbuf *sb; 188 189 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 190 sbuf_clear(sb); 191 g_call_me(g_confdot, sb); 192 do { 193 tsleep(sb, PZERO, "g_confdot", hz); 194 } while(!sbuf_done(sb)); 195 error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); 196 sbuf_delete(sb); 197 return error; 198} 199 200static int 201sysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS) 202{ 203 int error; 204 struct sbuf *sb; 205 206 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 207 sbuf_clear(sb); 208 g_call_me(g_confxml, sb); 209 do { 210 tsleep(sb, PZERO, "g_confxml", hz); 211 } while(!sbuf_done(sb)); 212 error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); 213 sbuf_delete(sb); 214 return error; 215} 216 217SYSCTL_NODE(_kern, OID_AUTO, geom, CTLFLAG_RW, 0, "GEOMetry management"); 218 219SYSCTL_PROC(_kern_geom, OID_AUTO, confxml, CTLTYPE_STRING|CTLFLAG_RD, 220 0, 0, sysctl_kern_geom_confxml, "", 221 "Dump the GEOM config in XML"); 222 223SYSCTL_PROC(_kern_geom, OID_AUTO, confdot, CTLTYPE_STRING|CTLFLAG_RD, 224 0, 0, sysctl_kern_geom_confdot, "", 225 "Dump the GEOM config in dot"); 226 227SYSCTL_PROC(_kern_geom, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RD, 228 0, 0, sysctl_kern_geom_conftxt, "", 229 "Dump the GEOM config in txt"); 230 231SYSCTL_INT(_kern_geom, OID_AUTO, debugflags, CTLFLAG_RW, 232 &g_debugflags, 0, ""); 233 234SYSCTL_INT(_kern_geom, OID_AUTO, collectstats, CTLFLAG_RW, 235 &g_collectstats, 0, ""); 236 237SYSCTL_INT(_debug_sizeof, OID_AUTO, g_class, CTLFLAG_RD, 238 0, sizeof(struct g_class), ""); 239SYSCTL_INT(_debug_sizeof, OID_AUTO, g_geom, CTLFLAG_RD, 240 0, sizeof(struct g_geom), ""); 241SYSCTL_INT(_debug_sizeof, OID_AUTO, g_provider, CTLFLAG_RD, 242 0, sizeof(struct g_provider), ""); 243SYSCTL_INT(_debug_sizeof, OID_AUTO, g_consumer, CTLFLAG_RD, 244 0, sizeof(struct g_consumer), ""); 245SYSCTL_INT(_debug_sizeof, OID_AUTO, g_bioq, CTLFLAG_RD, 246 0, sizeof(struct g_bioq), ""); 247SYSCTL_INT(_debug_sizeof, OID_AUTO, g_event, CTLFLAG_RD, 248 0, sizeof(struct g_event), ""); 249SYSCTL_INT(_debug_sizeof, OID_AUTO, g_stat, CTLFLAG_RD, 250 0, sizeof(struct g_stat), ""); 251