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