xref: /freebsd/usr.sbin/bsdconfig/share/geom.subr (revision 8f9bc4e2ba452040d80851f6ee35efd5dbcbce82)
19ecd54f2SDevin Teskeif [ ! "$_GEOM_SUBR" ]; then _GEOM_SUBR=1
29ecd54f2SDevin Teske#
39ecd54f2SDevin Teske# Copyright (c) 2012-2014 Devin Teske
49ecd54f2SDevin Teske# All rights reserved.
59ecd54f2SDevin Teske#
69ecd54f2SDevin Teske# Redistribution and use in source and binary forms, with or without
79ecd54f2SDevin Teske# modification, are permitted provided that the following conditions
89ecd54f2SDevin Teske# are met:
99ecd54f2SDevin Teske# 1. Redistributions of source code must retain the above copyright
109ecd54f2SDevin Teske#    notice, this list of conditions and the following disclaimer.
119ecd54f2SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright
129ecd54f2SDevin Teske#    notice, this list of conditions and the following disclaimer in the
139ecd54f2SDevin Teske#    documentation and/or other materials provided with the distribution.
149ecd54f2SDevin Teske#
159ecd54f2SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
169ecd54f2SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
179ecd54f2SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
189ecd54f2SDevin Teske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
199ecd54f2SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
209ecd54f2SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
219ecd54f2SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
229ecd54f2SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
239ecd54f2SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
249ecd54f2SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
259ecd54f2SDevin Teske# SUCH DAMAGE.
269ecd54f2SDevin Teske#
279ecd54f2SDevin Teske# $FreeBSD$
289ecd54f2SDevin Teske#
299ecd54f2SDevin Teske############################################################ INCLUDES
309ecd54f2SDevin Teske
319ecd54f2SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
329ecd54f2SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
339ecd54f2SDevin Teskef_dprintf "%s: loading includes..." geom.subr
349ecd54f2SDevin Teskef_include $BSDCFG_SHARE/strings.subr
359ecd54f2SDevin Teskef_include $BSDCFG_SHARE/struct.subr
369ecd54f2SDevin Teske
379ecd54f2SDevin Teske############################################################ GLOBALS
389ecd54f2SDevin Teske
399ecd54f2SDevin TeskeNGEOM_CLASSES=0 # Set by f_geom_get_all()/f_geom_reset()
409ecd54f2SDevin Teske
419ecd54f2SDevin Teske#
429ecd54f2SDevin Teske# GEOM classes for use with f_geom_find()
439ecd54f2SDevin Teske#
449ecd54f2SDevin Teske# NB: Since $GEOM_CLASS_ANY is the NULL string, make sure you quote it whenever
459ecd54f2SDevin Teske#     you put arguments after it.
469ecd54f2SDevin Teske#
479ecd54f2SDevin Teskesetvar GEOM_CLASS_ANY		"any"
489ecd54f2SDevin Teskesetvar GEOM_CLASS_DEV		"DEV"
499ecd54f2SDevin Teskesetvar GEOM_CLASS_DISK		"DISK"
509ecd54f2SDevin Teskesetvar GEOM_CLASS_ELI		"ELI"
519ecd54f2SDevin Teskesetvar GEOM_CLASS_FD		"FD"
529ecd54f2SDevin Teskesetvar GEOM_CLASS_LABEL		"LABEL"
539ecd54f2SDevin Teskesetvar GEOM_CLASS_MD		"MD"
549ecd54f2SDevin Teskesetvar GEOM_CLASS_NOP		"NOP"
559ecd54f2SDevin Teskesetvar GEOM_CLASS_PART		"PART"
569ecd54f2SDevin Teskesetvar GEOM_CLASS_RAID		"RAID"
579ecd54f2SDevin Teskesetvar GEOM_CLASS_SWAP		"SWAP"
589ecd54f2SDevin Teskesetvar GEOM_CLASS_VFS		"VFS"
599ecd54f2SDevin Teskesetvar GEOM_CLASS_ZFS_VDEV	"ZFS::VDEV"
609ecd54f2SDevin Teskesetvar GEOM_CLASS_ZFS_ZVOL	"ZFS::ZVOL"
619ecd54f2SDevin Teske
629ecd54f2SDevin Teske#
639ecd54f2SDevin Teske# GEOM structure definitions
649ecd54f2SDevin Teske#
659ecd54f2SDevin Teskef_struct_define GEOM_CLASS \
669ecd54f2SDevin Teske	id name ngeoms
679ecd54f2SDevin Teskef_struct_define GEOM_GEOM \
689ecd54f2SDevin Teske	id class_ref config name nconsumers nproviders rank
699ecd54f2SDevin Teske	# Also consumerN where N is 1 through nconsumers
709ecd54f2SDevin Teske	# Also providerN where N is 1 through nproviders
719ecd54f2SDevin Teskef_struct_define GEOM_CONSUMER \
729ecd54f2SDevin Teske	id geom_ref config mode provider_ref
739ecd54f2SDevin Teskef_struct_define GEOM_PROVIDER \
749ecd54f2SDevin Teske	id geom_ref config mode name mediasize
759ecd54f2SDevin Teske
769ecd54f2SDevin Teske# The config property of GEOM_GEOM struct is defined as this
779ecd54f2SDevin Teskef_struct_define GEOM_GEOM_CONFIG \
789ecd54f2SDevin Teske	entries first fwheads fwsectors last modified scheme state
799ecd54f2SDevin Teske
809ecd54f2SDevin Teske# The config property of GEOM_PROVIDER struct is defined as this
819ecd54f2SDevin Teskef_struct_define GEOM_PROVIDER_CONFIG \
829ecd54f2SDevin Teske	descr file fwheads fwsectors ident length type unit
839ecd54f2SDevin Teske
849ecd54f2SDevin Teske#
859ecd54f2SDevin Teske# Default behavior is to call f_geom_get_all() automatically when loaded.
869ecd54f2SDevin Teske#
879ecd54f2SDevin Teske: ${GEOM_SELF_SCAN_ALL=1}
889ecd54f2SDevin Teske
899ecd54f2SDevin Teske############################################################ FUNCTIONS
909ecd54f2SDevin Teske
919ecd54f2SDevin Teske# f_geom_get_all
929ecd54f2SDevin Teske#
939ecd54f2SDevin Teske# Parse sysctl(8) `kern.geom.confxml' data into a series of structs. GEOM
949ecd54f2SDevin Teske# classes are at the top of the heirarchy and are stored as numbered structs
959ecd54f2SDevin Teske# from 1 to $NGEOM_CLASSES (set by this function) named `geom_class_C'. GEOM
969ecd54f2SDevin Teske# objects within each class are stored as numbered structs from 1 to `ngeoms'
979ecd54f2SDevin Teske# (a property of the GEOM class struct) named `geom_class_C_geom_N' (where C
989ecd54f2SDevin Teske# is the class number and N is the geom number).
999ecd54f2SDevin Teske#
1009ecd54f2SDevin Teske# Use the function f_geom_find() to get a list of geoms (execute without
1019ecd54f2SDevin Teske# arguments) or find specific geoms by class or name.
1029ecd54f2SDevin Teske#
1039ecd54f2SDevin Teskef_geom_get_all()
1049ecd54f2SDevin Teske{
1059ecd54f2SDevin Teske	eval "$( sysctl -n kern.geom.confxml | awk '
1069ecd54f2SDevin Teske	BEGIN {
1079ecd54f2SDevin Teske		struct_count["class"] = 0
1089ecd54f2SDevin Teske		struct_count["geom"] = 0
1099ecd54f2SDevin Teske		struct_count["consumer"] = 0
1109ecd54f2SDevin Teske		struct_count["provider"] = 0
1119ecd54f2SDevin Teske	}
1129ecd54f2SDevin Teske	############################################### FUNCTIONS
1139ecd54f2SDevin Teske	function set_value(prop, value)
1149ecd54f2SDevin Teske	{
1159ecd54f2SDevin Teske		if (!struct_stack[cur_struct]) return
1169ecd54f2SDevin Teske		printf "%s set %s \"%s\"\n",
1179ecd54f2SDevin Teske			struct_stack[cur_struct], prop, value
1189ecd54f2SDevin Teske	}
1199ecd54f2SDevin Teske	function create(type, id)
1209ecd54f2SDevin Teske	{
1219ecd54f2SDevin Teske		if (struct = created[type "_" id])
1229ecd54f2SDevin Teske			print "f_struct_free", struct
1239ecd54f2SDevin Teske		else {
1249ecd54f2SDevin Teske			struct = struct_stack[cur_struct]
1259ecd54f2SDevin Teske			struct = struct ( struct ? "" : "geom" )
1269ecd54f2SDevin Teske			struct = struct "_" type "_" ++struct_count[type]
1279ecd54f2SDevin Teske			created[type "_" id] = struct
1289ecd54f2SDevin Teske		}
1299ecd54f2SDevin Teske		print "debug= f_struct_new GEOM_" toupper(type), struct
1309ecd54f2SDevin Teske		cur_struct++
1319ecd54f2SDevin Teske		struct_stack[cur_struct] = struct
1329ecd54f2SDevin Teske		type_stack[cur_struct] = type
1339ecd54f2SDevin Teske		set_value("id", id)
1349ecd54f2SDevin Teske	}
1359ecd54f2SDevin Teske	function create_config()
1369ecd54f2SDevin Teske	{
1379ecd54f2SDevin Teske		struct = struct_stack[cur_struct]
1389ecd54f2SDevin Teske		struct = struct ( struct ? "" : "geom" )
1399ecd54f2SDevin Teske		struct = struct "_config"
1409ecd54f2SDevin Teske		set_value("config", struct)
1419ecd54f2SDevin Teske		type = type_stack[cur_struct]
1429ecd54f2SDevin Teske		print "debug= f_struct_new GEOM_" toupper(type) "_CONFIG", \
1439ecd54f2SDevin Teske		      struct
1449ecd54f2SDevin Teske		cur_struct++
1459ecd54f2SDevin Teske		struct_stack[cur_struct] = struct
1469ecd54f2SDevin Teske		type_stack[cur_struct] = type "_config"
1479ecd54f2SDevin Teske	}
1489ecd54f2SDevin Teske	function extract_attr(field, attr)
1499ecd54f2SDevin Teske	{
1509ecd54f2SDevin Teske		if (match(field, attr "=\"0x[[:xdigit:]]+\"")) {
1519ecd54f2SDevin Teske			len = length(attr)
1529ecd54f2SDevin Teske			return substr($2, len + 3, RLENGTH - len - 3)
1539ecd54f2SDevin Teske		}
1549ecd54f2SDevin Teske	}
1559ecd54f2SDevin Teske	function extract_data(type)
1569ecd54f2SDevin Teske	{
1579ecd54f2SDevin Teske		data = $0
1589ecd54f2SDevin Teske		sub("^[[:space:]]*<" type ">", "", data)
1599ecd54f2SDevin Teske		sub("</" type ">.*$", "", data)
1609ecd54f2SDevin Teske		return data
1619ecd54f2SDevin Teske	}
1629ecd54f2SDevin Teske	############################################### OPENING PATTERNS
1639ecd54f2SDevin Teske	$1 == "<mesh>" { mesh = 1 }
1649ecd54f2SDevin Teske	$1 ~ /^<(class|geom)$/ && mesh {
1659ecd54f2SDevin Teske		prop = substr($1, 2)
1669ecd54f2SDevin Teske		if ((ref = extract_attr($2, "ref")) != "")
1679ecd54f2SDevin Teske			set_value(prop "_ref", ref)
1689ecd54f2SDevin Teske		else if ((id = extract_attr($2, "id")) != "")
1699ecd54f2SDevin Teske			create(prop, id)
1709ecd54f2SDevin Teske	}
1719ecd54f2SDevin Teske	$1 ~ /^<(consumer|provider)$/ && mesh {
1729ecd54f2SDevin Teske		prop = substr($1, 2)
1739ecd54f2SDevin Teske		if ((ref = extract_attr($2, "ref")) != "")
1749ecd54f2SDevin Teske			set_value(prop "_ref", ref)
1759ecd54f2SDevin Teske		else if ((id = extract_attr($2, "id")) != "") {
1769ecd54f2SDevin Teske			create(prop, id)
1779ecd54f2SDevin Teske			cur_struct--
1789ecd54f2SDevin Teske			propn = struct_count[prop]
1799ecd54f2SDevin Teske			set_value(prop propn, struct_stack[cur_struct+1])
1809ecd54f2SDevin Teske			cur_struct++
1819ecd54f2SDevin Teske		}
1829ecd54f2SDevin Teske	}
1839ecd54f2SDevin Teske	$1 == "<config>" && mesh { create_config() }
1849ecd54f2SDevin Teske	############################################### PROPERTIES
1859ecd54f2SDevin Teske	$1 ~ /^<[[:alnum:]]+>/ {
1869ecd54f2SDevin Teske		prop = $1
1879ecd54f2SDevin Teske		sub(/^</, "", prop); sub(/>.*/, "", prop)
1889ecd54f2SDevin Teske		set_value(prop, extract_data(prop))
1899ecd54f2SDevin Teske	}
1909ecd54f2SDevin Teske	############################################### CLOSING PATTERNS
1919ecd54f2SDevin Teske	$1 ~ "^</(consumer|provider|config)>$" { cur_struct-- }
1929ecd54f2SDevin Teske	$1 == "</geom>" {
1939ecd54f2SDevin Teske		set_value("nconsumers", struct_count["consumer"])
1949ecd54f2SDevin Teske		set_value("nproviders", struct_count["provider"])
1959ecd54f2SDevin Teske		cur_struct--
1969ecd54f2SDevin Teske		struct_count["consumer"] = 0
1979ecd54f2SDevin Teske		struct_count["provider"] = 0
1989ecd54f2SDevin Teske	}
1999ecd54f2SDevin Teske	$1 == "</class>" {
2009ecd54f2SDevin Teske		set_value("ngeoms", struct_count["geom"])
2019ecd54f2SDevin Teske		cur_struct--
2029ecd54f2SDevin Teske		struct_count["consumer"] = 0
2039ecd54f2SDevin Teske		struct_count["provider"] = 0
2049ecd54f2SDevin Teske		struct_count["geom"] = 0
2059ecd54f2SDevin Teske	}
2069ecd54f2SDevin Teske	$1 == "</mesh>" {
2079ecd54f2SDevin Teske		printf "NGEOM_CLASSES=%u\n", struct_count["class"]
2089ecd54f2SDevin Teske		delete struct_count
2099ecd54f2SDevin Teske		mesh = 0
2109ecd54f2SDevin Teske	}' )"
2119ecd54f2SDevin Teske}
2129ecd54f2SDevin Teske
2139ecd54f2SDevin Teske# f_geom_reset
2149ecd54f2SDevin Teske#
2159ecd54f2SDevin Teske# Reset the registered GEOM chain.
2169ecd54f2SDevin Teske#
2179ecd54f2SDevin Teskef_geom_reset()
2189ecd54f2SDevin Teske{
2199ecd54f2SDevin Teske	local classn=1 class ngeoms geomn geom
2209ecd54f2SDevin Teske	while [ $classn -le ${NGEOM_CLASSES:-0} ]; do
2219ecd54f2SDevin Teske		class=geom_class_$classn
2229ecd54f2SDevin Teske		$class get ngeoms ngeoms
2239ecd54f2SDevin Teske		geomn=1
2249ecd54f2SDevin Teske		while [ $geomn -le $ngeoms ]; do
2259ecd54f2SDevin Teske			f_struct_free ${class}_geom_$geomn
2269ecd54f2SDevin Teske			geomn=$(( $geomn + 1 ))
2279ecd54f2SDevin Teske		done
2289ecd54f2SDevin Teske		classn=$(( $classn + 1 ))
2299ecd54f2SDevin Teske	done
2309ecd54f2SDevin Teske	NGEOM_CLASSES=0
2319ecd54f2SDevin Teske}
2329ecd54f2SDevin Teske
2339ecd54f2SDevin Teske# f_geom_rescan
2349ecd54f2SDevin Teske#
2359ecd54f2SDevin Teske# Rescan all GEOMs - convenience function.
2369ecd54f2SDevin Teske#
2379ecd54f2SDevin Teskef_geom_rescan()
2389ecd54f2SDevin Teske{
2399ecd54f2SDevin Teske	f_geom_reset
2409ecd54f2SDevin Teske	f_geom_get_all
2419ecd54f2SDevin Teske}
2429ecd54f2SDevin Teske
2439ecd54f2SDevin Teske# f_geom_find $name [$type [$var_to_set]]
2449ecd54f2SDevin Teske#
2459ecd54f2SDevin Teske# Find one or more registered GEOMs by name, type, or both. Returns a space-
2469ecd54f2SDevin Teske# separated list of GEOMs matching the search criterion. The $type argument
2479ecd54f2SDevin Teske# should be the GEOM class (see $GEOM_CLASS_* variables in GLOBALS above).
2489ecd54f2SDevin Teske#
2499ecd54f2SDevin Teske# If $var_to_set is missing or NULL, the GEOM name(s) are printed to standard
2509ecd54f2SDevin Teske# out for capturing in a sub-shell (which is less-recommended because of
2519ecd54f2SDevin Teske# performance degredation; for example, when called in a loop).
2529ecd54f2SDevin Teske#
2539ecd54f2SDevin Teskef_geom_find()
2549ecd54f2SDevin Teske{
2559ecd54f2SDevin Teske	local __name="$1" __type="${2:-$GEOM_CLASS_ANY}" __var_to_set="$3"
2569ecd54f2SDevin Teske	local __classn=1 __class __class_name __ngeoms
2579ecd54f2SDevin Teske	local __geomn __geom __geom_name __found=
2589ecd54f2SDevin Teske	while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do
2599ecd54f2SDevin Teske		__class=geom_class_$__classn
2609ecd54f2SDevin Teske		$__class get name __class_name
2619ecd54f2SDevin Teske		if [ "$__type" != "$GEOM_CLASS_ANY" -a \
2629ecd54f2SDevin Teske		     "$__type" != "$__class_name" ]
2639ecd54f2SDevin Teske		then
2649ecd54f2SDevin Teske			__classn=$(( $__classn + 1 ))
2659ecd54f2SDevin Teske			continue
2669ecd54f2SDevin Teske		fi
2679ecd54f2SDevin Teske
2689ecd54f2SDevin Teske		__geomn=1
2699ecd54f2SDevin Teske		$__class get ngeoms __ngeoms || __ngeoms=0
2709ecd54f2SDevin Teske		while [ $__geomn -le $__ngeoms ]; do
2719ecd54f2SDevin Teske			__geom=${__class}_geom_$__geomn
2729ecd54f2SDevin Teske			$__geom get name __geom_name
2739ecd54f2SDevin Teske			[ "$__name" = "$__geom_name" -o ! "$__name" ] &&
2749ecd54f2SDevin Teske				__found="$__found $__geom"
2759ecd54f2SDevin Teske			__geomn=$(( $__geomn + 1 ))
2769ecd54f2SDevin Teske		done
2779ecd54f2SDevin Teske		__classn=$(( $__classn + 1 ))
2789ecd54f2SDevin Teske	done
2799ecd54f2SDevin Teske	if [ "$__var_to_set" ]; then
2809ecd54f2SDevin Teske		setvar "$__var_to_set" "${__found# }"
2819ecd54f2SDevin Teske	else
2829ecd54f2SDevin Teske		echo $__found
2839ecd54f2SDevin Teske	fi
2849ecd54f2SDevin Teske	[ "$__found" ] # Return status
2859ecd54f2SDevin Teske}
2869ecd54f2SDevin Teske
2879ecd54f2SDevin Teske# f_geom_find_by $prop $find [$type [$var_to_set]]
2889ecd54f2SDevin Teske#
2899ecd54f2SDevin Teske# Find GEOM-related struct where $prop of the struct is equal to $find. Returns
2909ecd54f2SDevin Teske# NULL or the name of the first GEOM struct to match. The $type argument should
2919ecd54f2SDevin Teske# be one of the following:
2929ecd54f2SDevin Teske#
2939ecd54f2SDevin Teske# 	NULL		Find any of the below
2949ecd54f2SDevin Teske# 	class		Find GEOM_CLASS struct
2959ecd54f2SDevin Teske# 	geom		Find GEOM_GEOM struct
2969ecd54f2SDevin Teske# 	consumer	Find GEOM_CONSUMER struct
2979ecd54f2SDevin Teske# 	provider	Find GEOM_PROVIDER struct
2989ecd54f2SDevin Teske#
2999ecd54f2SDevin Teske# The $prop argument can be any property of the given type of struct. Some
3009ecd54f2SDevin Teske# properties are common to all types (such as id) so the $type argument is
3019ecd54f2SDevin Teske# optional (allowing you to return any struct whose property matches $find).
3029ecd54f2SDevin Teske#
3039ecd54f2SDevin Teske# If $var_to_set is missing or NULL, the GEOM struct name is printed to
3049ecd54f2SDevin Teske# standard out for capturing in a sub-shell (which is less-recommended because
3059ecd54f2SDevin Teske# of performance degredation; for example when called in a loop).
3069ecd54f2SDevin Teske#
3079ecd54f2SDevin Teskef_geom_find_by()
3089ecd54f2SDevin Teske{
3099ecd54f2SDevin Teske	local __prop="$1" __find="$2" __type="$3" __var_to_set="$4"
3109ecd54f2SDevin Teske	local __classn=1 __class __ngeoms
3119ecd54f2SDevin Teske	local __geomn __geom __nitems
3129ecd54f2SDevin Teske	local __itype __itemn __item
3139ecd54f2SDevin Teske	local __value __found=
3149ecd54f2SDevin Teske
3159ecd54f2SDevin Teske	if [ ! "$__prop" ]; then
3169ecd54f2SDevin Teske		[ "$__var_to_set" ] && setvar "$__var_to_set" ""
3179ecd54f2SDevin Teske		return $FAILURE
3189ecd54f2SDevin Teske	fi
3199ecd54f2SDevin Teske
3209ecd54f2SDevin Teske	case "$__type" in
3219ecd54f2SDevin Teske	"") : OK ;;
3229ecd54f2SDevin Teske	class|GEOM_CLASS) __type=class ;;
3239ecd54f2SDevin Teske	geom|GEOM_GEOM) __type=geom ;;
3249ecd54f2SDevin Teske	consumer|GEOM_CONSUMER) __type=consumer ;;
3259ecd54f2SDevin Teske	provider|GEOM_PROVIDER) __type=provider ;;
3269ecd54f2SDevin Teske	*)
3279ecd54f2SDevin Teske		[ "$__var_to_set" ] && setvar "$__var_to_set" ""
3289ecd54f2SDevin Teske		return $FAILURE
3299ecd54f2SDevin Teske	esac
3309ecd54f2SDevin Teske
3319ecd54f2SDevin Teske	while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do
3329ecd54f2SDevin Teske		__class=geom_class_$__classn
3339ecd54f2SDevin Teske
3349ecd54f2SDevin Teske		if [ "${__type:-class}" = "class" ]; then
3359ecd54f2SDevin Teske			$__class get "$__prop" __value || __value=
3369ecd54f2SDevin Teske			[ "$__value" = "$__find" ] && __found="$__class" break
3379ecd54f2SDevin Teske			[ "$__type" ] && __classn=$(( $__classn + 1 )) continue
3389ecd54f2SDevin Teske		fi
3399ecd54f2SDevin Teske
3409ecd54f2SDevin Teske		__geomn=1
3419ecd54f2SDevin Teske		$__class get ngeoms __ngeoms || __ngeoms=0
3429ecd54f2SDevin Teske		while [ $__geomn -le $__ngeoms ]; do
3439ecd54f2SDevin Teske			__geom=${__class}_geom_$__geomn
3449ecd54f2SDevin Teske
3459ecd54f2SDevin Teske			if [ "${__type:-geom}" = "geom" ]; then
3469ecd54f2SDevin Teske				$__geom get "$__prop" __value || __value=
3479ecd54f2SDevin Teske				[ "$__value" = "$__find" ] &&
3489ecd54f2SDevin Teske					__found="$__geom" break
3499ecd54f2SDevin Teske				[ "$__type" ] &&
3509ecd54f2SDevin Teske					__geomn=$(( $__geomn + 1 )) continue
3519ecd54f2SDevin Teske			fi
3529ecd54f2SDevin Teske
3539ecd54f2SDevin Teske			for __itype in ${__type:-consumer provider}; do
3549ecd54f2SDevin Teske				$__geom get n${__itype}s __nitems || continue
3559ecd54f2SDevin Teske				__itemn=1
3569ecd54f2SDevin Teske				while [ $__itemn -le $__nitems ]; do
3579ecd54f2SDevin Teske					__item=${__geom}_${__itype}_$__itemn
3589ecd54f2SDevin Teske
3599ecd54f2SDevin Teske					$__item get "$__prop" __value ||
3609ecd54f2SDevin Teske						__value=
3619ecd54f2SDevin Teske					[ "$__value" = "$__find" ] &&
3629ecd54f2SDevin Teske						__found="$__item" break
3639ecd54f2SDevin Teske					__itemn=$(( $__itemn + 1 ))
3649ecd54f2SDevin Teske				done
3659ecd54f2SDevin Teske				[ "$__found" ] && break
3669ecd54f2SDevin Teske			done
3679ecd54f2SDevin Teske			[ "$__found" ] && break
3689ecd54f2SDevin Teske			__geomn=$(( $__geomn + 1 ))
3699ecd54f2SDevin Teske		done
3709ecd54f2SDevin Teske		[ "$__found" ] && break
3719ecd54f2SDevin Teske		__classn=$(( $__classn + 1 ))
3729ecd54f2SDevin Teske	done
3739ecd54f2SDevin Teske	if [ "$__var_to_set" ]; then
3749ecd54f2SDevin Teske		setvar "$__var_to_set" "$__found"
3759ecd54f2SDevin Teske	else
3769ecd54f2SDevin Teske		[ "$__found" ] && echo "$__found"
3779ecd54f2SDevin Teske	fi
3789ecd54f2SDevin Teske	[ "$__found" ] # Return status
3799ecd54f2SDevin Teske}
3809ecd54f2SDevin Teske
3819ecd54f2SDevin Teske# f_geom_parent $geom|$consumer|$provider|$config [$var_to_set]
3829ecd54f2SDevin Teske#
3839ecd54f2SDevin Teske# Get the GEOM class associated with one of $geom, $consumer, $provider or
3849ecd54f2SDevin Teske# $config.
3859ecd54f2SDevin Teske#
3869ecd54f2SDevin Teske# If $var_to_set is missing or NULL, the GEOM class name is printed to standard
3879ecd54f2SDevin Teske# out for capturing in a sub-shell (which is less-recommended because of
3889ecd54f2SDevin Teske# performance degredation; for example when called in a loop).
3899ecd54f2SDevin Teske#
3909ecd54f2SDevin Teskef_geom_parent()
3919ecd54f2SDevin Teske{
3929ecd54f2SDevin Teske	local __struct="$1" __var_to_set="$2"
3939ecd54f2SDevin Teske	# NB: Order of pattern matches below is important
3949ecd54f2SDevin Teske	case "$__struct" in
3959ecd54f2SDevin Teske	*_config*) __struct="${__struct%_config*}" ;;
3969ecd54f2SDevin Teske	*_consumer_*) __struct="${__struct%_consumer_[0-9]*}" ;;
3979ecd54f2SDevin Teske	*_provider_*) __struct="${__struct%_provider_[0-9]*}" ;;
3989ecd54f2SDevin Teske	*_geom_*) __struct="${__struct%_geom_[0-9]*}" ;;
3999ecd54f2SDevin Teske	*) __struct=
4009ecd54f2SDevin Teske	esac
4019ecd54f2SDevin Teske	if [ "$__var_to_set" ]; then
4029ecd54f2SDevin Teske		setvar "$__var_to_set" "$__struct"
4039ecd54f2SDevin Teske	else
4049ecd54f2SDevin Teske		echo "$__struct"
4059ecd54f2SDevin Teske	fi
4069ecd54f2SDevin Teske	f_struct "$__struct" # Return status
4079ecd54f2SDevin Teske}
4089ecd54f2SDevin Teske
4099ecd54f2SDevin Teske############################################################ MAIN
4109ecd54f2SDevin Teske
4119ecd54f2SDevin Teske#
412*8f9bc4e2SDevin Teske# Parse GEOM configuration unless requested otherwise
4139ecd54f2SDevin Teske#
4149ecd54f2SDevin Teskef_dprintf "%s: GEOM_SELF_SCAN_ALL=[%s]" geom.subr "$GEOM_SELF_SCAN_ALL"
4159ecd54f2SDevin Teskecase "$GEOM_SELF_SCAN_ALL" in
4169ecd54f2SDevin Teske""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
4179ecd54f2SDevin Teske*)
4189ecd54f2SDevin Teske	f_geom_get_all
4199ecd54f2SDevin Teske	if [ "$debug" ]; then
4209ecd54f2SDevin Teske		debug= f_geom_find "" "$GEOM_CLASS_ANY" geoms
4219ecd54f2SDevin Teske		f_count ngeoms $geoms
4229ecd54f2SDevin Teske		f_dprintf "%s: Initialized %u geom devices in %u classes." \
4239ecd54f2SDevin Teske		          geom.subr "$ngeoms" "$NGEOM_CLASSES"
4249ecd54f2SDevin Teske		unset geoms ngeoms
4259ecd54f2SDevin Teske	fi
4269ecd54f2SDevin Teskeesac
4279ecd54f2SDevin Teske
4289ecd54f2SDevin Teskef_dprintf "%s: Successfully loaded." geom.subr
4299ecd54f2SDevin Teske
4309ecd54f2SDevin Teskefi # ! $_GEOM_SUBR
431