geom_kern.c revision 108308
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 * $FreeBSD: head/sys/geom/geom_kern.c 108308 2002-12-27 07:58:59Z phk $
3692108Sphk */
3792108Sphk
3892108Sphk#include <sys/param.h>
3992108Sphk#include <sys/systm.h>
4092108Sphk#include <sys/kernel.h>
4192108Sphk#include <sys/malloc.h>
4292108Sphk#include <sys/bio.h>
4392108Sphk#include <sys/sysctl.h>
4492108Sphk#include <sys/proc.h>
4592108Sphk#include <sys/kthread.h>
4692108Sphk#include <sys/lock.h>
4792108Sphk#include <sys/mutex.h>
4892108Sphk#include <sys/sx.h>
4992108Sphk#include <sys/sbuf.h>
5092108Sphk#include <geom/geom.h>
5193250Sphk#include <geom/geom_int.h>
5292108Sphk
5392108SphkMALLOC_DEFINE(M_GEOM, "GEOM", "Geom data structures");
5492108Sphk
5592108Sphkstruct sx topology_lock;
5692108Sphk
5792108Sphkstatic struct proc *g_up_proc;
5892108Sphk
5992108Sphkint g_debugflags;
6092108Sphk
61104063Sphk/*
62104063Sphk * G_UP and G_DOWN are the two threads which push I/O through the
63104063Sphk * stack.
64104063Sphk *
65104063Sphk * Things are procesed in a FIFO order, but these threads could be
66104063Sphk * part of I/O prioritization by deciding which bios/bioqs to service
67104063Sphk * in what order.
68104063Sphk *
69104063Sphk * We have only one thread in each direction, it is belived that until
70104063Sphk * a very non-trivial workload in the UP/DOWN path this will be enough,
71104063Sphk * but more than one can actually be run without problems.
72104063Sphk *
73104063Sphk * Holding the "mymutex" is a debugging feature:  It prevents people
74104063Sphk * from sleeping in the UP/DOWN I/O path by mistake or design (doing
75104063Sphk * so almost invariably result in deadlocks since it stalls all I/O
76104063Sphk * processing in the given direction.
77104063Sphk */
78104063Sphk
7992108Sphkstatic void
8092108Sphkg_up_procbody(void)
8192108Sphk{
8292108Sphk	struct proc *p = g_up_proc;
8399028Sjulian	struct thread *tp = FIRST_THREAD_IN_PROC(p);
84104063Sphk	struct mtx mymutex;
8592108Sphk
86108296Sphk	mtx_assert(&Giant, MA_NOTOWNED);
87104107Sphk	bzero(&mymutex, sizeof mymutex);
88104063Sphk	mtx_init(&mymutex, "g_up", MTX_DEF, 0);
89104063Sphk	mtx_lock(&mymutex);
90104087Sphk	tp->td_base_pri = PRIBIO;
9192108Sphk	for(;;) {
9292108Sphk		g_io_schedule_up(tp);
93104063Sphk		msleep(&g_wait_up, &mymutex, PRIBIO, "g_up", hz/10);
9492108Sphk	}
9592108Sphk}
9692108Sphk
9792108Sphkstruct kproc_desc g_up_kp = {
9892108Sphk	"g_up",
9992108Sphk	g_up_procbody,
10092108Sphk	&g_up_proc,
10192108Sphk};
10292108Sphk
10392108Sphkstatic struct proc *g_down_proc;
10492108Sphk
10592108Sphkstatic void
10692108Sphkg_down_procbody(void)
10792108Sphk{
10892108Sphk	struct proc *p = g_down_proc;
10999028Sjulian	struct thread *tp = FIRST_THREAD_IN_PROC(p);
110104063Sphk	struct mtx mymutex;
11192108Sphk
112108296Sphk	mtx_assert(&Giant, MA_NOTOWNED);
113104107Sphk	bzero(&mymutex, sizeof mymutex);
114104063Sphk	mtx_init(&mymutex, "g_down", MTX_DEF, 0);
115104063Sphk	mtx_lock(&mymutex);
116104087Sphk	tp->td_base_pri = PRIBIO;
11792108Sphk	for(;;) {
11892108Sphk		g_io_schedule_down(tp);
119104063Sphk		msleep(&g_wait_down, &mymutex, PRIBIO, "g_down", hz/10);
12092108Sphk	}
12192108Sphk}
12292108Sphk
12392108Sphkstruct kproc_desc g_down_kp = {
12492108Sphk	"g_down",
12592108Sphk	g_down_procbody,
12692108Sphk	&g_down_proc,
12792108Sphk};
12892108Sphk
12992108Sphkstatic struct proc *g_event_proc;
13092108Sphk
13192108Sphkstatic void
13292108Sphkg_event_procbody(void)
13392108Sphk{
134107452Sphk	struct proc *p = g_event_proc;
135104087Sphk	struct thread *tp = FIRST_THREAD_IN_PROC(p);
13692108Sphk
137108296Sphk	mtx_assert(&Giant, MA_NOTOWNED);
138104087Sphk	tp->td_base_pri = PRIBIO;
13992108Sphk	for(;;) {
14093250Sphk		g_run_events();
14192108Sphk		tsleep(&g_wait_event, PRIBIO, "g_events", hz/10);
14292108Sphk	}
14392108Sphk}
14492108Sphk
14592108Sphkstruct kproc_desc g_event_kp = {
14692108Sphk	"g_event",
14792108Sphk	g_event_procbody,
14892108Sphk	&g_event_proc,
14992108Sphk};
15092108Sphk
15192108Sphkvoid
15292108Sphkg_init(void)
15392108Sphk{
15492108Sphk	printf("Initializing GEOMetry subsystem\n");
15592108Sphk	sx_init(&topology_lock, "GEOM topology");
15692108Sphk	g_io_init();
15792108Sphk	g_event_init();
15892108Sphk	mtx_lock(&Giant);
15992108Sphk	kproc_start(&g_event_kp);
16092108Sphk	kproc_start(&g_up_kp);
16192108Sphk	kproc_start(&g_down_kp);
16292108Sphk	mtx_unlock(&Giant);
16392108Sphk}
16492108Sphk
16592108Sphkstatic int
166106101Sphksysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS)
167106101Sphk{
168106101Sphk	int error;
169106101Sphk	struct sbuf *sb;
170106101Sphk
171106101Sphk	sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
172106101Sphk	sbuf_clear(sb);
173106101Sphk	g_call_me(g_conftxt, sb);
174106101Sphk	do {
175106101Sphk		tsleep(sb, PZERO, "g_dot", hz);
176106101Sphk	} while(!sbuf_done(sb));
177106101Sphk	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
178106101Sphk	sbuf_delete(sb);
179106101Sphk	return error;
180106101Sphk}
181106101Sphk
182106101Sphkstatic int
183104452Sphksysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS)
18492108Sphk{
185104452Sphk	int error;
18692108Sphk	struct sbuf *sb;
18792108Sphk
188104452Sphk	sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
189104452Sphk	sbuf_clear(sb);
190104452Sphk	g_call_me(g_confdot, sb);
191104452Sphk	do {
192104452Sphk		tsleep(sb, PZERO, "g_dot", hz);
193104452Sphk	} while(!sbuf_done(sb));
194105358Sphk	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
19592108Sphk	sbuf_delete(sb);
196104452Sphk	return error;
19792108Sphk}
198104452Sphk
19992108Sphkstatic int
200104452Sphksysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS)
20192108Sphk{
202104452Sphk	int error;
20392108Sphk	struct sbuf *sb;
20492108Sphk
205104452Sphk	sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
206104452Sphk	sbuf_clear(sb);
207104452Sphk	g_call_me(g_confxml, sb);
208104452Sphk	do {
209104452Sphk		tsleep(sb, PZERO, "g_xml", hz);
210104452Sphk	} while(!sbuf_done(sb));
211105358Sphk	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
21292108Sphk	sbuf_delete(sb);
213104452Sphk	return error;
21492108Sphk}
21592108Sphk
216104359SphkSYSCTL_NODE(_kern, OID_AUTO, geom, CTLFLAG_RW, 0, "GEOMetry management");
217104359Sphk
218104452SphkSYSCTL_PROC(_kern_geom, OID_AUTO, confxml, CTLTYPE_STRING|CTLFLAG_RD,
219108308Sphk	0, 0, sysctl_kern_geom_confxml, "",
220106101Sphk	"Dump the GEOM config in XML");
22192108Sphk
222104452SphkSYSCTL_PROC(_kern_geom, OID_AUTO, confdot, CTLTYPE_STRING|CTLFLAG_RD,
223108308Sphk	0, 0, sysctl_kern_geom_confdot, "",
224106101Sphk	"Dump the GEOM config in dot");
225104359Sphk
226106101SphkSYSCTL_PROC(_kern_geom, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RD,
227108308Sphk	0, 0, sysctl_kern_geom_conftxt, "",
228106101Sphk	"Dump the GEOM config in txt");
229106101Sphk
230105581SphkSYSCTL_INT(_kern_geom, OID_AUTO, debugflags, CTLFLAG_RW,
23192108Sphk	&g_debugflags, 0, "");
23292108Sphk
233105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_class, CTLFLAG_RD,
23493248Sphk	0, sizeof(struct g_class), "");
235105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_geom, CTLFLAG_RD,
23692108Sphk	0, sizeof(struct g_geom), "");
237105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_provider, CTLFLAG_RD,
23892108Sphk	0, sizeof(struct g_provider), "");
239105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_consumer, CTLFLAG_RD,
24092108Sphk	0, sizeof(struct g_consumer), "");
241105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_bioq, CTLFLAG_RD,
24292108Sphk	0, sizeof(struct g_bioq), "");
243105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_event, CTLFLAG_RD,
24492108Sphk	0, sizeof(struct g_event), "");
245