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: releng/10.2/sys/geom/geom_kern.c 273736 2014-10-27 14:38:00Z hselasky $");
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
127260385Sscottlint
128260385Sscottlg_is_geom_thread(struct thread *td)
129260385Sscottl{
130260385Sscottl
131260385Sscottl	return (td == g_up_td || td == g_down_td || td == g_event_td);
132260385Sscottl}
133260385Sscottl
134113926Sphkstatic void
135113926Sphkgeom_shutdown(void *foo __unused)
136113926Sphk{
137113926Sphk
138113926Sphk	g_shutdown = 1;
139113926Sphk}
140113926Sphk
14192108Sphkvoid
14292108Sphkg_init(void)
14392108Sphk{
144116522Sphk
145116522Sphk	g_trace(G_T_TOPOLOGY, "g_ignition");
14692108Sphk	sx_init(&topology_lock, "GEOM topology");
14792108Sphk	g_io_init();
14892108Sphk	g_event_init();
149112534Sphk	g_ctl_init();
15092108Sphk	mtx_lock(&Giant);
151221792Sthompsa	kproc_kthread_add(g_event_procbody, NULL, &g_proc, &g_event_td,
152221792Sthompsa	    RFHIGHPID, 0, "geom", "g_event");
153221792Sthompsa	kproc_kthread_add(g_up_procbody, NULL, &g_proc, &g_up_td,
154221792Sthompsa	    RFHIGHPID, 0, "geom", "g_up");
155221792Sthompsa	kproc_kthread_add(g_down_procbody, NULL, &g_proc, &g_down_td,
156221792Sthompsa	    RFHIGHPID, 0, "geom", "g_down");
15792108Sphk	mtx_unlock(&Giant);
158113926Sphk	EVENTHANDLER_REGISTER(shutdown_pre_sync, geom_shutdown, NULL,
159113926Sphk		SHUTDOWN_PRI_FIRST);
16092108Sphk}
16192108Sphk
16292108Sphkstatic int
163106101Sphksysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS)
164106101Sphk{
165106101Sphk	int error;
166106101Sphk	struct sbuf *sb;
167106101Sphk
168181463Sdes	sb = sbuf_new_auto();
169113940Sphk	g_waitfor_event(g_conftxt, sb, M_WAITOK, NULL);
170106101Sphk	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
171106101Sphk	sbuf_delete(sb);
172106101Sphk	return error;
173106101Sphk}
174106101Sphk
175106101Sphkstatic int
176104452Sphksysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS)
17792108Sphk{
178104452Sphk	int error;
17992108Sphk	struct sbuf *sb;
18092108Sphk
181181463Sdes	sb = sbuf_new_auto();
182113940Sphk	g_waitfor_event(g_confdot, sb, M_WAITOK, NULL);
183105358Sphk	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
18492108Sphk	sbuf_delete(sb);
185104452Sphk	return error;
18692108Sphk}
187104452Sphk
18892108Sphkstatic int
189104452Sphksysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS)
19092108Sphk{
191104452Sphk	int error;
19292108Sphk	struct sbuf *sb;
19392108Sphk
194181463Sdes	sb = sbuf_new_auto();
195113940Sphk	g_waitfor_event(g_confxml, sb, M_WAITOK, NULL);
196105358Sphk	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
19792108Sphk	sbuf_delete(sb);
198104452Sphk	return error;
19992108Sphk}
20092108Sphk
201104359SphkSYSCTL_NODE(_kern, OID_AUTO, geom, CTLFLAG_RW, 0, "GEOMetry management");
202104359Sphk
203104452SphkSYSCTL_PROC(_kern_geom, OID_AUTO, confxml, CTLTYPE_STRING|CTLFLAG_RD,
204108308Sphk	0, 0, sysctl_kern_geom_confxml, "",
205106101Sphk	"Dump the GEOM config in XML");
20692108Sphk
207104452SphkSYSCTL_PROC(_kern_geom, OID_AUTO, confdot, CTLTYPE_STRING|CTLFLAG_RD,
208108308Sphk	0, 0, sysctl_kern_geom_confdot, "",
209106101Sphk	"Dump the GEOM config in dot");
210104359Sphk
211106101SphkSYSCTL_PROC(_kern_geom, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RD,
212108308Sphk	0, 0, sysctl_kern_geom_conftxt, "",
213106101Sphk	"Dump the GEOM config in txt");
214106101Sphk
215135151SpjdTUNABLE_INT("kern.geom.debugflags", &g_debugflags);
216105581SphkSYSCTL_INT(_kern_geom, OID_AUTO, debugflags, CTLFLAG_RW,
217152784Sle	&g_debugflags, 0, "Set various trace levels for GEOM debugging");
21892108Sphk
219255860SdesSYSCTL_INT(_kern_geom, OID_AUTO, notaste, CTLFLAG_RW,
220255860Sdes	&g_notaste, 0, "Prevent GEOM tasting");
221255860Sdes
222110523SphkSYSCTL_INT(_kern_geom, OID_AUTO, collectstats, CTLFLAG_RW,
223152784Sle	&g_collectstats, 0,
224152784Sle	"Control statistics collection on GEOM providers and consumers");
225110523Sphk
226105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_class, CTLFLAG_RD,
227273736Shselasky	SYSCTL_NULL_INT_PTR, sizeof(struct g_class), "sizeof(struct g_class)");
228105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_geom, CTLFLAG_RD,
229273736Shselasky	SYSCTL_NULL_INT_PTR, sizeof(struct g_geom), "sizeof(struct g_geom)");
230105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_provider, CTLFLAG_RD,
231273736Shselasky	SYSCTL_NULL_INT_PTR, sizeof(struct g_provider), "sizeof(struct g_provider)");
232105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_consumer, CTLFLAG_RD,
233273736Shselasky	SYSCTL_NULL_INT_PTR, sizeof(struct g_consumer), "sizeof(struct g_consumer)");
234105581SphkSYSCTL_INT(_debug_sizeof, OID_AUTO, g_bioq, CTLFLAG_RD,
235273736Shselasky	SYSCTL_NULL_INT_PTR, sizeof(struct g_bioq), "sizeof(struct g_bioq)");
236