xref: /freebsd-src/sys/geom/geom_kern.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1dd84a43cSPoul-Henning Kamp /*-
23728855aSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
33728855aSPedro F. Giffuni  *
4dd84a43cSPoul-Henning Kamp  * Copyright (c) 2002 Poul-Henning Kamp
5dd84a43cSPoul-Henning Kamp  * Copyright (c) 2002 Networks Associates Technology, Inc.
6dd84a43cSPoul-Henning Kamp  * All rights reserved.
7dd84a43cSPoul-Henning Kamp  *
8dd84a43cSPoul-Henning Kamp  * This software was developed for the FreeBSD Project by Poul-Henning Kamp
9dd84a43cSPoul-Henning Kamp  * and NAI Labs, the Security Research Division of Network Associates, Inc.
10dd84a43cSPoul-Henning Kamp  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
11dd84a43cSPoul-Henning Kamp  * DARPA CHATS research program.
12dd84a43cSPoul-Henning Kamp  *
13dd84a43cSPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
14dd84a43cSPoul-Henning Kamp  * modification, are permitted provided that the following conditions
15dd84a43cSPoul-Henning Kamp  * are met:
16dd84a43cSPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
17dd84a43cSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
18dd84a43cSPoul-Henning Kamp  * 2. Redistributions in binary form must reproduce the above copyright
19dd84a43cSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer in the
20dd84a43cSPoul-Henning Kamp  *    documentation and/or other materials provided with the distribution.
21dd84a43cSPoul-Henning Kamp  * 3. The names of the authors may not be used to endorse or promote
22dd84a43cSPoul-Henning Kamp  *    products derived from this software without specific prior written
23dd84a43cSPoul-Henning Kamp  *    permission.
24dd84a43cSPoul-Henning Kamp  *
25dd84a43cSPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26dd84a43cSPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27dd84a43cSPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28dd84a43cSPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29dd84a43cSPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30dd84a43cSPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31dd84a43cSPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32dd84a43cSPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33dd84a43cSPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34dd84a43cSPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35dd84a43cSPoul-Henning Kamp  * SUCH DAMAGE.
36dd84a43cSPoul-Henning Kamp  */
37dd84a43cSPoul-Henning Kamp 
38dd84a43cSPoul-Henning Kamp #include <sys/param.h>
39dd84a43cSPoul-Henning Kamp #include <sys/systm.h>
40dd84a43cSPoul-Henning Kamp #include <sys/kernel.h>
41b5cba416SPoul-Henning Kamp #include <sys/eventhandler.h>
42dd84a43cSPoul-Henning Kamp #include <sys/malloc.h>
43dd84a43cSPoul-Henning Kamp #include <sys/bio.h>
44dd84a43cSPoul-Henning Kamp #include <sys/sysctl.h>
45dd84a43cSPoul-Henning Kamp #include <sys/proc.h>
46b2901e99SAndrew Thompson #include <sys/unistd.h>
47dd84a43cSPoul-Henning Kamp #include <sys/kthread.h>
48dd84a43cSPoul-Henning Kamp #include <sys/lock.h>
49dd84a43cSPoul-Henning Kamp #include <sys/mutex.h>
50dd84a43cSPoul-Henning Kamp #include <sys/sbuf.h>
5163710c4dSJohn Baldwin #include <sys/sched.h>
5263710c4dSJohn Baldwin #include <sys/sx.h>
53dd84a43cSPoul-Henning Kamp #include <geom/geom.h>
54b1876192SPoul-Henning Kamp #include <geom/geom_int.h>
55dd84a43cSPoul-Henning Kamp 
56dd84a43cSPoul-Henning Kamp MALLOC_DEFINE(M_GEOM, "GEOM", "Geom data structures");
57dd84a43cSPoul-Henning Kamp 
58dd84a43cSPoul-Henning Kamp struct sx topology_lock;
59dd84a43cSPoul-Henning Kamp 
60b2901e99SAndrew Thompson static struct proc *g_proc;
61*ffc1cc95SAlexander Motin struct thread __read_mostly *g_up_td;
62*ffc1cc95SAlexander Motin struct thread __read_mostly *g_down_td;
6361322a0aSAlexander Motin static struct thread __read_mostly *g_event_td;
64dd84a43cSPoul-Henning Kamp 
6561322a0aSAlexander Motin int __read_mostly g_debugflags;
6661322a0aSAlexander Motin int __read_mostly g_collectstats = G_STATS_PROVIDERS;
67b5cba416SPoul-Henning Kamp int g_shutdown;
681b2cb2b3SDag-Erling Smørgrav int g_notaste;
69dd84a43cSPoul-Henning Kamp 
70b1937dd1SPoul-Henning Kamp /*
71b1937dd1SPoul-Henning Kamp  * G_UP and G_DOWN are the two threads which push I/O through the
72b1937dd1SPoul-Henning Kamp  * stack.
73b1937dd1SPoul-Henning Kamp  *
74b1937dd1SPoul-Henning Kamp  * Things are procesed in a FIFO order, but these threads could be
75b1937dd1SPoul-Henning Kamp  * part of I/O prioritization by deciding which bios/bioqs to service
76b1937dd1SPoul-Henning Kamp  * in what order.
77b1937dd1SPoul-Henning Kamp  *
78e8d57122SPedro F. Giffuni  * We have only one thread in each direction, it is believed that until
79b1937dd1SPoul-Henning Kamp  * a very non-trivial workload in the UP/DOWN path this will be enough,
80b1937dd1SPoul-Henning Kamp  * but more than one can actually be run without problems.
81b1937dd1SPoul-Henning Kamp  *
82b1937dd1SPoul-Henning Kamp  * Holding the "mymutex" is a debugging feature:  It prevents people
83b1937dd1SPoul-Henning Kamp  * from sleeping in the UP/DOWN I/O path by mistake or design (doing
84b1937dd1SPoul-Henning Kamp  * so almost invariably result in deadlocks since it stalls all I/O
85b1937dd1SPoul-Henning Kamp  * processing in the given direction.
86b1937dd1SPoul-Henning Kamp  */
87b1937dd1SPoul-Henning Kamp 
88dd84a43cSPoul-Henning Kamp static void
g_up_procbody(void * arg)89b2901e99SAndrew Thompson g_up_procbody(void *arg)
90dd84a43cSPoul-Henning Kamp {
91dd84a43cSPoul-Henning Kamp 
92b2901e99SAndrew Thompson 	thread_lock(g_up_td);
93b2901e99SAndrew Thompson 	sched_prio(g_up_td, PRIBIO);
94b2901e99SAndrew Thompson 	thread_unlock(g_up_td);
95dd84a43cSPoul-Henning Kamp 	for(;;) {
96b2901e99SAndrew Thompson 		g_io_schedule_up(g_up_td);
97dd84a43cSPoul-Henning Kamp 	}
98dd84a43cSPoul-Henning Kamp }
99dd84a43cSPoul-Henning Kamp 
100dd84a43cSPoul-Henning Kamp static void
g_down_procbody(void * arg)101b2901e99SAndrew Thompson g_down_procbody(void *arg)
102dd84a43cSPoul-Henning Kamp {
103dd84a43cSPoul-Henning Kamp 
104b2901e99SAndrew Thompson 	thread_lock(g_down_td);
105b2901e99SAndrew Thompson 	sched_prio(g_down_td, PRIBIO);
106b2901e99SAndrew Thompson 	thread_unlock(g_down_td);
107dd84a43cSPoul-Henning Kamp 	for(;;) {
108b2901e99SAndrew Thompson 		g_io_schedule_down(g_down_td);
109dd84a43cSPoul-Henning Kamp 	}
110dd84a43cSPoul-Henning Kamp }
111dd84a43cSPoul-Henning Kamp 
112dd84a43cSPoul-Henning Kamp static void
g_event_procbody(void * arg)113b2901e99SAndrew Thompson g_event_procbody(void *arg)
114dd84a43cSPoul-Henning Kamp {
115dd84a43cSPoul-Henning Kamp 
116b2901e99SAndrew Thompson 	thread_lock(g_event_td);
117b2901e99SAndrew Thompson 	sched_prio(g_event_td, PRIBIO);
118b2901e99SAndrew Thompson 	thread_unlock(g_event_td);
119b1876192SPoul-Henning Kamp 	g_run_events();
120f7842e00SJaakko Heinonen 	/* NOTREACHED */
121dd84a43cSPoul-Henning Kamp }
122dd84a43cSPoul-Henning Kamp 
12340ea77a0SAlexander Motin int
g_is_geom_thread(struct thread * td)12440ea77a0SAlexander Motin g_is_geom_thread(struct thread *td)
12540ea77a0SAlexander Motin {
12640ea77a0SAlexander Motin 
12740ea77a0SAlexander Motin 	return (td == g_up_td || td == g_down_td || td == g_event_td);
12840ea77a0SAlexander Motin }
12940ea77a0SAlexander Motin 
130b5cba416SPoul-Henning Kamp static void
geom_shutdown(void * foo __unused)131b5cba416SPoul-Henning Kamp geom_shutdown(void *foo __unused)
132b5cba416SPoul-Henning Kamp {
133b5cba416SPoul-Henning Kamp 
134b5cba416SPoul-Henning Kamp 	g_shutdown = 1;
135b5cba416SPoul-Henning Kamp }
136b5cba416SPoul-Henning Kamp 
137dd84a43cSPoul-Henning Kamp void
g_init(void)138dd84a43cSPoul-Henning Kamp g_init(void)
139dd84a43cSPoul-Henning Kamp {
14044be139bSPoul-Henning Kamp 
14144be139bSPoul-Henning Kamp 	g_trace(G_T_TOPOLOGY, "g_ignition");
142dd84a43cSPoul-Henning Kamp 	sx_init(&topology_lock, "GEOM topology");
143dd84a43cSPoul-Henning Kamp 	g_io_init();
144dd84a43cSPoul-Henning Kamp 	g_event_init();
145d49d7ca5SPoul-Henning Kamp 	g_ctl_init();
146b2901e99SAndrew Thompson 	kproc_kthread_add(g_event_procbody, NULL, &g_proc, &g_event_td,
147b2901e99SAndrew Thompson 	    RFHIGHPID, 0, "geom", "g_event");
148b2901e99SAndrew Thompson 	kproc_kthread_add(g_up_procbody, NULL, &g_proc, &g_up_td,
149b2901e99SAndrew Thompson 	    RFHIGHPID, 0, "geom", "g_up");
150b2901e99SAndrew Thompson 	kproc_kthread_add(g_down_procbody, NULL, &g_proc, &g_down_td,
151b2901e99SAndrew Thompson 	    RFHIGHPID, 0, "geom", "g_down");
152b5cba416SPoul-Henning Kamp 	EVENTHANDLER_REGISTER(shutdown_pre_sync, geom_shutdown, NULL,
153b5cba416SPoul-Henning Kamp 		SHUTDOWN_PRI_FIRST);
154dd84a43cSPoul-Henning Kamp }
155dd84a43cSPoul-Henning Kamp 
156dd84a43cSPoul-Henning Kamp static int
sysctl_kern_geom_confany(struct sysctl_req * req,g_event_t * func,size_t * hint)1575c32e9fcSAlexander Motin sysctl_kern_geom_confany(struct sysctl_req *req, g_event_t *func, size_t *hint)
158d518e539SPoul-Henning Kamp {
1595c32e9fcSAlexander Motin 	size_t len = 0;
1605c32e9fcSAlexander Motin 	int error = 0;
161d518e539SPoul-Henning Kamp 	struct sbuf *sb;
162d518e539SPoul-Henning Kamp 
1635c32e9fcSAlexander Motin 	if (req->oldptr == NULL) {
1645c32e9fcSAlexander Motin 		sb = sbuf_new(NULL, NULL, PAGE_SIZE, SBUF_FIXEDLEN |
1655c32e9fcSAlexander Motin 		    SBUF_INCLUDENUL);
1665c32e9fcSAlexander Motin 		sbuf_set_drain(sb, sbuf_count_drain, &len);
1675c32e9fcSAlexander Motin 		g_waitfor_event(func, sb, M_WAITOK, NULL);
1685c32e9fcSAlexander Motin 		req->oldidx = *hint = len;
1695c32e9fcSAlexander Motin 	} else {
1705c32e9fcSAlexander Motin 		sb = sbuf_new(NULL, NULL, *hint, SBUF_AUTOEXTEND |
1715c32e9fcSAlexander Motin 		    SBUF_INCLUDENUL);
1725c32e9fcSAlexander Motin 		g_waitfor_event(func, sb, M_WAITOK, NULL);
1735c32e9fcSAlexander Motin 		*hint = sbuf_len(sb);
1745c32e9fcSAlexander Motin 		error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
1755c32e9fcSAlexander Motin 	}
176d518e539SPoul-Henning Kamp 	sbuf_delete(sb);
177d518e539SPoul-Henning Kamp 	return error;
178d518e539SPoul-Henning Kamp }
179d518e539SPoul-Henning Kamp 
180d518e539SPoul-Henning Kamp static int
sysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS)1815c32e9fcSAlexander Motin sysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS)
1825c32e9fcSAlexander Motin {
1835c32e9fcSAlexander Motin 	static size_t hint = PAGE_SIZE;
1845c32e9fcSAlexander Motin 
1855c32e9fcSAlexander Motin 	return (sysctl_kern_geom_confany(req, g_conftxt, &hint));
1865c32e9fcSAlexander Motin }
1875c32e9fcSAlexander Motin 
1885c32e9fcSAlexander Motin static int
sysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS)1892874f1cfSPoul-Henning Kamp sysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS)
190dd84a43cSPoul-Henning Kamp {
1915c32e9fcSAlexander Motin 	static size_t hint = PAGE_SIZE;
192dd84a43cSPoul-Henning Kamp 
1935c32e9fcSAlexander Motin 	return (sysctl_kern_geom_confany(req, g_confdot, &hint));
194dd84a43cSPoul-Henning Kamp }
195dd84a43cSPoul-Henning Kamp 
196dd84a43cSPoul-Henning Kamp static int
sysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS)1972874f1cfSPoul-Henning Kamp sysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS)
198dd84a43cSPoul-Henning Kamp {
1995c32e9fcSAlexander Motin 	static size_t hint = PAGE_SIZE;
200dd84a43cSPoul-Henning Kamp 
2015c32e9fcSAlexander Motin 	return (sysctl_kern_geom_confany(req, g_confxml, &hint));
202dd84a43cSPoul-Henning Kamp }
203dd84a43cSPoul-Henning Kamp 
2047029da5cSPawel Biernacki SYSCTL_NODE(_kern, OID_AUTO, geom, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
2057029da5cSPawel Biernacki     "GEOMetry management");
20629c21195SPoul-Henning Kamp 
2077029da5cSPawel Biernacki SYSCTL_PROC(_kern_geom, OID_AUTO, confxml,
208c2da9542SAlexander Motin     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 0,
2097029da5cSPawel Biernacki     sysctl_kern_geom_confxml, "",
210d518e539SPoul-Henning Kamp     "Dump the GEOM config in XML");
211dd84a43cSPoul-Henning Kamp 
2127029da5cSPawel Biernacki SYSCTL_PROC(_kern_geom, OID_AUTO, confdot,
213c2da9542SAlexander Motin     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 0,
2147029da5cSPawel Biernacki     sysctl_kern_geom_confdot, "",
215d518e539SPoul-Henning Kamp     "Dump the GEOM config in dot");
216d518e539SPoul-Henning Kamp 
2177029da5cSPawel Biernacki SYSCTL_PROC(_kern_geom, OID_AUTO, conftxt,
218c2da9542SAlexander Motin     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 0,
2197029da5cSPawel Biernacki     sysctl_kern_geom_conftxt, "",
220d518e539SPoul-Henning Kamp     "Dump the GEOM config in txt");
22129c21195SPoul-Henning Kamp 
222af3b2549SHans Petter Selasky SYSCTL_INT(_kern_geom, OID_AUTO, debugflags, CTLFLAG_RWTUN,
2238c957640SLukas Ertl 	&g_debugflags, 0, "Set various trace levels for GEOM debugging");
224dd84a43cSPoul-Henning Kamp 
2251b2cb2b3SDag-Erling Smørgrav SYSCTL_INT(_kern_geom, OID_AUTO, notaste, CTLFLAG_RW,
2261b2cb2b3SDag-Erling Smørgrav 	&g_notaste, 0, "Prevent GEOM tasting");
2271b2cb2b3SDag-Erling Smørgrav 
228801bb689SPoul-Henning Kamp SYSCTL_INT(_kern_geom, OID_AUTO, collectstats, CTLFLAG_RW,
2298c957640SLukas Ertl 	&g_collectstats, 0,
2308c957640SLukas Ertl 	"Control statistics collection on GEOM providers and consumers");
231801bb689SPoul-Henning Kamp 
2326adb7488SPoul-Henning Kamp SYSCTL_INT(_debug_sizeof, OID_AUTO, g_class, CTLFLAG_RD,
233f0188618SHans Petter Selasky 	SYSCTL_NULL_INT_PTR, sizeof(struct g_class), "sizeof(struct g_class)");
2346adb7488SPoul-Henning Kamp SYSCTL_INT(_debug_sizeof, OID_AUTO, g_geom, CTLFLAG_RD,
235f0188618SHans Petter Selasky 	SYSCTL_NULL_INT_PTR, sizeof(struct g_geom), "sizeof(struct g_geom)");
2366adb7488SPoul-Henning Kamp SYSCTL_INT(_debug_sizeof, OID_AUTO, g_provider, CTLFLAG_RD,
237f0188618SHans Petter Selasky 	SYSCTL_NULL_INT_PTR, sizeof(struct g_provider), "sizeof(struct g_provider)");
2386adb7488SPoul-Henning Kamp SYSCTL_INT(_debug_sizeof, OID_AUTO, g_consumer, CTLFLAG_RD,
239f0188618SHans Petter Selasky 	SYSCTL_NULL_INT_PTR, sizeof(struct g_consumer), "sizeof(struct g_consumer)");
2406adb7488SPoul-Henning Kamp SYSCTL_INT(_debug_sizeof, OID_AUTO, g_bioq, CTLFLAG_RD,
241f0188618SHans Petter Selasky 	SYSCTL_NULL_INT_PTR, sizeof(struct g_bioq), "sizeof(struct g_bioq)");
242