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