192108Sphk/*- 292108Sphk * Copyright (c) 2002 Poul-Henning Kamp 392108Sphk * Copyright (c) 2002 Networks Associates Technology, Inc. 492108Sphk * All rights reserved. 592108Sphk * 692108Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp 792108Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc. 892108Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 992108Sphk * DARPA CHATS research program. 1092108Sphk * 1192108Sphk * Redistribution and use in source and binary forms, with or without 1292108Sphk * modification, are permitted provided that the following conditions 1392108Sphk * are met: 1492108Sphk * 1. Redistributions of source code must retain the above copyright 1592108Sphk * notice, this list of conditions and the following disclaimer. 1692108Sphk * 2. Redistributions in binary form must reproduce the above copyright 1792108Sphk * notice, this list of conditions and the following disclaimer in the 1892108Sphk * documentation and/or other materials provided with the distribution. 1992108Sphk * 3. The names of the authors may not be used to endorse or promote 2092108Sphk * products derived from this software without specific prior written 2192108Sphk * permission. 2292108Sphk * 2392108Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2492108Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2592108Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2692108Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2792108Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2892108Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2992108Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3092108Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3192108Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3292108Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3392108Sphk * SUCH DAMAGE. 3492108Sphk */ 3592108Sphk 36116196Sobrien#include <sys/cdefs.h> 37116196Sobrien__FBSDID("$FreeBSD$"); 38116196Sobrien 3992108Sphk#include <sys/param.h> 4092108Sphk#include <sys/systm.h> 4192108Sphk#include <sys/kernel.h> 42113926Sphk#include <sys/eventhandler.h> 4392108Sphk#include <sys/malloc.h> 4492108Sphk#include <sys/bio.h> 4592108Sphk#include <sys/sysctl.h> 4692108Sphk#include <sys/proc.h> 47221792Sthompsa#include <sys/unistd.h> 4892108Sphk#include <sys/kthread.h> 4992108Sphk#include <sys/lock.h> 5092108Sphk#include <sys/mutex.h> 51139451Sjhb#include <sys/sbuf.h> 52139451Sjhb#include <sys/sched.h> 5392108Sphk#include <sys/sx.h> 5492108Sphk#include <geom/geom.h> 5593250Sphk#include <geom/geom_int.h> 5692108Sphk 5792108SphkMALLOC_DEFINE(M_GEOM, "GEOM", "Geom data structures"); 5892108Sphk 5992108Sphkstruct sx topology_lock; 6092108Sphk 61221792Sthompsastatic struct proc *g_proc; 62221792Sthompsastatic struct thread *g_up_td; 63221792Sthompsastatic struct thread *g_down_td; 64221792Sthompsastatic struct thread *g_event_td; 6592108Sphk 6692108Sphkint g_debugflags; 67110592Sphkint g_collectstats = 1; 68113926Sphkint g_shutdown; 69255860Sdesint g_notaste; 7092108Sphk 71104063Sphk/* 72104063Sphk * G_UP and G_DOWN are the two threads which push I/O through the 73104063Sphk * stack. 74104063Sphk * 75104063Sphk * Things are procesed in a FIFO order, but these threads could be 76104063Sphk * part of I/O prioritization by deciding which bios/bioqs to service 77104063Sphk * in what order. 78104063Sphk * 79104063Sphk * We have only one thread in each direction, it is belived that until 80104063Sphk * a very non-trivial workload in the UP/DOWN path this will be enough, 81104063Sphk * but more than one can actually be run without problems. 82104063Sphk * 83104063Sphk * Holding the "mymutex" is a debugging feature: It prevents people 84104063Sphk * from sleeping in the UP/DOWN I/O path by mistake or design (doing 85104063Sphk * so almost invariably result in deadlocks since it stalls all I/O 86104063Sphk * processing in the given direction. 87104063Sphk */ 88104063Sphk 8992108Sphkstatic void 90221792Sthompsag_up_procbody(void *arg) 9192108Sphk{ 9292108Sphk 93108296Sphk mtx_assert(&Giant, MA_NOTOWNED); 94221792Sthompsa thread_lock(g_up_td); 95221792Sthompsa sched_prio(g_up_td, PRIBIO); 96221792Sthompsa thread_unlock(g_up_td); 9792108Sphk for(;;) { 98221792Sthompsa g_io_schedule_up(g_up_td); 9992108Sphk } 10092108Sphk} 10192108Sphk 10292108Sphkstatic void 103221792Sthompsag_down_procbody(void *arg) 10492108Sphk{ 10592108Sphk 106108296Sphk mtx_assert(&Giant, MA_NOTOWNED); 107221792Sthompsa thread_lock(g_down_td); 108221792Sthompsa sched_prio(g_down_td, PRIBIO); 109221792Sthompsa thread_unlock(g_down_td); 11092108Sphk for(;;) { 111221792Sthompsa g_io_schedule_down(g_down_td); 11292108Sphk } 11392108Sphk} 11492108Sphk 11592108Sphkstatic void 116221792Sthompsag_event_procbody(void *arg) 11792108Sphk{ 11892108Sphk 119108296Sphk mtx_assert(&Giant, MA_NOTOWNED); 120221792Sthompsa thread_lock(g_event_td); 121221792Sthompsa sched_prio(g_event_td, PRIBIO); 122221792Sthompsa thread_unlock(g_event_td); 123215687Sjh g_run_events(); 124215687Sjh /* NOTREACHED */ 12592108Sphk} 12692108Sphk 127113926Sphkstatic void 128113926Sphkgeom_shutdown(void *foo __unused) 129113926Sphk{ 130113926Sphk 131113926Sphk g_shutdown = 1; 132113926Sphk} 133113926Sphk 13492108Sphkvoid 13592108Sphkg_init(void) 13692108Sphk{ 137116522Sphk 138116522Sphk g_trace(G_T_TOPOLOGY, "g_ignition"); 13992108Sphk sx_init(&topology_lock, "GEOM topology"); 14092108Sphk g_io_init(); 14192108Sphk g_event_init(); 142112534Sphk g_ctl_init(); 14392108Sphk mtx_lock(&Giant); 144221792Sthompsa kproc_kthread_add(g_event_procbody, NULL, &g_proc, &g_event_td, 145221792Sthompsa RFHIGHPID, 0, "geom", "g_event"); 146221792Sthompsa kproc_kthread_add(g_up_procbody, NULL, &g_proc, &g_up_td, 147221792Sthompsa RFHIGHPID, 0, "geom", "g_up"); 148221792Sthompsa kproc_kthread_add(g_down_procbody, NULL, &g_proc, &g_down_td, 149221792Sthompsa RFHIGHPID, 0, "geom", "g_down"); 15092108Sphk mtx_unlock(&Giant); 151113926Sphk EVENTHANDLER_REGISTER(shutdown_pre_sync, geom_shutdown, NULL, 152113926Sphk SHUTDOWN_PRI_FIRST); 15392108Sphk} 15492108Sphk 15592108Sphkstatic int 156106101Sphksysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS) 157106101Sphk{ 158106101Sphk int error; 159106101Sphk struct sbuf *sb; 160106101Sphk 161181463Sdes sb = sbuf_new_auto(); 162113940Sphk g_waitfor_event(g_conftxt, sb, M_WAITOK, NULL); 163106101Sphk error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); 164106101Sphk sbuf_delete(sb); 165106101Sphk return error; 166106101Sphk} 167106101Sphk 168106101Sphkstatic int 169104452Sphksysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS) 17092108Sphk{ 171104452Sphk int error; 17292108Sphk struct sbuf *sb; 17392108Sphk 174181463Sdes sb = sbuf_new_auto(); 175113940Sphk g_waitfor_event(g_confdot, sb, M_WAITOK, NULL); 176105358Sphk error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); 17792108Sphk sbuf_delete(sb); 178104452Sphk return error; 17992108Sphk} 180104452Sphk 18192108Sphkstatic int 182104452Sphksysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS) 18392108Sphk{ 184104452Sphk int error; 18592108Sphk struct sbuf *sb; 18692108Sphk 187181463Sdes sb = sbuf_new_auto(); 188113940Sphk g_waitfor_event(g_confxml, sb, M_WAITOK, NULL); 189105358Sphk error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); 19092108Sphk sbuf_delete(sb); 191104452Sphk return error; 19292108Sphk} 19392108Sphk 194104359SphkSYSCTL_NODE(_kern, OID_AUTO, geom, CTLFLAG_RW, 0, "GEOMetry management"); 195104359Sphk 196104452SphkSYSCTL_PROC(_kern_geom, OID_AUTO, confxml, CTLTYPE_STRING|CTLFLAG_RD, 197108308Sphk 0, 0, sysctl_kern_geom_confxml, "", 198106101Sphk "Dump the GEOM config in XML"); 19992108Sphk 200104452SphkSYSCTL_PROC(_kern_geom, OID_AUTO, confdot, CTLTYPE_STRING|CTLFLAG_RD, 201108308Sphk 0, 0, sysctl_kern_geom_confdot, "", 202106101Sphk "Dump the GEOM config in dot"); 203104359Sphk 204106101SphkSYSCTL_PROC(_kern_geom, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RD, 205108308Sphk 0, 0, sysctl_kern_geom_conftxt, "", 206106101Sphk "Dump the GEOM config in txt"); 207106101Sphk 208135151SpjdTUNABLE_INT("kern.geom.debugflags", &g_debugflags); 209105581SphkSYSCTL_INT(_kern_geom, OID_AUTO, debugflags, CTLFLAG_RW, 210152784Sle &g_debugflags, 0, "Set various trace levels for GEOM debugging"); 21192108Sphk 212255860SdesSYSCTL_INT(_kern_geom, OID_AUTO, notaste, CTLFLAG_RW, 213255860Sdes &g_notaste, 0, "Prevent GEOM tasting"); 214255860Sdes 215110523SphkSYSCTL_INT(_kern_geom, OID_AUTO, collectstats, CTLFLAG_RW, 216152784Sle &g_collectstats, 0, 217152784Sle "Control statistics collection on GEOM providers and consumers"); 218110523Sphk 219105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_class, CTLFLAG_RD, 220152784Sle 0, sizeof(struct g_class), "sizeof(struct g_class)"); 221105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_geom, CTLFLAG_RD, 222152784Sle 0, sizeof(struct g_geom), "sizeof(struct g_geom)"); 223105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_provider, CTLFLAG_RD, 224152784Sle 0, sizeof(struct g_provider), "sizeof(struct g_provider)"); 225105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_consumer, CTLFLAG_RD, 226152784Sle 0, sizeof(struct g_consumer), "sizeof(struct g_consumer)"); 227105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_bioq, CTLFLAG_RD, 228152784Sle 0, sizeof(struct g_bioq), "sizeof(struct g_bioq)"); 229