geom.subr revision 298884
1264840Sdteskeif [ ! "$_GEOM_SUBR" ]; then _GEOM_SUBR=1 2264840Sdteske# 3264840Sdteske# Copyright (c) 2012-2014 Devin Teske 4264840Sdteske# All rights reserved. 5264840Sdteske# 6264840Sdteske# Redistribution and use in source and binary forms, with or without 7264840Sdteske# modification, are permitted provided that the following conditions 8264840Sdteske# are met: 9264840Sdteske# 1. Redistributions of source code must retain the above copyright 10264840Sdteske# notice, this list of conditions and the following disclaimer. 11264840Sdteske# 2. Redistributions in binary form must reproduce the above copyright 12264840Sdteske# notice, this list of conditions and the following disclaimer in the 13264840Sdteske# documentation and/or other materials provided with the distribution. 14264840Sdteske# 15264840Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16264840Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17264840Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18264840Sdteske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19264840Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20264840Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21264840Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22264840Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23264840Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24264840Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25264840Sdteske# SUCH DAMAGE. 26264840Sdteske# 27264840Sdteske# $FreeBSD: head/usr.sbin/bsdconfig/share/geom.subr 298884 2016-05-01 16:38:12Z pfg $ 28264840Sdteske# 29264840Sdteske############################################################ INCLUDES 30264840Sdteske 31264840SdteskeBSDCFG_SHARE="/usr/share/bsdconfig" 32264840Sdteske. $BSDCFG_SHARE/common.subr || exit 1 33264840Sdteskef_dprintf "%s: loading includes..." geom.subr 34264840Sdteskef_include $BSDCFG_SHARE/strings.subr 35264840Sdteskef_include $BSDCFG_SHARE/struct.subr 36264840Sdteske 37264840Sdteske############################################################ GLOBALS 38264840Sdteske 39264840SdteskeNGEOM_CLASSES=0 # Set by f_geom_get_all()/f_geom_reset() 40264840Sdteske 41264840Sdteske# 42264840Sdteske# GEOM classes for use with f_geom_find() 43264840Sdteske# 44264840Sdteske# NB: Since $GEOM_CLASS_ANY is the NULL string, make sure you quote it whenever 45264840Sdteske# you put arguments after it. 46264840Sdteske# 47264840Sdteskesetvar GEOM_CLASS_ANY "any" 48264840Sdteskesetvar GEOM_CLASS_DEV "DEV" 49264840Sdteskesetvar GEOM_CLASS_DISK "DISK" 50264840Sdteskesetvar GEOM_CLASS_ELI "ELI" 51264840Sdteskesetvar GEOM_CLASS_FD "FD" 52264840Sdteskesetvar GEOM_CLASS_LABEL "LABEL" 53264840Sdteskesetvar GEOM_CLASS_MD "MD" 54264840Sdteskesetvar GEOM_CLASS_NOP "NOP" 55264840Sdteskesetvar GEOM_CLASS_PART "PART" 56264840Sdteskesetvar GEOM_CLASS_RAID "RAID" 57264840Sdteskesetvar GEOM_CLASS_SWAP "SWAP" 58264840Sdteskesetvar GEOM_CLASS_VFS "VFS" 59264840Sdteskesetvar GEOM_CLASS_ZFS_VDEV "ZFS::VDEV" 60264840Sdteskesetvar GEOM_CLASS_ZFS_ZVOL "ZFS::ZVOL" 61264840Sdteske 62264840Sdteske# 63264840Sdteske# GEOM structure definitions 64264840Sdteske# 65264840Sdteskef_struct_define GEOM_CLASS \ 66264840Sdteske id name ngeoms 67264840Sdteskef_struct_define GEOM_GEOM \ 68264840Sdteske id class_ref config name nconsumers nproviders rank 69264840Sdteske # Also consumerN where N is 1 through nconsumers 70264840Sdteske # Also providerN where N is 1 through nproviders 71264840Sdteskef_struct_define GEOM_CONSUMER \ 72264840Sdteske id geom_ref config mode provider_ref 73264840Sdteskef_struct_define GEOM_PROVIDER \ 74264840Sdteske id geom_ref config mode name mediasize 75264840Sdteske 76264840Sdteske# The config property of GEOM_GEOM struct is defined as this 77264840Sdteskef_struct_define GEOM_GEOM_CONFIG \ 78264840Sdteske entries first fwheads fwsectors last modified scheme state 79264840Sdteske 80264840Sdteske# The config property of GEOM_PROVIDER struct is defined as this 81264840Sdteskef_struct_define GEOM_PROVIDER_CONFIG \ 82264840Sdteske descr file fwheads fwsectors ident length type unit 83264840Sdteske 84264840Sdteske# 85264840Sdteske# Default behavior is to call f_geom_get_all() automatically when loaded. 86264840Sdteske# 87264840Sdteske: ${GEOM_SELF_SCAN_ALL=1} 88264840Sdteske 89264840Sdteske############################################################ FUNCTIONS 90264840Sdteske 91264840Sdteske# f_geom_get_all 92264840Sdteske# 93264840Sdteske# Parse sysctl(8) `kern.geom.confxml' data into a series of structs. GEOM 94298884Spfg# classes are at the top of the hierarchy and are stored as numbered structs 95264840Sdteske# from 1 to $NGEOM_CLASSES (set by this function) named `geom_class_C'. GEOM 96264840Sdteske# objects within each class are stored as numbered structs from 1 to `ngeoms' 97264840Sdteske# (a property of the GEOM class struct) named `geom_class_C_geom_N' (where C 98264840Sdteske# is the class number and N is the geom number). 99264840Sdteske# 100264840Sdteske# Use the function f_geom_find() to get a list of geoms (execute without 101264840Sdteske# arguments) or find specific geoms by class or name. 102264840Sdteske# 103264840Sdteskef_geom_get_all() 104264840Sdteske{ 105264840Sdteske eval "$( sysctl -n kern.geom.confxml | awk ' 106264840Sdteske BEGIN { 107264840Sdteske struct_count["class"] = 0 108264840Sdteske struct_count["geom"] = 0 109264840Sdteske struct_count["consumer"] = 0 110264840Sdteske struct_count["provider"] = 0 111264840Sdteske } 112264840Sdteske ############################################### FUNCTIONS 113264840Sdteske function set_value(prop, value) 114264840Sdteske { 115264840Sdteske if (!struct_stack[cur_struct]) return 116264840Sdteske printf "%s set %s \"%s\"\n", 117264840Sdteske struct_stack[cur_struct], prop, value 118264840Sdteske } 119264840Sdteske function create(type, id) 120264840Sdteske { 121264840Sdteske if (struct = created[type "_" id]) 122264840Sdteske print "f_struct_free", struct 123264840Sdteske else { 124264840Sdteske struct = struct_stack[cur_struct] 125264840Sdteske struct = struct ( struct ? "" : "geom" ) 126264840Sdteske struct = struct "_" type "_" ++struct_count[type] 127264840Sdteske created[type "_" id] = struct 128264840Sdteske } 129264840Sdteske print "debug= f_struct_new GEOM_" toupper(type), struct 130264840Sdteske cur_struct++ 131264840Sdteske struct_stack[cur_struct] = struct 132264840Sdteske type_stack[cur_struct] = type 133264840Sdteske set_value("id", id) 134264840Sdteske } 135264840Sdteske function create_config() 136264840Sdteske { 137264840Sdteske struct = struct_stack[cur_struct] 138264840Sdteske struct = struct ( struct ? "" : "geom" ) 139264840Sdteske struct = struct "_config" 140264840Sdteske set_value("config", struct) 141264840Sdteske type = type_stack[cur_struct] 142264840Sdteske print "debug= f_struct_new GEOM_" toupper(type) "_CONFIG", \ 143264840Sdteske struct 144264840Sdteske cur_struct++ 145264840Sdteske struct_stack[cur_struct] = struct 146264840Sdteske type_stack[cur_struct] = type "_config" 147264840Sdteske } 148264840Sdteske function extract_attr(field, attr) 149264840Sdteske { 150264840Sdteske if (match(field, attr "=\"0x[[:xdigit:]]+\"")) { 151264840Sdteske len = length(attr) 152264840Sdteske return substr($2, len + 3, RLENGTH - len - 3) 153264840Sdteske } 154264840Sdteske } 155264840Sdteske function extract_data(type) 156264840Sdteske { 157264840Sdteske data = $0 158264840Sdteske sub("^[[:space:]]*<" type ">", "", data) 159264840Sdteske sub("</" type ">.*$", "", data) 160264840Sdteske return data 161264840Sdteske } 162264840Sdteske ############################################### OPENING PATTERNS 163264840Sdteske $1 == "<mesh>" { mesh = 1 } 164264840Sdteske $1 ~ /^<(class|geom)$/ && mesh { 165264840Sdteske prop = substr($1, 2) 166264840Sdteske if ((ref = extract_attr($2, "ref")) != "") 167264840Sdteske set_value(prop "_ref", ref) 168264840Sdteske else if ((id = extract_attr($2, "id")) != "") 169264840Sdteske create(prop, id) 170264840Sdteske } 171264840Sdteske $1 ~ /^<(consumer|provider)$/ && mesh { 172264840Sdteske prop = substr($1, 2) 173264840Sdteske if ((ref = extract_attr($2, "ref")) != "") 174264840Sdteske set_value(prop "_ref", ref) 175264840Sdteske else if ((id = extract_attr($2, "id")) != "") { 176264840Sdteske create(prop, id) 177264840Sdteske cur_struct-- 178264840Sdteske propn = struct_count[prop] 179264840Sdteske set_value(prop propn, struct_stack[cur_struct+1]) 180264840Sdteske cur_struct++ 181264840Sdteske } 182264840Sdteske } 183264840Sdteske $1 == "<config>" && mesh { create_config() } 184264840Sdteske ############################################### PROPERTIES 185264840Sdteske $1 ~ /^<[[:alnum:]]+>/ { 186264840Sdteske prop = $1 187264840Sdteske sub(/^</, "", prop); sub(/>.*/, "", prop) 188264840Sdteske set_value(prop, extract_data(prop)) 189264840Sdteske } 190264840Sdteske ############################################### CLOSING PATTERNS 191264840Sdteske $1 ~ "^</(consumer|provider|config)>$" { cur_struct-- } 192264840Sdteske $1 == "</geom>" { 193264840Sdteske set_value("nconsumers", struct_count["consumer"]) 194264840Sdteske set_value("nproviders", struct_count["provider"]) 195264840Sdteske cur_struct-- 196264840Sdteske struct_count["consumer"] = 0 197264840Sdteske struct_count["provider"] = 0 198264840Sdteske } 199264840Sdteske $1 == "</class>" { 200264840Sdteske set_value("ngeoms", struct_count["geom"]) 201264840Sdteske cur_struct-- 202264840Sdteske struct_count["consumer"] = 0 203264840Sdteske struct_count["provider"] = 0 204264840Sdteske struct_count["geom"] = 0 205264840Sdteske } 206264840Sdteske $1 == "</mesh>" { 207264840Sdteske printf "NGEOM_CLASSES=%u\n", struct_count["class"] 208264840Sdteske delete struct_count 209264840Sdteske mesh = 0 210264840Sdteske }' )" 211264840Sdteske} 212264840Sdteske 213264840Sdteske# f_geom_reset 214264840Sdteske# 215264840Sdteske# Reset the registered GEOM chain. 216264840Sdteske# 217264840Sdteskef_geom_reset() 218264840Sdteske{ 219264840Sdteske local classn=1 class ngeoms geomn geom 220264840Sdteske while [ $classn -le ${NGEOM_CLASSES:-0} ]; do 221264840Sdteske class=geom_class_$classn 222264840Sdteske $class get ngeoms ngeoms 223264840Sdteske geomn=1 224264840Sdteske while [ $geomn -le $ngeoms ]; do 225264840Sdteske f_struct_free ${class}_geom_$geomn 226264840Sdteske geomn=$(( $geomn + 1 )) 227264840Sdteske done 228264840Sdteske classn=$(( $classn + 1 )) 229264840Sdteske done 230264840Sdteske NGEOM_CLASSES=0 231264840Sdteske} 232264840Sdteske 233264840Sdteske# f_geom_rescan 234264840Sdteske# 235264840Sdteske# Rescan all GEOMs - convenience function. 236264840Sdteske# 237264840Sdteskef_geom_rescan() 238264840Sdteske{ 239264840Sdteske f_geom_reset 240264840Sdteske f_geom_get_all 241264840Sdteske} 242264840Sdteske 243264840Sdteske# f_geom_find $name [$type [$var_to_set]] 244264840Sdteske# 245264840Sdteske# Find one or more registered GEOMs by name, type, or both. Returns a space- 246264840Sdteske# separated list of GEOMs matching the search criterion. The $type argument 247264840Sdteske# should be the GEOM class (see $GEOM_CLASS_* variables in GLOBALS above). 248264840Sdteske# 249264840Sdteske# If $var_to_set is missing or NULL, the GEOM name(s) are printed to standard 250264840Sdteske# out for capturing in a sub-shell (which is less-recommended because of 251264840Sdteske# performance degredation; for example, when called in a loop). 252264840Sdteske# 253264840Sdteskef_geom_find() 254264840Sdteske{ 255264840Sdteske local __name="$1" __type="${2:-$GEOM_CLASS_ANY}" __var_to_set="$3" 256264840Sdteske local __classn=1 __class __class_name __ngeoms 257264840Sdteske local __geomn __geom __geom_name __found= 258264840Sdteske while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do 259264840Sdteske __class=geom_class_$__classn 260264840Sdteske $__class get name __class_name 261264840Sdteske if [ "$__type" != "$GEOM_CLASS_ANY" -a \ 262264840Sdteske "$__type" != "$__class_name" ] 263264840Sdteske then 264264840Sdteske __classn=$(( $__classn + 1 )) 265264840Sdteske continue 266264840Sdteske fi 267264840Sdteske 268264840Sdteske __geomn=1 269264840Sdteske $__class get ngeoms __ngeoms || __ngeoms=0 270264840Sdteske while [ $__geomn -le $__ngeoms ]; do 271264840Sdteske __geom=${__class}_geom_$__geomn 272264840Sdteske $__geom get name __geom_name 273264840Sdteske [ "$__name" = "$__geom_name" -o ! "$__name" ] && 274264840Sdteske __found="$__found $__geom" 275264840Sdteske __geomn=$(( $__geomn + 1 )) 276264840Sdteske done 277264840Sdteske __classn=$(( $__classn + 1 )) 278264840Sdteske done 279264840Sdteske if [ "$__var_to_set" ]; then 280264840Sdteske setvar "$__var_to_set" "${__found# }" 281264840Sdteske else 282264840Sdteske echo $__found 283264840Sdteske fi 284264840Sdteske [ "$__found" ] # Return status 285264840Sdteske} 286264840Sdteske 287264840Sdteske# f_geom_find_by $prop $find [$type [$var_to_set]] 288264840Sdteske# 289264840Sdteske# Find GEOM-related struct where $prop of the struct is equal to $find. Returns 290264840Sdteske# NULL or the name of the first GEOM struct to match. The $type argument should 291264840Sdteske# be one of the following: 292264840Sdteske# 293264840Sdteske# NULL Find any of the below 294264840Sdteske# class Find GEOM_CLASS struct 295264840Sdteske# geom Find GEOM_GEOM struct 296264840Sdteske# consumer Find GEOM_CONSUMER struct 297264840Sdteske# provider Find GEOM_PROVIDER struct 298264840Sdteske# 299264840Sdteske# The $prop argument can be any property of the given type of struct. Some 300264840Sdteske# properties are common to all types (such as id) so the $type argument is 301264840Sdteske# optional (allowing you to return any struct whose property matches $find). 302264840Sdteske# 303264840Sdteske# If $var_to_set is missing or NULL, the GEOM struct name is printed to 304264840Sdteske# standard out for capturing in a sub-shell (which is less-recommended because 305264840Sdteske# of performance degredation; for example when called in a loop). 306264840Sdteske# 307264840Sdteskef_geom_find_by() 308264840Sdteske{ 309264840Sdteske local __prop="$1" __find="$2" __type="$3" __var_to_set="$4" 310264840Sdteske local __classn=1 __class __ngeoms 311264840Sdteske local __geomn __geom __nitems 312264840Sdteske local __itype __itemn __item 313264840Sdteske local __value __found= 314264840Sdteske 315264840Sdteske if [ ! "$__prop" ]; then 316264840Sdteske [ "$__var_to_set" ] && setvar "$__var_to_set" "" 317264840Sdteske return $FAILURE 318264840Sdteske fi 319264840Sdteske 320264840Sdteske case "$__type" in 321264840Sdteske "") : OK ;; 322264840Sdteske class|GEOM_CLASS) __type=class ;; 323264840Sdteske geom|GEOM_GEOM) __type=geom ;; 324264840Sdteske consumer|GEOM_CONSUMER) __type=consumer ;; 325264840Sdteske provider|GEOM_PROVIDER) __type=provider ;; 326264840Sdteske *) 327264840Sdteske [ "$__var_to_set" ] && setvar "$__var_to_set" "" 328264840Sdteske return $FAILURE 329264840Sdteske esac 330264840Sdteske 331264840Sdteske while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do 332264840Sdteske __class=geom_class_$__classn 333264840Sdteske 334264840Sdteske if [ "${__type:-class}" = "class" ]; then 335264840Sdteske $__class get "$__prop" __value || __value= 336264840Sdteske [ "$__value" = "$__find" ] && __found="$__class" break 337264840Sdteske [ "$__type" ] && __classn=$(( $__classn + 1 )) continue 338264840Sdteske fi 339264840Sdteske 340264840Sdteske __geomn=1 341264840Sdteske $__class get ngeoms __ngeoms || __ngeoms=0 342264840Sdteske while [ $__geomn -le $__ngeoms ]; do 343264840Sdteske __geom=${__class}_geom_$__geomn 344264840Sdteske 345264840Sdteske if [ "${__type:-geom}" = "geom" ]; then 346264840Sdteske $__geom get "$__prop" __value || __value= 347264840Sdteske [ "$__value" = "$__find" ] && 348264840Sdteske __found="$__geom" break 349264840Sdteske [ "$__type" ] && 350264840Sdteske __geomn=$(( $__geomn + 1 )) continue 351264840Sdteske fi 352264840Sdteske 353264840Sdteske for __itype in ${__type:-consumer provider}; do 354264840Sdteske $__geom get n${__itype}s __nitems || continue 355264840Sdteske __itemn=1 356264840Sdteske while [ $__itemn -le $__nitems ]; do 357264840Sdteske __item=${__geom}_${__itype}_$__itemn 358264840Sdteske 359264840Sdteske $__item get "$__prop" __value || 360264840Sdteske __value= 361264840Sdteske [ "$__value" = "$__find" ] && 362264840Sdteske __found="$__item" break 363264840Sdteske __itemn=$(( $__itemn + 1 )) 364264840Sdteske done 365264840Sdteske [ "$__found" ] && break 366264840Sdteske done 367264840Sdteske [ "$__found" ] && break 368264840Sdteske __geomn=$(( $__geomn + 1 )) 369264840Sdteske done 370264840Sdteske [ "$__found" ] && break 371264840Sdteske __classn=$(( $__classn + 1 )) 372264840Sdteske done 373264840Sdteske if [ "$__var_to_set" ]; then 374264840Sdteske setvar "$__var_to_set" "$__found" 375264840Sdteske else 376264840Sdteske [ "$__found" ] && echo "$__found" 377264840Sdteske fi 378264840Sdteske [ "$__found" ] # Return status 379264840Sdteske} 380264840Sdteske 381264840Sdteske# f_geom_parent $geom|$consumer|$provider|$config [$var_to_set] 382264840Sdteske# 383264840Sdteske# Get the GEOM class associated with one of $geom, $consumer, $provider or 384264840Sdteske# $config. 385264840Sdteske# 386264840Sdteske# If $var_to_set is missing or NULL, the GEOM class name is printed to standard 387264840Sdteske# out for capturing in a sub-shell (which is less-recommended because of 388264840Sdteske# performance degredation; for example when called in a loop). 389264840Sdteske# 390264840Sdteskef_geom_parent() 391264840Sdteske{ 392264840Sdteske local __struct="$1" __var_to_set="$2" 393264840Sdteske # NB: Order of pattern matches below is important 394264840Sdteske case "$__struct" in 395264840Sdteske *_config*) __struct="${__struct%_config*}" ;; 396264840Sdteske *_consumer_*) __struct="${__struct%_consumer_[0-9]*}" ;; 397264840Sdteske *_provider_*) __struct="${__struct%_provider_[0-9]*}" ;; 398264840Sdteske *_geom_*) __struct="${__struct%_geom_[0-9]*}" ;; 399264840Sdteske *) __struct= 400264840Sdteske esac 401264840Sdteske if [ "$__var_to_set" ]; then 402264840Sdteske setvar "$__var_to_set" "$__struct" 403264840Sdteske else 404264840Sdteske echo "$__struct" 405264840Sdteske fi 406264840Sdteske f_struct "$__struct" # Return status 407264840Sdteske} 408264840Sdteske 409264840Sdteske############################################################ MAIN 410264840Sdteske 411264840Sdteske# 412280921Sdteske# Parse GEOM configuration unless requested otherwise 413264840Sdteske# 414264840Sdteskef_dprintf "%s: GEOM_SELF_SCAN_ALL=[%s]" geom.subr "$GEOM_SELF_SCAN_ALL" 415264840Sdteskecase "$GEOM_SELF_SCAN_ALL" in 416264840Sdteske""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; 417264840Sdteske*) 418264840Sdteske f_geom_get_all 419264840Sdteske if [ "$debug" ]; then 420264840Sdteske debug= f_geom_find "" "$GEOM_CLASS_ANY" geoms 421264840Sdteske f_count ngeoms $geoms 422264840Sdteske f_dprintf "%s: Initialized %u geom devices in %u classes." \ 423264840Sdteske geom.subr "$ngeoms" "$NGEOM_CLASSES" 424264840Sdteske unset geoms ngeoms 425264840Sdteske fi 426264840Sdteskeesac 427264840Sdteske 428264840Sdteskef_dprintf "%s: Successfully loaded." geom.subr 429264840Sdteske 430264840Sdteskefi # ! $_GEOM_SUBR 431