geom_kern.c revision 116196
1215976Sjmallett/*-
2215976Sjmallett * Copyright (c) 2002 Poul-Henning Kamp
3215976Sjmallett * Copyright (c) 2002 Networks Associates Technology, Inc.
4215976Sjmallett * All rights reserved.
5215976Sjmallett *
6215976Sjmallett * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7215976Sjmallett * and NAI Labs, the Security Research Division of Network Associates, Inc.
8215976Sjmallett * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9215976Sjmallett * DARPA CHATS research program.
10215976Sjmallett *
11215976Sjmallett * Redistribution and use in source and binary forms, with or without
12215976Sjmallett * modification, are permitted provided that the following conditions
13215976Sjmallett * are met:
14215976Sjmallett * 1. Redistributions of source code must retain the above copyright
15215976Sjmallett *    notice, this list of conditions and the following disclaimer.
16215976Sjmallett * 2. Redistributions in binary form must reproduce the above copyright
17215976Sjmallett *    notice, this list of conditions and the following disclaimer in the
18215976Sjmallett *    documentation and/or other materials provided with the distribution.
19215976Sjmallett * 3. The names of the authors may not be used to endorse or promote
20215976Sjmallett *    products derived from this software without specific prior written
21215976Sjmallett *    permission.
22215976Sjmallett *
23215976Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24215976Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25215976Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26215976Sjmallett * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27215976Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28215976Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29215976Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30215976Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31215976Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32215976Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33215976Sjmallett * SUCH DAMAGE.
34215976Sjmallett */
35215976Sjmallett
36215976Sjmallett#include <sys/cdefs.h>
37215976Sjmallett__FBSDID("$FreeBSD: head/sys/geom/geom_kern.c 116196 2003-06-11 06:49:16Z obrien $");
38215976Sjmallett
39215976Sjmallett#include <sys/param.h>
40215976Sjmallett#include <sys/systm.h>
41215976Sjmallett#include <sys/kernel.h>
42215976Sjmallett#include <sys/eventhandler.h>
43215976Sjmallett#include <sys/malloc.h>
44215976Sjmallett#include <sys/bio.h>
45215976Sjmallett#include <sys/sysctl.h>
46215976Sjmallett#include <sys/proc.h>
47215976Sjmallett#include <sys/kthread.h>
48215976Sjmallett#include <sys/lock.h>
49215976Sjmallett#include <sys/mutex.h>
50215976Sjmallett#include <sys/sx.h>
51215976Sjmallett#include <sys/sbuf.h>
52215976Sjmallett#include <geom/geom.h>
53215976Sjmallett#include <geom/geom_int.h>
54215976Sjmallett
55215976SjmallettMALLOC_DEFINE(M_GEOM, "GEOM", "Geom data structures");
56215976Sjmallett
57215976Sjmallettstruct sx topology_lock;
58215976Sjmallett
59215976Sjmallettstatic struct proc *g_up_proc;
60215976Sjmallett
61215976Sjmallettint g_debugflags;
62215976Sjmallettint g_collectstats = 1;
63215976Sjmallettint g_shutdown;
64215976Sjmallett
65215976Sjmallett/*
66215976Sjmallett * G_UP and G_DOWN are the two threads which push I/O through the
67215976Sjmallett * stack.
68215976Sjmallett *
69215976Sjmallett * Things are procesed in a FIFO order, but these threads could be
70215976Sjmallett * part of I/O prioritization by deciding which bios/bioqs to service
71215976Sjmallett * in what order.
72215976Sjmallett *
73215976Sjmallett * We have only one thread in each direction, it is belived that until
74215976Sjmallett * a very non-trivial workload in the UP/DOWN path this will be enough,
75215976Sjmallett * but more than one can actually be run without problems.
76215976Sjmallett *
77215976Sjmallett * Holding the "mymutex" is a debugging feature:  It prevents people
78215976Sjmallett * from sleeping in the UP/DOWN I/O path by mistake or design (doing
79215976Sjmallett * so almost invariably result in deadlocks since it stalls all I/O
80215976Sjmallett * processing in the given direction.
81215976Sjmallett */
82215976Sjmallett
83215976Sjmallettstatic void
84215976Sjmallettg_up_procbody(void)
85215976Sjmallett{
86215976Sjmallett	struct proc *p = g_up_proc;
87215976Sjmallett	struct thread *tp = FIRST_THREAD_IN_PROC(p);
88215976Sjmallett
89215976Sjmallett	mtx_assert(&Giant, MA_NOTOWNED);
90215976Sjmallett	tp->td_base_pri = PRIBIO;
91215976Sjmallett	for(;;) {
92215976Sjmallett		g_io_schedule_up(tp);
93215976Sjmallett	}
94215976Sjmallett}
95215976Sjmallett
96215976Sjmallettstruct kproc_desc g_up_kp = {
97215976Sjmallett	"g_up",
98215976Sjmallett	g_up_procbody,
99215976Sjmallett	&g_up_proc,
100215976Sjmallett};
101215976Sjmallett
102215976Sjmallettstatic struct proc *g_down_proc;
103215976Sjmallett
104215976Sjmallettstatic void
105215976Sjmallettg_down_procbody(void)
106215976Sjmallett{
107215976Sjmallett	struct proc *p = g_down_proc;
108215976Sjmallett	struct thread *tp = FIRST_THREAD_IN_PROC(p);
109215976Sjmallett
110215976Sjmallett	mtx_assert(&Giant, MA_NOTOWNED);
111215976Sjmallett	tp->td_base_pri = PRIBIO;
112215976Sjmallett	for(;;) {
113215976Sjmallett		g_io_schedule_down(tp);
114215976Sjmallett	}
115215976Sjmallett}
116215976Sjmallett
117215976Sjmallettstruct kproc_desc g_down_kp = {
118215976Sjmallett	"g_down",
119215976Sjmallett	g_down_procbody,
120215976Sjmallett	&g_down_proc,
121215976Sjmallett};
122215976Sjmallett
123215976Sjmallettstatic struct proc *g_event_proc;
124215976Sjmallett
125215976Sjmallettstatic void
126215976Sjmallettg_event_procbody(void)
127215976Sjmallett{
128215976Sjmallett	struct proc *p = g_event_proc;
129215976Sjmallett	struct thread *tp = FIRST_THREAD_IN_PROC(p);
130215976Sjmallett
131215976Sjmallett	mtx_assert(&Giant, MA_NOTOWNED);
132215976Sjmallett	tp->td_base_pri = PRIBIO;
133215976Sjmallett	for(;;) {
134215976Sjmallett		g_run_events();
135215976Sjmallett		tsleep(&g_wait_event, PRIBIO, "g_events", hz/10);
136215976Sjmallett	}
137215976Sjmallett}
138215976Sjmallett
139215976Sjmallettstatic struct kproc_desc g_event_kp = {
140215976Sjmallett	"g_event",
141215976Sjmallett	g_event_procbody,
142215976Sjmallett	&g_event_proc,
143215976Sjmallett};
144215976Sjmallett
145215976Sjmallettstatic void
146215976Sjmallettgeom_shutdown(void *foo __unused)
147215976Sjmallett{
148215976Sjmallett
149215976Sjmallett	g_shutdown = 1;
150215976Sjmallett}
151215976Sjmallett
152215976Sjmallettvoid
153215976Sjmallettg_init(void)
154215976Sjmallett{
155215976Sjmallett	sx_init(&topology_lock, "GEOM topology");
156215976Sjmallett	g_io_init();
157215976Sjmallett	g_event_init();
158215976Sjmallett	g_ctl_init();
159215976Sjmallett	mtx_lock(&Giant);
160215976Sjmallett	kproc_start(&g_event_kp);
161215976Sjmallett	kproc_start(&g_up_kp);
162215976Sjmallett	kproc_start(&g_down_kp);
163215976Sjmallett	mtx_unlock(&Giant);
164215976Sjmallett	EVENTHANDLER_REGISTER(shutdown_pre_sync, geom_shutdown, NULL,
165215976Sjmallett		SHUTDOWN_PRI_FIRST);
166215976Sjmallett}
167215976Sjmallett
168215976Sjmallettstatic int
169215976Sjmallettsysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS)
170215976Sjmallett{
171215976Sjmallett	int error;
172215976Sjmallett	struct sbuf *sb;
173215976Sjmallett
174215976Sjmallett	sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
175215976Sjmallett	sbuf_clear(sb);
176215976Sjmallett	g_waitfor_event(g_conftxt, sb, M_WAITOK, NULL);
177215976Sjmallett	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
178215976Sjmallett	sbuf_delete(sb);
179215976Sjmallett	return error;
180215976Sjmallett}
181215976Sjmallett
182215976Sjmallettstatic int
183215976Sjmallettsysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS)
184215976Sjmallett{
185215976Sjmallett	int error;
186215976Sjmallett	struct sbuf *sb;
187215976Sjmallett
188215976Sjmallett	sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
189215976Sjmallett	sbuf_clear(sb);
190215976Sjmallett	g_waitfor_event(g_confdot, sb, M_WAITOK, NULL);
191215976Sjmallett	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
192215976Sjmallett	sbuf_delete(sb);
193215976Sjmallett	return error;
194215976Sjmallett}
195215976Sjmallett
196215976Sjmallettstatic int
197215976Sjmallettsysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS)
198215976Sjmallett{
199215976Sjmallett	int error;
200215976Sjmallett	struct sbuf *sb;
201215976Sjmallett
202215976Sjmallett	sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
203215976Sjmallett	sbuf_clear(sb);
204215976Sjmallett	g_waitfor_event(g_confxml, sb, M_WAITOK, NULL);
205215976Sjmallett	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
206215976Sjmallett	sbuf_delete(sb);
207215976Sjmallett	return error;
208215976Sjmallett}
209215976Sjmallett
210215976SjmallettSYSCTL_NODE(_kern, OID_AUTO, geom, CTLFLAG_RW, 0, "GEOMetry management");
211215976Sjmallett
212215976SjmallettSYSCTL_PROC(_kern_geom, OID_AUTO, confxml, CTLTYPE_STRING|CTLFLAG_RD,
213215976Sjmallett	0, 0, sysctl_kern_geom_confxml, "",
214215976Sjmallett	"Dump the GEOM config in XML");
215215976Sjmallett
216215976SjmallettSYSCTL_PROC(_kern_geom, OID_AUTO, confdot, CTLTYPE_STRING|CTLFLAG_RD,
217215976Sjmallett	0, 0, sysctl_kern_geom_confdot, "",
218215976Sjmallett	"Dump the GEOM config in dot");
219215976Sjmallett
220215976SjmallettSYSCTL_PROC(_kern_geom, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RD,
221215976Sjmallett	0, 0, sysctl_kern_geom_conftxt, "",
222215976Sjmallett	"Dump the GEOM config in txt");
223215976Sjmallett
224215976SjmallettSYSCTL_INT(_kern_geom, OID_AUTO, debugflags, CTLFLAG_RW,
225215976Sjmallett	&g_debugflags, 0, "");
226215976Sjmallett
227215976SjmallettSYSCTL_INT(_kern_geom, OID_AUTO, collectstats, CTLFLAG_RW,
228215976Sjmallett	&g_collectstats, 0, "");
229215976Sjmallett
230215976SjmallettSYSCTL_INT(_debug_sizeof, OID_AUTO, g_class, CTLFLAG_RD,
231215976Sjmallett	0, sizeof(struct g_class), "");
232215976SjmallettSYSCTL_INT(_debug_sizeof, OID_AUTO, g_geom, CTLFLAG_RD,
233215976Sjmallett	0, sizeof(struct g_geom), "");
234215976SjmallettSYSCTL_INT(_debug_sizeof, OID_AUTO, g_provider, CTLFLAG_RD,
235215976Sjmallett	0, sizeof(struct g_provider), "");
236215976SjmallettSYSCTL_INT(_debug_sizeof, OID_AUTO, g_consumer, CTLFLAG_RD,
237215976Sjmallett	0, sizeof(struct g_consumer), "");
238215976SjmallettSYSCTL_INT(_debug_sizeof, OID_AUTO, g_bioq, CTLFLAG_RD,
239215976Sjmallett	0, sizeof(struct g_bioq), "");
240215976Sjmallett