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