Skip site navigation (1)Skip section navigation (2)
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>