xref: /freebsd/usr.sbin/bsdconfig/share/geom.subr (revision 9ecd54f24fe9fa373e07c9fd7c052deb2188f545)
1*9ecd54f2SDevin Teskeif [ ! "$_GEOM_SUBR" ]; then _GEOM_SUBR=1
2*9ecd54f2SDevin Teske#
3*9ecd54f2SDevin Teske# Copyright (c) 2012-2014 Devin Teske
4*9ecd54f2SDevin Teske# All rights reserved.
5*9ecd54f2SDevin Teske#
6*9ecd54f2SDevin Teske# Redistribution and use in source and binary forms, with or without
7*9ecd54f2SDevin Teske# modification, are permitted provided that the following conditions
8*9ecd54f2SDevin Teske# are met:
9*9ecd54f2SDevin Teske# 1. Redistributions of source code must retain the above copyright
10*9ecd54f2SDevin Teske#    notice, this list of conditions and the following disclaimer.
11*9ecd54f2SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright
12*9ecd54f2SDevin Teske#    notice, this list of conditions and the following disclaimer in the
13*9ecd54f2SDevin Teske#    documentation and/or other materials provided with the distribution.
14*9ecd54f2SDevin Teske#
15*9ecd54f2SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*9ecd54f2SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*9ecd54f2SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*9ecd54f2SDevin Teske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*9ecd54f2SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*9ecd54f2SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*9ecd54f2SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*9ecd54f2SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*9ecd54f2SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*9ecd54f2SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*9ecd54f2SDevin Teske# SUCH DAMAGE.
26*9ecd54f2SDevin Teske#
27*9ecd54f2SDevin Teske# $FreeBSD$
28*9ecd54f2SDevin Teske#
29*9ecd54f2SDevin Teske############################################################ INCLUDES
30*9ecd54f2SDevin Teske
31*9ecd54f2SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
32*9ecd54f2SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
33*9ecd54f2SDevin Teskef_dprintf "%s: loading includes..." geom.subr
34*9ecd54f2SDevin Teskef_include $BSDCFG_SHARE/strings.subr
35*9ecd54f2SDevin Teskef_include $BSDCFG_SHARE/struct.subr
36*9ecd54f2SDevin Teske
37*9ecd54f2SDevin Teske############################################################ GLOBALS
38*9ecd54f2SDevin Teske
39*9ecd54f2SDevin TeskeNGEOM_CLASSES=0 # Set by f_geom_get_all()/f_geom_reset()
40*9ecd54f2SDevin Teske
41*9ecd54f2SDevin Teske#
42*9ecd54f2SDevin Teske# GEOM classes for use with f_geom_find()
43*9ecd54f2SDevin Teske#
44*9ecd54f2SDevin Teske# NB: Since $GEOM_CLASS_ANY is the NULL string, make sure you quote it whenever
45*9ecd54f2SDevin Teske#     you put arguments after it.
46*9ecd54f2SDevin Teske#
47*9ecd54f2SDevin Teskesetvar GEOM_CLASS_ANY		"any"
48*9ecd54f2SDevin Teskesetvar GEOM_CLASS_DEV		"DEV"
49*9ecd54f2SDevin Teskesetvar GEOM_CLASS_DISK		"DISK"
50*9ecd54f2SDevin Teskesetvar GEOM_CLASS_ELI		"ELI"
51*9ecd54f2SDevin Teskesetvar GEOM_CLASS_FD		"FD"
52*9ecd54f2SDevin Teskesetvar GEOM_CLASS_LABEL		"LABEL"
53*9ecd54f2SDevin Teskesetvar GEOM_CLASS_MD		"MD"
54*9ecd54f2SDevin Teskesetvar GEOM_CLASS_NOP		"NOP"
55*9ecd54f2SDevin Teskesetvar GEOM_CLASS_PART		"PART"
56*9ecd54f2SDevin Teskesetvar GEOM_CLASS_RAID		"RAID"
57*9ecd54f2SDevin Teskesetvar GEOM_CLASS_SWAP		"SWAP"
58*9ecd54f2SDevin Teskesetvar GEOM_CLASS_VFS		"VFS"
59*9ecd54f2SDevin Teskesetvar GEOM_CLASS_ZFS_VDEV	"ZFS::VDEV"
60*9ecd54f2SDevin Teskesetvar GEOM_CLASS_ZFS_ZVOL	"ZFS::ZVOL"
61*9ecd54f2SDevin Teske
62*9ecd54f2SDevin Teske#
63*9ecd54f2SDevin Teske# GEOM structure definitions
64*9ecd54f2SDevin Teske#
65*9ecd54f2SDevin Teskef_struct_define GEOM_CLASS \
66*9ecd54f2SDevin Teske	id name ngeoms
67*9ecd54f2SDevin Teskef_struct_define GEOM_GEOM \
68*9ecd54f2SDevin Teske	id class_ref config name nconsumers nproviders rank
69*9ecd54f2SDevin Teske	# Also consumerN where N is 1 through nconsumers
70*9ecd54f2SDevin Teske	# Also providerN where N is 1 through nproviders
71*9ecd54f2SDevin Teskef_struct_define GEOM_CONSUMER \
72*9ecd54f2SDevin Teske	id geom_ref config mode provider_ref
73*9ecd54f2SDevin Teskef_struct_define GEOM_PROVIDER \
74*9ecd54f2SDevin Teske	id geom_ref config mode name mediasize
75*9ecd54f2SDevin Teske
76*9ecd54f2SDevin Teske# The config property of GEOM_GEOM struct is defined as this
77*9ecd54f2SDevin Teskef_struct_define GEOM_GEOM_CONFIG \
78*9ecd54f2SDevin Teske	entries first fwheads fwsectors last modified scheme state
79*9ecd54f2SDevin Teske
80*9ecd54f2SDevin Teske# The config property of GEOM_PROVIDER struct is defined as this
81*9ecd54f2SDevin Teskef_struct_define GEOM_PROVIDER_CONFIG \
82*9ecd54f2SDevin Teske	descr file fwheads fwsectors ident length type unit
83*9ecd54f2SDevin Teske
84*9ecd54f2SDevin Teske#
85*9ecd54f2SDevin Teske# Default behavior is to call f_geom_get_all() automatically when loaded.
86*9ecd54f2SDevin Teske#
87*9ecd54f2SDevin Teske: ${GEOM_SELF_SCAN_ALL=1}
88*9ecd54f2SDevin Teske
89*9ecd54f2SDevin Teske############################################################ FUNCTIONS
90*9ecd54f2SDevin Teske
91*9ecd54f2SDevin Teske# f_geom_get_all
92*9ecd54f2SDevin Teske#
93*9ecd54f2SDevin Teske# Parse sysctl(8) `kern.geom.confxml' data into a series of structs. GEOM
94*9ecd54f2SDevin Teske# classes are at the top of the heirarchy and are stored as numbered structs
95*9ecd54f2SDevin Teske# from 1 to $NGEOM_CLASSES (set by this function) named `geom_class_C'. GEOM
96*9ecd54f2SDevin Teske# objects within each class are stored as numbered structs from 1 to `ngeoms'
97*9ecd54f2SDevin Teske# (a property of the GEOM class struct) named `geom_class_C_geom_N' (where C
98*9ecd54f2SDevin Teske# is the class number and N is the geom number).
99*9ecd54f2SDevin Teske#
100*9ecd54f2SDevin Teske# Use the function f_geom_find() to get a list of geoms (execute without
101*9ecd54f2SDevin Teske# arguments) or find specific geoms by class or name.
102*9ecd54f2SDevin Teske#
103*9ecd54f2SDevin Teskef_geom_get_all()
104*9ecd54f2SDevin Teske{
105*9ecd54f2SDevin Teske	eval "$( sysctl -n kern.geom.confxml | awk '
106*9ecd54f2SDevin Teske	BEGIN {
107*9ecd54f2SDevin Teske		struct_count["class"] = 0
108*9ecd54f2SDevin Teske		struct_count["geom"] = 0
109*9ecd54f2SDevin Teske		struct_count["consumer"] = 0
110*9ecd54f2SDevin Teske		struct_count["provider"] = 0
111*9ecd54f2SDevin Teske	}
112*9ecd54f2SDevin Teske	############################################### FUNCTIONS
113*9ecd54f2SDevin Teske	function set_value(prop, value)
114*9ecd54f2SDevin Teske	{
115*9ecd54f2SDevin Teske		if (!struct_stack[cur_struct]) return
116*9ecd54f2SDevin Teske		printf "%s set %s \"%s\"\n",
117*9ecd54f2SDevin Teske			struct_stack[cur_struct], prop, value
118*9ecd54f2SDevin Teske	}
119*9ecd54f2SDevin Teske	function create(type, id)
120*9ecd54f2SDevin Teske	{
121*9ecd54f2SDevin Teske		if (struct = created[type "_" id])
122*9ecd54f2SDevin Teske			print "f_struct_free", struct
123*9ecd54f2SDevin Teske		else {
124*9ecd54f2SDevin Teske			struct = struct_stack[cur_struct]
125*9ecd54f2SDevin Teske			struct = struct ( struct ? "" : "geom" )
126*9ecd54f2SDevin Teske			struct = struct "_" type "_" ++struct_count[type]
127*9ecd54f2SDevin Teske			created[type "_" id] = struct
128*9ecd54f2SDevin Teske		}
129*9ecd54f2SDevin Teske		print "debug= f_struct_new GEOM_" toupper(type), struct
130*9ecd54f2SDevin Teske		cur_struct++
131*9ecd54f2SDevin Teske		struct_stack[cur_struct] = struct
132*9ecd54f2SDevin Teske		type_stack[cur_struct] = type
133*9ecd54f2SDevin Teske		set_value("id", id)
134*9ecd54f2SDevin Teske	}
135*9ecd54f2SDevin Teske	function create_config()
136*9ecd54f2SDevin Teske	{
137*9ecd54f2SDevin Teske		struct = struct_stack[cur_struct]
138*9ecd54f2SDevin Teske		struct = struct ( struct ? "" : "geom" )
139*9ecd54f2SDevin Teske		struct = struct "_config"
140*9ecd54f2SDevin Teske		set_value("config", struct)
141*9ecd54f2SDevin Teske		type = type_stack[cur_struct]
142*9ecd54f2SDevin Teske		print "debug= f_struct_new GEOM_" toupper(type) "_CONFIG", \
143*9ecd54f2SDevin Teske		      struct
144*9ecd54f2SDevin Teske		cur_struct++
145*9ecd54f2SDevin Teske		struct_stack[cur_struct] = struct
146*9ecd54f2SDevin Teske		type_stack[cur_struct] = type "_config"
147*9ecd54f2SDevin Teske	}
148*9ecd54f2SDevin Teske	function extract_attr(field, attr)
149*9ecd54f2SDevin Teske	{
150*9ecd54f2SDevin Teske		if (match(field, attr "=\"0x[[:xdigit:]]+\"")) {
151*9ecd54f2SDevin Teske			len = length(attr)
152*9ecd54f2SDevin Teske			return substr($2, len + 3, RLENGTH - len - 3)
153*9ecd54f2SDevin Teske		}
154*9ecd54f2SDevin Teske	}
155*9ecd54f2SDevin Teske	function extract_data(type)
156*9ecd54f2SDevin Teske	{
157*9ecd54f2SDevin Teske		data = $0
158*9ecd54f2SDevin Teske		sub("^[[:space:]]*<" type ">", "", data)
159*9ecd54f2SDevin Teske		sub("</" type ">.*$", "", data)
160*9ecd54f2SDevin Teske		return data
161*9ecd54f2SDevin Teske	}
162*9ecd54f2SDevin Teske	############################################### OPENING PATTERNS
163*9ecd54f2SDevin Teske	$1 == "<mesh>" { mesh = 1 }
164*9ecd54f2SDevin Teske	$1 ~ /^<(class|geom)$/ && mesh {
165*9ecd54f2SDevin Teske		prop = substr($1, 2)
166*9ecd54f2SDevin Teske		if ((ref = extract_attr($2, "ref")) != "")
167*9ecd54f2SDevin Teske			set_value(prop "_ref", ref)
168*9ecd54f2SDevin Teske		else if ((id = extract_attr($2, "id")) != "")
169*9ecd54f2SDevin Teske			create(prop, id)
170*9ecd54f2SDevin Teske	}
171*9ecd54f2SDevin Teske	$1 ~ /^<(consumer|provider)$/ && mesh {
172*9ecd54f2SDevin Teske		prop = substr($1, 2)
173*9ecd54f2SDevin Teske		if ((ref = extract_attr($2, "ref")) != "")
174*9ecd54f2SDevin Teske			set_value(prop "_ref", ref)
175*9ecd54f2SDevin Teske		else if ((id = extract_attr($2, "id")) != "") {
176*9ecd54f2SDevin Teske			create(prop, id)
177*9ecd54f2SDevin Teske			cur_struct--
178*9ecd54f2SDevin Teske			propn = struct_count[prop]
179*9ecd54f2SDevin Teske			set_value(prop propn, struct_stack[cur_struct+1])
180*9ecd54f2SDevin Teske			cur_struct++
181*9ecd54f2SDevin Teske		}
182*9ecd54f2SDevin Teske	}
183*9ecd54f2SDevin Teske	$1 == "<config>" && mesh { create_config() }
184*9ecd54f2SDevin Teske	############################################### PROPERTIES
185*9ecd54f2SDevin Teske	$1 ~ /^<[[:alnum:]]+>/ {
186*9ecd54f2SDevin Teske		prop = $1
187*9ecd54f2SDevin Teske		sub(/^</, "", prop); sub(/>.*/, "", prop)
188*9ecd54f2SDevin Teske		set_value(prop, extract_data(prop))
189*9ecd54f2SDevin Teske	}
190*9ecd54f2SDevin Teske	############################################### CLOSING PATTERNS
191*9ecd54f2SDevin Teske	$1 ~ "^</(consumer|provider|config)>$" { cur_struct-- }
192*9ecd54f2SDevin Teske	$1 == "</geom>" {
193*9ecd54f2SDevin Teske		set_value("nconsumers", struct_count["consumer"])
194*9ecd54f2SDevin Teske		set_value("nproviders", struct_count["provider"])
195*9ecd54f2SDevin Teske		cur_struct--
196*9ecd54f2SDevin Teske		struct_count["consumer"] = 0
197*9ecd54f2SDevin Teske		struct_count["provider"] = 0
198*9ecd54f2SDevin Teske	}
199*9ecd54f2SDevin Teske	$1 == "</class>" {
200*9ecd54f2SDevin Teske		set_value("ngeoms", struct_count["geom"])
201*9ecd54f2SDevin Teske		cur_struct--
202*9ecd54f2SDevin Teske		struct_count["consumer"] = 0
203*9ecd54f2SDevin Teske		struct_count["provider"] = 0
204*9ecd54f2SDevin Teske		struct_count["geom"] = 0
205*9ecd54f2SDevin Teske	}
206*9ecd54f2SDevin Teske	$1 == "</mesh>" {
207*9ecd54f2SDevin Teske		printf "NGEOM_CLASSES=%u\n", struct_count["class"]
208*9ecd54f2SDevin Teske		delete struct_count
209*9ecd54f2SDevin Teske		mesh = 0
210*9ecd54f2SDevin Teske	}' )"
211*9ecd54f2SDevin Teske}
212*9ecd54f2SDevin Teske
213*9ecd54f2SDevin Teske# f_geom_reset
214*9ecd54f2SDevin Teske#
215*9ecd54f2SDevin Teske# Reset the registered GEOM chain.
216*9ecd54f2SDevin Teske#
217*9ecd54f2SDevin Teskef_geom_reset()
218*9ecd54f2SDevin Teske{
219*9ecd54f2SDevin Teske	local classn=1 class ngeoms geomn geom
220*9ecd54f2SDevin Teske	while [ $classn -le ${NGEOM_CLASSES:-0} ]; do
221*9ecd54f2SDevin Teske		class=geom_class_$classn
222*9ecd54f2SDevin Teske		$class get ngeoms ngeoms
223*9ecd54f2SDevin Teske		geomn=1
224*9ecd54f2SDevin Teske		while [ $geomn -le $ngeoms ]; do
225*9ecd54f2SDevin Teske			f_struct_free ${class}_geom_$geomn
226*9ecd54f2SDevin Teske			geomn=$(( $geomn + 1 ))
227*9ecd54f2SDevin Teske		done
228*9ecd54f2SDevin Teske		classn=$(( $classn + 1 ))
229*9ecd54f2SDevin Teske	done
230*9ecd54f2SDevin Teske	NGEOM_CLASSES=0
231*9ecd54f2SDevin Teske}
232*9ecd54f2SDevin Teske
233*9ecd54f2SDevin Teske# f_geom_rescan
234*9ecd54f2SDevin Teske#
235*9ecd54f2SDevin Teske# Rescan all GEOMs - convenience function.
236*9ecd54f2SDevin Teske#
237*9ecd54f2SDevin Teskef_geom_rescan()
238*9ecd54f2SDevin Teske{
239*9ecd54f2SDevin Teske	f_geom_reset
240*9ecd54f2SDevin Teske	f_geom_get_all
241*9ecd54f2SDevin Teske}
242*9ecd54f2SDevin Teske
243*9ecd54f2SDevin Teske# f_geom_find $name [$type [$var_to_set]]
244*9ecd54f2SDevin Teske#
245*9ecd54f2SDevin Teske# Find one or more registered GEOMs by name, type, or both. Returns a space-
246*9ecd54f2SDevin Teske# separated list of GEOMs matching the search criterion. The $type argument
247*9ecd54f2SDevin Teske# should be the GEOM class (see $GEOM_CLASS_* variables in GLOBALS above).
248*9ecd54f2SDevin Teske#
249*9ecd54f2SDevin Teske# If $var_to_set is missing or NULL, the GEOM name(s) are printed to standard
250*9ecd54f2SDevin Teske# out for capturing in a sub-shell (which is less-recommended because of
251*9ecd54f2SDevin Teske# performance degredation; for example, when called in a loop).
252*9ecd54f2SDevin Teske#
253*9ecd54f2SDevin Teskef_geom_find()
254*9ecd54f2SDevin Teske{
255*9ecd54f2SDevin Teske	local __name="$1" __type="${2:-$GEOM_CLASS_ANY}" __var_to_set="$3"
256*9ecd54f2SDevin Teske	local __classn=1 __class __class_name __ngeoms
257*9ecd54f2SDevin Teske	local __geomn __geom __geom_name __found=
258*9ecd54f2SDevin Teske	while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do
259*9ecd54f2SDevin Teske		__class=geom_class_$__classn
260*9ecd54f2SDevin Teske		$__class get name __class_name
261*9ecd54f2SDevin Teske		if [ "$__type" != "$GEOM_CLASS_ANY" -a \
262*9ecd54f2SDevin Teske		     "$__type" != "$__class_name" ]
263*9ecd54f2SDevin Teske		then
264*9ecd54f2SDevin Teske			__classn=$(( $__classn + 1 ))
265*9ecd54f2SDevin Teske			continue
266*9ecd54f2SDevin Teske		fi
267*9ecd54f2SDevin Teske
268*9ecd54f2SDevin Teske		__geomn=1
269*9ecd54f2SDevin Teske		$__class get ngeoms __ngeoms || __ngeoms=0
270*9ecd54f2SDevin Teske		while [ $__geomn -le $__ngeoms ]; do
271*9ecd54f2SDevin Teske			__geom=${__class}_geom_$__geomn
272*9ecd54f2SDevin Teske			$__geom get name __geom_name
273*9ecd54f2SDevin Teske			[ "$__name" = "$__geom_name" -o ! "$__name" ] &&
274*9ecd54f2SDevin Teske				__found="$__found $__geom"
275*9ecd54f2SDevin Teske			__geomn=$(( $__geomn + 1 ))
276*9ecd54f2SDevin Teske		done
277*9ecd54f2SDevin Teske		__classn=$(( $__classn + 1 ))
278*9ecd54f2SDevin Teske	done
279*9ecd54f2SDevin Teske	if [ "$__var_to_set" ]; then
280*9ecd54f2SDevin Teske		setvar "$__var_to_set" "${__found# }"
281*9ecd54f2SDevin Teske	else
282*9ecd54f2SDevin Teske		echo $__found
283*9ecd54f2SDevin Teske	fi
284*9ecd54f2SDevin Teske	[ "$__found" ] # Return status
285*9ecd54f2SDevin Teske}
286*9ecd54f2SDevin Teske
287*9ecd54f2SDevin Teske# f_geom_find_by $prop $find [$type [$var_to_set]]
288*9ecd54f2SDevin Teske#
289*9ecd54f2SDevin Teske# Find GEOM-related struct where $prop of the struct is equal to $find. Returns
290*9ecd54f2SDevin Teske# NULL or the name of the first GEOM struct to match. The $type argument should
291*9ecd54f2SDevin Teske# be one of the following:
292*9ecd54f2SDevin Teske#
293*9ecd54f2SDevin Teske# 	NULL		Find any of the below
294*9ecd54f2SDevin Teske# 	class		Find GEOM_CLASS struct
295*9ecd54f2SDevin Teske# 	geom		Find GEOM_GEOM struct
296*9ecd54f2SDevin Teske# 	consumer	Find GEOM_CONSUMER struct
297*9ecd54f2SDevin Teske# 	provider	Find GEOM_PROVIDER struct
298*9ecd54f2SDevin Teske#
299*9ecd54f2SDevin Teske# The $prop argument can be any property of the given type of struct. Some
300*9ecd54f2SDevin Teske# properties are common to all types (such as id) so the $type argument is
301*9ecd54f2SDevin Teske# optional (allowing you to return any struct whose property matches $find).
302*9ecd54f2SDevin Teske#
303*9ecd54f2SDevin Teske# If $var_to_set is missing or NULL, the GEOM struct name is printed to
304*9ecd54f2SDevin Teske# standard out for capturing in a sub-shell (which is less-recommended because
305*9ecd54f2SDevin Teske# of performance degredation; for example when called in a loop).
306*9ecd54f2SDevin Teske#
307*9ecd54f2SDevin Teskef_geom_find_by()
308*9ecd54f2SDevin Teske{
309*9ecd54f2SDevin Teske	local __prop="$1" __find="$2" __type="$3" __var_to_set="$4"
310*9ecd54f2SDevin Teske	local __classn=1 __class __ngeoms
311*9ecd54f2SDevin Teske	local __geomn __geom __nitems
312*9ecd54f2SDevin Teske	local __itype __itemn __item
313*9ecd54f2SDevin Teske	local __value __found=
314*9ecd54f2SDevin Teske
315*9ecd54f2SDevin Teske	if [ ! "$__prop" ]; then
316*9ecd54f2SDevin Teske		[ "$__var_to_set" ] && setvar "$__var_to_set" ""
317*9ecd54f2SDevin Teske		return $FAILURE
318*9ecd54f2SDevin Teske	fi
319*9ecd54f2SDevin Teske
320*9ecd54f2SDevin Teske	case "$__type" in
321*9ecd54f2SDevin Teske	"") : OK ;;
322*9ecd54f2SDevin Teske	class|GEOM_CLASS) __type=class ;;
323*9ecd54f2SDevin Teske	geom|GEOM_GEOM) __type=geom ;;
324*9ecd54f2SDevin Teske	consumer|GEOM_CONSUMER) __type=consumer ;;
325*9ecd54f2SDevin Teske	provider|GEOM_PROVIDER) __type=provider ;;
326*9ecd54f2SDevin Teske	*)
327*9ecd54f2SDevin Teske		[ "$__var_to_set" ] && setvar "$__var_to_set" ""
328*9ecd54f2SDevin Teske		return $FAILURE
329*9ecd54f2SDevin Teske	esac
330*9ecd54f2SDevin Teske
331*9ecd54f2SDevin Teske	while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do
332*9ecd54f2SDevin Teske		__class=geom_class_$__classn
333*9ecd54f2SDevin Teske
334*9ecd54f2SDevin Teske		if [ "${__type:-class}" = "class" ]; then
335*9ecd54f2SDevin Teske			$__class get "$__prop" __value || __value=
336*9ecd54f2SDevin Teske			[ "$__value" = "$__find" ] && __found="$__class" break
337*9ecd54f2SDevin Teske			[ "$__type" ] && __classn=$(( $__classn + 1 )) continue
338*9ecd54f2SDevin Teske		fi
339*9ecd54f2SDevin Teske
340*9ecd54f2SDevin Teske		__geomn=1
341*9ecd54f2SDevin Teske		$__class get ngeoms __ngeoms || __ngeoms=0
342*9ecd54f2SDevin Teske		while [ $__geomn -le $__ngeoms ]; do
343*9ecd54f2SDevin Teske			__geom=${__class}_geom_$__geomn
344*9ecd54f2SDevin Teske
345*9ecd54f2SDevin Teske			if [ "${__type:-geom}" = "geom" ]; then
346*9ecd54f2SDevin Teske				$__geom get "$__prop" __value || __value=
347*9ecd54f2SDevin Teske				[ "$__value" = "$__find" ] &&
348*9ecd54f2SDevin Teske					__found="$__geom" break
349*9ecd54f2SDevin Teske				[ "$__type" ] &&
350*9ecd54f2SDevin Teske					__geomn=$(( $__geomn + 1 )) continue
351*9ecd54f2SDevin Teske			fi
352*9ecd54f2SDevin Teske
353*9ecd54f2SDevin Teske			for __itype in ${__type:-consumer provider}; do
354*9ecd54f2SDevin Teske				$__geom get n${__itype}s __nitems || continue
355*9ecd54f2SDevin Teske				__itemn=1
356*9ecd54f2SDevin Teske				while [ $__itemn -le $__nitems ]; do
357*9ecd54f2SDevin Teske					__item=${__geom}_${__itype}_$__itemn
358*9ecd54f2SDevin Teske
359*9ecd54f2SDevin Teske					$__item get "$__prop" __value ||
360*9ecd54f2SDevin Teske						__value=
361*9ecd54f2SDevin Teske					[ "$__value" = "$__find" ] &&
362*9ecd54f2SDevin Teske						__found="$__item" break
363*9ecd54f2SDevin Teske					__itemn=$(( $__itemn + 1 ))
364*9ecd54f2SDevin Teske				done
365*9ecd54f2SDevin Teske				[ "$__found" ] && break
366*9ecd54f2SDevin Teske			done
367*9ecd54f2SDevin Teske			[ "$__found" ] && break
368*9ecd54f2SDevin Teske			__geomn=$(( $__geomn + 1 ))
369*9ecd54f2SDevin Teske		done
370*9ecd54f2SDevin Teske		[ "$__found" ] && break
371*9ecd54f2SDevin Teske		__classn=$(( $__classn + 1 ))
372*9ecd54f2SDevin Teske	done
373*9ecd54f2SDevin Teske	if [ "$__var_to_set" ]; then
374*9ecd54f2SDevin Teske		setvar "$__var_to_set" "$__found"
375*9ecd54f2SDevin Teske	else
376*9ecd54f2SDevin Teske		[ "$__found" ] && echo "$__found"
377*9ecd54f2SDevin Teske	fi
378*9ecd54f2SDevin Teske	[ "$__found" ] # Return status
379*9ecd54f2SDevin Teske}
380*9ecd54f2SDevin Teske
381*9ecd54f2SDevin Teske# f_geom_parent $geom|$consumer|$provider|$config [$var_to_set]
382*9ecd54f2SDevin Teske#
383*9ecd54f2SDevin Teske# Get the GEOM class associated with one of $geom, $consumer, $provider or
384*9ecd54f2SDevin Teske# $config.
385*9ecd54f2SDevin Teske#
386*9ecd54f2SDevin Teske# If $var_to_set is missing or NULL, the GEOM class name is printed to standard
387*9ecd54f2SDevin Teske# out for capturing in a sub-shell (which is less-recommended because of
388*9ecd54f2SDevin Teske# performance degredation; for example when called in a loop).
389*9ecd54f2SDevin Teske#
390*9ecd54f2SDevin Teskef_geom_parent()
391*9ecd54f2SDevin Teske{
392*9ecd54f2SDevin Teske	local __struct="$1" __var_to_set="$2"
393*9ecd54f2SDevin Teske	# NB: Order of pattern matches below is important
394*9ecd54f2SDevin Teske	case "$__struct" in
395*9ecd54f2SDevin Teske	*_config*) __struct="${__struct%_config*}" ;;
396*9ecd54f2SDevin Teske	*_consumer_*) __struct="${__struct%_consumer_[0-9]*}" ;;
397*9ecd54f2SDevin Teske	*_provider_*) __struct="${__struct%_provider_[0-9]*}" ;;
398*9ecd54f2SDevin Teske	*_geom_*) __struct="${__struct%_geom_[0-9]*}" ;;
399*9ecd54f2SDevin Teske	*) __struct=
400*9ecd54f2SDevin Teske	esac
401*9ecd54f2SDevin Teske	if [ "$__var_to_set" ]; then
402*9ecd54f2SDevin Teske		setvar "$__var_to_set" "$__struct"
403*9ecd54f2SDevin Teske	else
404*9ecd54f2SDevin Teske		echo "$__struct"
405*9ecd54f2SDevin Teske	fi
406*9ecd54f2SDevin Teske	f_struct "$__struct" # Return status
407*9ecd54f2SDevin Teske}
408*9ecd54f2SDevin Teske
409*9ecd54f2SDevin Teske############################################################ MAIN
410*9ecd54f2SDevin Teske
411*9ecd54f2SDevin Teske#
412*9ecd54f2SDevin Teske# Parse GEOM configuration unless requeted otherwise
413*9ecd54f2SDevin Teske#
414*9ecd54f2SDevin Teskef_dprintf "%s: GEOM_SELF_SCAN_ALL=[%s]" geom.subr "$GEOM_SELF_SCAN_ALL"
415*9ecd54f2SDevin Teskecase "$GEOM_SELF_SCAN_ALL" in
416*9ecd54f2SDevin Teske""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
417*9ecd54f2SDevin Teske*)
418*9ecd54f2SDevin Teske	f_geom_get_all
419*9ecd54f2SDevin Teske	if [ "$debug" ]; then
420*9ecd54f2SDevin Teske		debug= f_geom_find "" "$GEOM_CLASS_ANY" geoms
421*9ecd54f2SDevin Teske		f_count ngeoms $geoms
422*9ecd54f2SDevin Teske		f_dprintf "%s: Initialized %u geom devices in %u classes." \
423*9ecd54f2SDevin Teske		          geom.subr "$ngeoms" "$NGEOM_CLASSES"
424*9ecd54f2SDevin Teske		unset geoms ngeoms
425*9ecd54f2SDevin Teske	fi
426*9ecd54f2SDevin Teskeesac
427*9ecd54f2SDevin Teske
428*9ecd54f2SDevin Teskef_dprintf "%s: Successfully loaded." geom.subr
429*9ecd54f2SDevin Teske
430*9ecd54f2SDevin Teskefi # ! $_GEOM_SUBR
431