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