Date: Wed, 23 Apr 2014 22:04:05 +0000 (UTC) From: Devin Teske <dteske@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r264840 - in head/usr.sbin/bsdconfig: dot examples networking/share share share/media share/packages Message-ID: <201404232204.s3NM45NQ064960@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dteske Date: Wed Apr 23 22:04:04 2014 New Revision: 264840 URL: http://svnweb.freebsd.org/changeset/base/264840 Log: Implement GEOM based media device classification. You'll notice a few different things from this commit: + More devices. Devices that were previously ignored are now present. + Faster device scanning. "There is no try, only Do" -- f_device_try() is no longer the basis of device scanning as GEOM provides [nearly] all devices (doesn't provide network devices). + More information available as non-root. Usually you have to be root to do things like taste filesystems, and that limits the amount of information available to non-root users; with GEOM, we see all even running unprivileged as the brunt of information (except for so- called ``dangerously dedicated'' file systems) is represented by the `kern.geom.confxml' sysctl(8) MIB. NB: Only really useful for external scripts that use the API and run as non-root; where this code is used in bsdconfig(8) and bsdinstall(8) you are running as root so can detect even ``dangerously dedicated'' file systems that are not present in GEOM; e.g., no PART class for a DOS filesystem written directly to disk without partition table). + No more use of legacy tools such as diskinfo(8) to get disk capacity or fdisk(8) to see partitions. MFC after: 1 week Added: head/usr.sbin/bsdconfig/share/geom.subr (contents, props changed) Modified: head/usr.sbin/bsdconfig/dot/dot head/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh head/usr.sbin/bsdconfig/examples/browse_packages_http.sh head/usr.sbin/bsdconfig/networking/share/device.subr head/usr.sbin/bsdconfig/share/Makefile head/usr.sbin/bsdconfig/share/common.subr head/usr.sbin/bsdconfig/share/device.subr head/usr.sbin/bsdconfig/share/media/cdrom.subr head/usr.sbin/bsdconfig/share/media/common.subr head/usr.sbin/bsdconfig/share/media/directory.subr head/usr.sbin/bsdconfig/share/media/dos.subr head/usr.sbin/bsdconfig/share/media/floppy.subr head/usr.sbin/bsdconfig/share/media/ftp.subr head/usr.sbin/bsdconfig/share/media/http.subr head/usr.sbin/bsdconfig/share/media/nfs.subr head/usr.sbin/bsdconfig/share/media/tcpip.subr head/usr.sbin/bsdconfig/share/media/ufs.subr head/usr.sbin/bsdconfig/share/media/usb.subr head/usr.sbin/bsdconfig/share/packages/index.subr head/usr.sbin/bsdconfig/share/packages/packages.subr head/usr.sbin/bsdconfig/share/struct.subr Modified: head/usr.sbin/bsdconfig/dot/dot ============================================================================== --- head/usr.sbin/bsdconfig/dot/dot Wed Apr 23 21:52:43 2014 (r264839) +++ head/usr.sbin/bsdconfig/dot/dot Wed Apr 23 22:04:04 2014 (r264840) @@ -29,7 +29,7 @@ ############################################################ INCLUDES # Prevent common.subr from auto initializing debugging (this is not an inter- -# active utility that requires debugging; also `-d' has been repurposed). +# active utility so does not require debugging; also `-d' has been repurposed). # DEBUG_SELF_INITIALIZE=NO Modified: head/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh ============================================================================== --- head/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh Wed Apr 23 21:52:43 2014 (r264839) +++ head/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh Wed Apr 23 22:04:04 2014 (r264840) @@ -18,7 +18,7 @@ if [ ! -e "$TMPDIR/packages/INDEX" ]; th mediaSetFTP mediaOpen f_show_info "Downloading packages/INDEX from\n %s" "$_ftpPath" - f_device_get media packages/INDEX > $TMPDIR/packages/INDEX + f_device_get device_media packages/INDEX > $TMPDIR/packages/INDEX fi _directoryPath=$TMPDIR mediaSetDirectory Modified: head/usr.sbin/bsdconfig/examples/browse_packages_http.sh ============================================================================== --- head/usr.sbin/bsdconfig/examples/browse_packages_http.sh Wed Apr 23 21:52:43 2014 (r264839) +++ head/usr.sbin/bsdconfig/examples/browse_packages_http.sh Wed Apr 23 22:04:04 2014 (r264840) @@ -18,7 +18,7 @@ if [ ! -e "$TMPDIR/packages/INDEX" ]; th mediaSetHTTP mediaOpen f_show_info "Downloading packages/INDEX from\n %s" "$_httpPath" - f_device_get media packages/INDEX > $TMPDIR/packages/INDEX + f_device_get device_media packages/INDEX > $TMPDIR/packages/INDEX fi _directoryPath=$TMPDIR mediaSetDirectory Modified: head/usr.sbin/bsdconfig/networking/share/device.subr ============================================================================== --- head/usr.sbin/bsdconfig/networking/share/device.subr Wed Apr 23 21:52:43 2014 (r264839) +++ head/usr.sbin/bsdconfig/networking/share/device.subr Wed Apr 23 22:04:04 2014 (r264840) @@ -75,10 +75,11 @@ f_dialog_menu_netdev() # # Get list of usable network interfaces # - local devs if iflist= # Calculated below + local dev devs if iflist= # Calculated below f_device_rescan_network f_device_find "" $DEVICE_TYPE_NETWORK devs - for if in $devs; do + for dev in $devs; do + f_struct "$dev" get name if || continue # Skip unsavory interfaces case "$if" in lo[0-9]*|ppp[0-9]*|sl[0-9]*|faith[0-9]*) continue ;; Modified: head/usr.sbin/bsdconfig/share/Makefile ============================================================================== --- head/usr.sbin/bsdconfig/share/Makefile Wed Apr 23 21:52:43 2014 (r264839) +++ head/usr.sbin/bsdconfig/share/Makefile Wed Apr 23 22:04:04 2014 (r264840) @@ -5,7 +5,7 @@ NO_OBJ= SUBDIR= media packages FILESDIR= ${SHAREDIR}/bsdconfig -FILES= common.subr device.subr dialog.subr keymap.subr \ +FILES= common.subr device.subr dialog.subr geom.subr keymap.subr \ mustberoot.subr script.subr strings.subr struct.subr \ sysrc.subr variable.subr Modified: head/usr.sbin/bsdconfig/share/common.subr ============================================================================== --- head/usr.sbin/bsdconfig/share/common.subr Wed Apr 23 21:52:43 2014 (r264839) +++ head/usr.sbin/bsdconfig/share/common.subr Wed Apr 23 22:04:04 2014 (r264840) @@ -153,7 +153,7 @@ f_debug_init() # Process stored command-line arguments # set -- $ARGV - local OPTIND flag + local OPTIND OPTARG flag f_dprintf "f_debug_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \ "$ARGV" "$GETOPTS_STDARGS" while getopts "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" flag \ @@ -798,14 +798,30 @@ f_running_as_init() } # f_mounted $local_directory +# f_mounted -b $device # -# Return success if a filesystem is mounted on a particular directory. +# Return success if a filesystem is mounted on a particular directory. If `-b' +# is present, instead check that the block device (or a partition thereof) is +# mounted. # f_mounted() { - local dir="$1" - [ -d "$dir" ] || return $FAILURE - mount | grep -Eq " on $dir \([^)]+\)$" + local OPTIND OPTARG flag use_device= + while getopts b flag; do + case "$flag" in + b) use_device=1 ;; + esac + done + shift $(( $OPTIND - 1 )) + if [ "$use_device" ]; then + local device="$1" + mount | grep -Eq \ + "^$device([[:space:]]|p[0-9]|s[0-9]|\.nop|\.eli)" + else + [ -d "$dir" ] || return $FAILURE + mount | grep -Eq " on $dir \([^)]+\)$" + fi + # Return status is that of last grep(1) } # f_eval_catch [-de] [-k $var_to_set] $funcname $utility \ @@ -890,7 +906,7 @@ f_eval_catch() # # Process local function arguments # - local OPTIND __flag + local OPTIND OPTARG __flag while getopts "dek:" __flag > /dev/null; do case "$__flag" in d) __no_dialog=1 ;; Modified: head/usr.sbin/bsdconfig/share/device.subr ============================================================================== --- head/usr.sbin/bsdconfig/share/device.subr Wed Apr 23 21:52:43 2014 (r264839) +++ head/usr.sbin/bsdconfig/share/device.subr Wed Apr 23 22:04:04 2014 (r264840) @@ -32,6 +32,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." device.subr f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/geom.subr f_include $BSDCFG_SHARE/strings.subr f_include $BSDCFG_SHARE/struct.subr @@ -40,42 +41,53 @@ f_include_lang $BSDCFG_LIBE/include/mess ############################################################ GLOBALS -DEVICES= -DEVICE_NAMES= -NDEVICES=0 +NDEVICES=0 # Set by f_device_register(), used by f_device_*() -# A "device" from sysinstall's point of view +# +# A "device" from legacy sysinstall's point of view (mostly) +# +# NB: Disk devices have their `private' property set to GEOM ident +# NB: USB devices have their `private' property set to USB disk device name +# f_struct_define DEVICE \ - name \ + capacity \ desc \ devname \ - type \ - capacity \ enabled \ - init \ - get \ - shutdown \ flags \ + get \ + init \ + name \ private \ + shutdown \ + type \ volume # Network devices have their `private' property set to this f_struct_define DEVICE_INFO \ - use_rtsol use_dhcp ipaddr ipv6addr netmask extras - -setvar DEVICE_TYPE_NONE 1 -setvar DEVICE_TYPE_DISK 2 -setvar DEVICE_TYPE_FLOPPY 3 -setvar DEVICE_TYPE_FTP 4 -setvar DEVICE_TYPE_NETWORK 5 -setvar DEVICE_TYPE_CDROM 6 -setvar DEVICE_TYPE_USB 7 -setvar DEVICE_TYPE_DOS 8 -setvar DEVICE_TYPE_UFS 9 -setvar DEVICE_TYPE_NFS 10 -setvar DEVICE_TYPE_ANY 11 -setvar DEVICE_TYPE_HTTP_PROXY 12 -setvar DEVICE_TYPE_HTTP 13 + extras \ + ipaddr \ + ipv6addr \ + netmask \ + use_dhcp \ + use_rtsol + +# +# Device types for f_device_register(), f_device_find(), et al. +# +setvar DEVICE_TYPE_ANY "any" # Any +setvar DEVICE_TYPE_NONE "NONE" # Unknown +setvar DEVICE_TYPE_DISK "DISK" # GEOM `DISK' +setvar DEVICE_TYPE_FLOPPY "FD" # GEOM `FD' +setvar DEVICE_TYPE_FTP "FTP" # Dynamic network device +setvar DEVICE_TYPE_NETWORK "NETWORK" # See f_device_get_all_network +setvar DEVICE_TYPE_CDROM "CDROM" # GEOM `DISK' +setvar DEVICE_TYPE_USB "USB" # GEOM `PART' +setvar DEVICE_TYPE_DOS "DOS" # GEOM `DISK' `PART' or `LABEL' +setvar DEVICE_TYPE_UFS "UFS" # GEOM `DISK' `PART' or `LABEL' +setvar DEVICE_TYPE_NFS "NFS" # Dynamic network device +setvar DEVICE_TYPE_HTTP_PROXY "HTTP_PROXY" # Dynamic network device +setvar DEVICE_TYPE_HTTP "HTTP" # Dynamic network device # Network devices have the following flags available setvar IF_ETHERNET 1 @@ -87,76 +99,70 @@ setvar IF_ACTIVE 4 # : ${DEVICE_SELF_SCAN_ALL=1} -############################################################ FUNCTIONS - -# f_device_try $name [$i [$var_path]] -# -# Test a particular device. If $i is given, then $name is expected to contain a -# single "%d" where $i will be inserted using printf. If $var_path is given, -# it is used as a variable name to provide the caller the device pathname. # -# Returns success if the device path exists and is a cdev. +# Device Catalog variables # -f_device_try() -{ - local name="$1" i="$2" var_path="$3" unit - if [ "$i" ]; then - f_sprintf unit "$name" "$i" - else - unit="$name" - fi - case "$unit" in - /dev/*) : good ;; # already qualified - *) unit="/dev/$unit" ;; - esac - [ "$var_path" ] && setvar "$var_path" "$unit" - f_dprintf "f_device_try: making sure %s is a device node" "$unit" - if [ -c "$unit" ]; then - f_dprintf "f_device_try: %s is a cdev [good]" "$unit" - return $SUCCESS - else - f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit" - return $FAILURE - fi -} +DEVICE_CATALOG_APPEND_ONLY= # Used by f_device_catalog_set() +NCATALOG_DEVICES=0 # Used by f_device_catalog_*() and MAIN -# f_device_register $name $desc $devname $type $enabled $init_function \ -# $get_function $shutdown_function $private $capacity # -# Register a device. A `structure' (see struct.subr) is created with the name -# device_$name (so make sure $name contains only alpha-numeric characters or -# the underscore, `_'). The remaining arguments after $name correspond to the -# properties of the `DEVICE' structure-type (defined above). +# A ``catalog'' device is for mapping GEOM devices to media devices (for +# example, determining if a $GEOM_CLASS_DISK geom is $DEVICE_TYPE_CDROM or +# $DEVICE_TYPE_DISK) and also getting default descriptions for devices that +# either lack a GEOM provided description or lack a presence in GEOM) # -# If not already registered, the device is then appended to the DEVICES -# environment variable, a space-separated list of all registered devices. +f_struct_define CATALOG_DEVICE \ + desc \ + name \ + type + +############################################################ FUNCTIONS + +# f_device_register $var_to_set $name $desc $devname $type $enabled +# $init_function $get_function $shutdown_function +# $private $capacity +# +# Register a device. A `structure' (see struct.subr) is created and if +# $var_to_set is non-NULL, upon success holds the name of the struct created. +# The remaining positional arguments correspond to the properties of the +# `DEVICE' structure-type to be assigned (defined above). +# +# If not already registered (based on $name and $type), a new device is created +# and $NDEVICES is incremented. # f_device_register() { - local name="$1" desc="$2" devname="$3" type="$4" enabled="$5" - local init_func="$6" get_func="$7" shutdown_func="$8" private="$9" - local capacity="${10}" - - f_struct_new DEVICE "device_$name" || return $FAILURE - device_$name set name "$name" - device_$name set desc "$desc" - device_$name set devname "$devname" - device_$name set type "$type" - device_$name set enabled "$enabled" - device_$name set init "$init_func" - device_$name set get "$get_func" - device_$name set shutdown "$shutdown_func" - device_$name set private "$private" - device_$name set capacity "$capacity" - - # Scan our global register to see if it needs ammending - local dev found= - for dev in $DEVICES; do - [ "$dev" = "$name" ] || continue - found=1 && break - done - [ "$found" ] || DEVICES="$DEVICES $name" + local __var_to_set="$1" __name="$2" __desc="$3" __devname="$4" + local __type="$5" __enabled="$6" __init_func="$7" __get_func="$8" + local __shutdown_func="$9" __private="${10}" __capacity="${11}" + # Required parameter(s) + [ "$__name" ] || return $FAILURE + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "" || return $FAILURE + fi + + local __device + if f_device_find -1 "$__name" "$__type" __device; then + f_struct_free "$__device" + f_struct_new DEVICE "$__device" || return $FAILURE + else + __device=device_$(( NDEVICES + 1 )) + f_struct_new DEVICE "$__device" || return $FAILURE + NDEVICES=$(( $NDEVICES + 1 )) + fi + $__device set name "$__name" + $__device set desc "$__desc" + $__device set devname "$__devname" + $__device set type "$__type" + $__device set enabled "$__enabled" + $__device set init "$__init_func" + $__device set get "$__get_func" + $__device set shutdown "$__shutdown_func" + $__device set private "$__private" + $__device set capacity "$__capacity" + + [ "$__var_to_set" ] && setvar "$__var_to_set" "$__device" return $SUCCESS } @@ -166,18 +172,21 @@ f_device_register() # f_device_reset() { - local dev - for dev in $DEVICES; do - f_device_shutdown $dev + local n=1 + while [ $n -le $NDEVICES ]; do + f_device_shutdown device_$n + # # XXX This potentially leaks $dev->private if it's being # used to point to something dynamic, but you're not supposed # to call this routine at such times that some open instance # has its private member pointing somewhere anyway. # - f_struct_free device_$dev + f_struct_free device_$n + + n=$(( $n + 1 )) done - DEVICES= + NDEVICES=0 } # f_device_reset_network @@ -186,34 +195,45 @@ f_device_reset() # f_device_reset_network() { - local dev type private pruned_list= - for dev in $DEVICES; do - device_$dev get type type - if [ "$type" != "$DEVICE_TYPE_NETWORK" ]; then - pruned_list="$pruned_list $dev" - continue - fi + local n=1 device type private i + while [ $n -le $NDEVICES ]; do + device=device_$n + f_struct $device || continue + $device get type type + [ "$type" = "$DEVICE_TYPE_NETWORK" ] || continue # # Leave the device up (don't call shutdown routine) # # Network devices may have DEVICE_INFO private member - device_$dev get private private + $device get private private [ "$private" ] && f_struct_free "$private" - f_struct_free device_$dev + # Free the network device + f_struct_free $device + + # Fill the gap we just created + i=$n + while [ $i -lt $NDEVICES ]; do + f_struct_copy device_$(( $i + 1 )) device_$i + done + f_struct_free device_$NDEVICES + + # Finally decrement the number of devices + NDEVICES=$(( $NDEVICES - 1 )) + + n=$(( $n + 1 )) done - DEVICES="${pruned_list# }" } # f_device_get_all # -# Get all device information for devices we have attached. +# Get all device information for all devices. # f_device_get_all() { - local devname desc capacity + local devname type desc capacity f_dprintf "f_device_get_all: Probing devices..." f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while" @@ -221,180 +241,16 @@ f_device_get_all() # First go for the network interfaces f_device_get_all_network - # Next, try to find all the types of devices one might use - # as a media source for content - # - - local dev type max n=0 - for dev in $DEVICE_NAMES; do - n=$(( $n + 1 )) - # Get the desc, type, and max (with debugging disabled) - # NOTE: Bypassing f_device_name_get() for efficiency - # ASIDE: This would be equivalent to the following: - # debug= f_device_name_get $dev desc - # debug= f_device_name_get $dev type - # debug= f_device_name_get $dev max - debug= f_getvar _device_desc$n desc - debug= f_getvar _device_type$n type - debug= f_getvar _device_max$n max - - local k=0 - while [ $k -lt ${max:-0} ]; do - i=$k k=$(( $k + 1 )) - devname="" - case "$type" in - $DEVICE_TYPE_CDROM) - f_device_try "$dev" "$i" devname || continue - f_device_capacity "$devname" capacity - f_device_register "${devname##*/}" "$desc" \ - "$devname" $DEVICE_TYPE_CDROM 1 \ - f_media_init_cdrom f_media_get_cdrom \ - f_media_shutdown_cdrom "" "$capacity" - f_dprintf "Found a CDROM device for %s" \ - "$devname" - ;; - $DEVICE_TYPE_FLOPPY) - f_device_try "$dev" "$i" devname || continue - f_device_capacity "$devname" capacity - f_device_register "${devname##*/}" "$desc" \ - "$devname" $DEVICE_TYPE_FLOPPY 1 \ - f_media_init_floppy \ - f_media_get_floppy \ - f_media_shutdown_floppy "" "$capacity" - f_dprintf "Found a floppy device for %s" \ - "$devname" - ;; - $DEVICE_TYPE_USB) - f_device_try "$dev" "$i" devname || continue - f_device_capacity "$devname" capacity - f_device_register "${devname##*/}" "$desc" \ - "$devname" $DEVICE_TYPE_USB 1 \ - f_media_init_usb f_media_get_usb \ - f_media_shutdown_usb "" "$capacity" - f_dprintf "Found a USB disk for %s" "$devname" - ;; - esac - done - done - - # Register ISO9660 providers as CDROM devices - for devname in /dev/iso9660/*; do - f_device_try "$devname" || continue - f_device_capacity "$devname" capacity - f_device_register "${devname##*/}" "ISO9660 file system" \ - "$devname" $DEVICE_TYPE_CDROM 1 \ - f_media_init_cdrom f_media_get_cdrom \ - f_media_shutdown_cdrom "" "$capacity" - f_dprintf "Found a CDROM device for %s" "$devname" - done - - # Scan for mdconfig(8)-created md(4) devices - local filename - for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do - f_device_try "$devname" || continue - - # See if the md(4) device is a vnode type backed by a file - filename=$( sysctl kern.geom.conftxt | - awk -v devname="${devname##*/}" \ - ' - ( $2 == "MD" ) && \ - ( $3 == devname ) && \ - ( $(NF-2) == "vnode" ) && \ - ( $(NF-1) == "file" ) \ - { - print $NF - } - ' ) - case "$filename" in - *.iso) # Register the device as an ISO9660 provider - f_device_capacity "$devname" capacity - f_device_register "${devname##*/}" \ - "md(4) vnode file system" \ - "$devname" $DEVICE_TYPE_CDROM 1 \ - f_media_init_cdrom f_media_get_cdrom \ - f_media_shutdown_cdrom "" "$capacity" - f_dprintf "Found a CDROM device for %s" "$devname" - ;; - esac - done - - # Finally go get the disks and look for partitions to register - local diskname slices index type rest slice part - for diskname in $( sysctl -n kern.disks ); do - - case "$diskname" in - cd*) - # XXX Due to unknown reasons, kern.disks returns SCSI - # CDROM as a valid disk. This will prevent bsdconfig - # from presenting SCSI CDROMs as available disks in - # various menus. Why GEOM treats SCSI CDROM as a disk - # is beyond me and that should be investigated. - # For temporary workaround, ignore SCSI CDROM device. - # - continue ;; - esac - - # Try to create a list of partitions and their types, - # consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06"). - if ! slices=$( fdisk -p "$diskname" 2> /dev/null | - awk '( $1 == "p" ) { print $2","$3 }' ) - then - f_dprintf "Unable to open disk %s" "$diskname" - continue + # Next, go for the GEOM devices we might want to use as media + local geom geoms geom_name + debug= f_geom_find "" $GEOM_CLASS_DEV geoms + for geom in $geoms; do + if ! f_device_probe_geom $geom; then + debug= $geom get name geom_name + f_dprintf "WARNING! Unable to classify %s as %s" \ + "GEOM device $geom_name" "media source" fi - - # Try and find its description - f_device_desc "$diskname" $DEVICE_TYPE_DISK desc - - f_device_capacity "$diskname" capacity - f_device_register "$diskname" "$desc" \ - "/dev/$diskname" $DEVICE_TYPE_DISK 0 \ - "" "" "" "" "$capacity" - f_dprintf "Found a disk device named %s" "$diskname" - - # Look for existing partitions to register - for slice in $slices; do - index="${slice%%,*}" type="${slice#*,}" - slice=${diskname}s$index - case "$type" in - 0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef) - # DOS partitions to add as "DOS media devices" - f_device_capacity "/dev/$slice" capacity - f_device_register "$slice" "" \ - "/dev/$slice" $DEVICE_TYPE_DOS 1 \ - f_media_init_dos f_media_get_dos \ - f_media_shutdown_dos "" "$capacity" - f_dprintf "Found a DOS partition %s" "$slice" - ;; - 0xa5) # FreeBSD partition - for part in $( - bsdlabel -r $slice 2> /dev/null | - awk -v slice="$slice" ' - ( $1 ~ /[abdefgh]:/ ) { - printf "%s%s\n", - slice, - substr($1,1,1) - }' - ); do - f_quietly dumpfs -m /dev/$part || - continue - f_device_capacity \ - "$/dev/$part" capacity - f_device_register \ - "$part" "" "/dev/$part" \ - $DEVICE_TYPE_UFS 1 \ - f_media_init_ufs \ - f_media_get_ufs \ - f_media_shutdown_ufs "" \ - "$capacity" - f_dprintf "Found a UFS partition %s" \ - "$part" - done # parts - ;; - esac - done # slices - - done # disks + done } # f_device_get_all_network @@ -403,7 +259,7 @@ f_device_get_all() # f_device_get_all_network() { - local devname desc flags + local devname desc device flags for devname in $( ifconfig -l ); do # Eliminate network devices that don't make sense case "$devname" in @@ -413,9 +269,9 @@ f_device_get_all_network() # Try and find its description f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc - f_dprintf "Found a network device named %s" "$devname" - f_device_register $devname \ - "$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \ + f_dprintf "Found network device named %s" "$devname" + debug= f_device_register device $devname "$desc" \ + "$devname" $DEVICE_TYPE_NETWORK 1 \ f_media_init_network "" f_media_shutdown_network "" -1 # Set flags based on media and status @@ -435,37 +291,532 @@ f_device_get_all_network() if (value ~ /^active/) _or(var, "IF_ACTIVE") } }' )" - device_$devname set flags $flags + $device set flags $flags done } -# f_device_name_get $type $name type|desc|max [$var_to_set] +# f_device_rescan +# +# Rescan all devices, after closing previous set - convenience function. # -# Fetch the device type (type), description (desc), or maximum number of -# devices to scan for (max) associated with device $name and $type. If $type is -# either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used. +f_device_rescan() +{ + f_device_reset + f_geom_rescan + f_device_get_all +} + +# f_device_rescan_network +# +# Rescan all network devices, after closing previous set - for convenience. +# +f_device_rescan_network() +{ + f_device_reset_network + f_device_get_all_network +} + +# f_device_probe_geom $geom +# +# Probe a single GEOM device and if it can be classified as a media source, +# register it using f_device_register() with known type-specific arguments. +# +f_device_probe_geom() +{ + local geom="$1" + + f_struct "$geom" || return $FAILURE + + # geom associated variables + local geom_name geom_consumer provider_ref geom_provider= + local provider_geom provider_config provider_class= + local provider_config_type catalog_struct catalog_type + local disk_ident + + # gnop(8)/geli(8) associated variables (p for `parent device') + local p_devname p_geom p_consumer p_provider_ref p_provider + local p_provider_config p_provider_geom p_provider_class + + # md(4) associated variables + local config config_type config_file magic= + + # Temporarily disable debugging to keep debug output light + local old_debug="$debug" debug= + + # + # Get the GEOM name (for use below in device registration) + # + $geom get name devname || continue + + # + # Attempt to get the consumer, provider, provider config, and + # provider class for this geom (errors ignored). + # + # NB: Each GEOM in the `DEV' class should have one consumer. + # That consumer should have a reference to its provider. + # + $geom get consumer1 geom_consumer + f_struct "$geom_consumer" get provider_ref provider_ref && + f_geom_find_by id "$provider_ref" provider geom_provider + if f_struct "$geom_provider"; then + $geom_provider get config provider_config + f_geom_parent $geom_provider provider_geom && + f_geom_parent $provider_geom provider_class + fi + + # + # Get values for device registration (errors ignored) + # + f_struct "$provider_class" get name type + f_struct "$geom_provider" get mediasize capacity + f_struct "$provider_config" get descr desc + + # + # For gnop(8), geli(8), or combination thereof, change device type to + # that of the consumer + # + p_devname= p_geom= p_provider= p_provider_config= + case "$devname" in + *.nop.eli) p_devname="${devname%.nop.eli}" ;; + *.eli.nop) p_devname="${devname%.eli.nop}" ;; + *.eli) p_devname="${devname%.eli}" ;; + *.nop) p_devname="${devname%.nop}" ;; + esac + [ "$p_devname" ] && f_geom_find "$p_devname" $GEOM_CLASS_DEV p_geom + if [ "${p_geom:-$geom}" != "$geom" ]; then + f_struct "$p_geom" get consumer1 p_consumer + f_struct "$p_consumer" get provider_ref p_provider_ref && + f_geom_find_by id "$p_provider_ref" provider p_provider + if f_struct "$p_provider"; then + $p_provider get config p_provider_config + f_geom_parent $p_provider p_provider_geom && + f_geom_parent $p_provider_geom p_provider_class + fi + f_struct "$p_provider_class" get name type + fi + + # Look up geom device in device catalog for default description + f_device_catalog_get \ + $DEVICE_TYPE_ANY "${p_devname:-$devname}" catalog_struct + [ "$desc" ] || f_struct "catalog_device_$catalog_struct" get desc desc + + # Use device catalog entry for potential re-classification(s) + f_struct "catalog_device_$catalog_struct" get type catalog_type + + # Restore debugging for this next part (device registration) + debug="$old_debug" + + # + # Register the device + # + local retval device + case "$type" in + $GEOM_CLASS_DISK) + # First attempt to classify by device catalog (see MAIN) + case "$catalog_type" in + $DEVICE_TYPE_CDROM) + f_dprintf "Found CDROM device for disk %s" "$devname" + debug= f_device_register device "$devname" "$desc" \ + "/dev/$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" "$capacity" && + return $SUCCESS + ;; + esac + + # Fall back to register label device as a disk and taste it + f_dprintf "Found disk device named %s" "$devname" + debug= f_struct "$p_provider_config" get \ + ident disk_ident || + debug= f_struct "$provider_config" get \ + ident disk_ident + debug= f_device_register device "$devname" "$desc" \ + "/dev/$devname" $DEVICE_TYPE_DISK 1 \ + "" "" "" "$disk_ident" "$capacity" + retval=$? + + # Detect ``dangerously dedicated'' filesystems (errors ignored) + f_device_probe_disk_fs device "$devname" "$capacity" && + retval=$SUCCESS + + return $retval + ;; + $GEOM_CLASS_FD) + f_dprintf "Found floppy device named %s" "$devname" + debug= f_device_register device "$devname" "$desc" \ + "/dev/$devname" $DEVICE_TYPE_FLOPPY 1 \ + f_media_init_floppy f_media_get_floppy \ + f_media_shutdown_floppy "" "$capacity" + return $? + ;; + $GEOM_CLASS_LABEL) + : fall through to below section # reduces indentation level + ;; + $GEOM_CLASS_MD) + f_dprintf "Found disk device named %s" "$devname" + debug= f_device_register device "$devname" "$desc" \ + "/dev/$devname" $DEVICE_TYPE_DISK 1 \ + "" "" "" "" "$capacity" + retval=$? + + # + # Attempt to get file(1) magic to potentially classify as + # alternate media type. If unable to get magic, fall back to + # md(4) characteristics (such as vnode filename). + # + [ -r "/dev/$devname" ] && + magic=$( file -bs "/dev/$devname" 2> /dev/null ) + if [ ! "$magic" ]; then + # Fall back to md(4) characteristics + if f_struct "$p_provider_config"; then + config="$p_provider_config" + else + config="$provider_config" + fi + debug= f_struct "$config" get type config_type + debug= f_struct "$config" get file config_file + + # Substitute magic for below based on type and file + case "$config_type=$config_file" in + vnode=*.iso) magic="ISO 9660" ;; + esac + fi + f_device_probe_disk_fs device \ + "$devname" "$capacity" "$magic" && + retval=$SUCCESS # Errors ignored + + return $retval + ;; + $GEOM_CLASS_PART) + if f_struct "$p_provider_config"; then + config="$p_provider_config" + else + config="$provider_config" + fi + debug= f_struct "$config" get type provider_config_type + f_device_probe_geom_part device \ + "$provider_config_type" "$devname" "$capacity" + retval=$? + device_type=$DEVICE_TYPE_NONE + [ $retval -eq $SUCCESS ] && + debug= f_struct "$device" get type device_type + + # Potentially re-classify as USB device + if [ "$device_type" = "$DEVICE_TYPE_UFS" -a \ + "$catalog_type" = "$DEVICE_TYPE_USB" ] + then + f_dprintf "Found USB device for partition %s" \ + "$devname" + debug= f_struct "$p_provider_geom" get \ + name disk_name || + debug= f_struct "$provider_geom" get \ + name disk_name + debug= f_device_register device "$devname" "$desc" \ + "/dev/$devname" $DEVICE_TYPE_USB 1 \ + f_media_init_usb f_media_get_usb \ + f_media_shutdown_usb "$disk_name" "$capacity" + retval=$? + fi + + return $retval + ;; + $GEOM_CLASS_RAID) + # Use the provider geom name as the description + if [ ! "$desc" ]; then + f_struct "$p_provider_geom" get name desc || + f_struct "$provider_geom" get name desc + fi + + f_dprintf "Found disk device named %s" "$devname" + debug= f_device_register device \ + "$devname" "${desc:-GEOM RAID device}" \ + "/dev/$devname" $DEVICE_TYPE_DISK 1 \ + "" "" "" "" "$capacity" + retval=$? + + # Detect ``dangerously dedicated'' filesystems + f_device_probe_disk_fs device "$devname" "$capacity" && + retval=$SUCCESS # Errors ignored + + return $retval + ;; + $GEOM_CLASS_ZFS_ZVOL) + f_dprintf "Found disk device named %s" "$devname" + debug= f_device_register device \ + "$devname" "${desc:-GEOM ZFS::ZVOL device}" \ + "/dev/$devname" $DEVICE_TYPE_DISK 1 \ + "" "" "" "" "$capacity" + retval=$? + + # Detect ``dangerously dedicated'' filesystems + f_device_probe_disk_fs device "$devname" "$capacity" && + retval=$SUCCESS # Errors ignored + + return $retval + ;; + *) + return $FAILURE # Unknown GEOM class + esac + + # + # Still here? Must be $GEOM_CLASS_LABEL + # + + local label_geom label_devname label_devgeom= label_devconsumer + local label_devprovider= label_devprovider_ref label_devprovider_config + local label_gpart_type + + if f_struct "$p_provider"; then + label_geom="$p_provider_geom" + else + label_geom="$provider_geom" + fi + + case "$devname" in + gpt/*|gptid/*) + # + # Attempt to get the partition type by getting the `config' + # member of the provider for our device (which is named in the + # parent geom of our current provider). + # + debug= f_struct "$label_geom" get name label_devname && + debug= f_geom_find "$label_devname" $GEOM_CLASS_DEV \ + label_devgeom + debug= f_struct "$label_devgeom" get \ + consumer1 label_devconsumer + debug= f_struct "$label_devconsumer" get \ + provider_ref label_devprovider_ref && + debug= f_geom_find_by id "$label_devprovider_ref" \ + provider label_devprovider + debug= f_struct "$label_devprovider" get \ + config label_devprovider_config + debug= f_struct "$label_devprovider_config" get \ + type label_gpart_type + + # + # Register device label based on partition type + # + f_device_probe_geom_part device \ + "$label_gpart_type" "$devname" "$capacity" + return $? + ;; + iso9660/*) + f_dprintf "Found CDROM device labeled %s" "$devname" + debug= f_device_register device \ + "$devname" "ISO9660 file system" \ + "/dev/$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" "$capacity" + return $? + ;; + label/*) + # For generic labels, use provider geom name as real device + debug= f_struct "$label_geom" get name label_devname + + # Look up label geom device in device catalog for default desc + debug= f_device_catalog_get \ + $DEVICE_TYPE_ANY "$label_devname" catalog_struct + [ "$desc" ] || debug= f_struct \ + "catalog_device_$catalog_struct" get desc desc + + # Use device catalog entry for potential re-classification(s) + debug= f_struct "catalog_device_$catalog_struct" get \ + type catalog_type + + # First attempt to classify by device catalog (see MAIN) + case "$catalog_type" in + $DEVICE_TYPE_CDROM) + f_dprintf "Found CDROM device for disk %s" "$devname" + debug= f_device_register device "$devname" "$desc" \ + "/dev/$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" "$capacity" && + return $SUCCESS + ;; + esac + + # Fall back to register label device as a disk and taste it + f_dprintf "Found disk device labeled %s" "$devname" + debug= f_device_register device \ + "$devname" "GEOM LABEL device" \ + "/dev/$devname" $DEVICE_TYPE_DISK 1 \ + "" "" "" "" "$capacity" + retval=$? + + # Detect ``dangerously dedicated'' filesystems (errors ignored) + f_device_probe_disk_fs device "$devname" "$capacity" && + retval=$SUCCESS + + return $retval + ;; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404232204.s3NM45NQ064960>