Add enclosure_symlinks option to vdev_id

Add an 'enclosure_symlinks' option to vdev_id.conf.  This creates
consistently named symlinks to the enclosure devices (/dev/sg*) based
off the configuration in vdev_id.conf.  The enclosure symlinks show
up in /dev/by-enclosure/<prefix>-<channel><num>.  The links make it
make it easy to run sg_ses on a particular enclosure device.  The
enclosure links are created in addition to the normal
/dev/disk/by-vdev links.

'enclosure_symlinks' is only valid in sas_direct configurations.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Simon Guest <simon.guest@tesujimath.org>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes #8194
This commit is contained in:
Tony Hutter 2018-12-14 17:27:49 -08:00 committed by Brian Behlendorf
parent 7c46894081
commit c66401fae0
4 changed files with 112 additions and 3 deletions

View File

@ -104,6 +104,7 @@ Usage: vdev_id [-h]
-c specify name of alernate config file [default=$CONFIG] -c specify name of alernate config file [default=$CONFIG]
-d specify basename of device (i.e. sda) -d specify basename of device (i.e. sda)
-e Create enclose device symlinks only (/dev/by-enclosure)
-g Storage network topology [default="$TOPOLOGY"] -g Storage network topology [default="$TOPOLOGY"]
-m Run in multipath mode -m Run in multipath mode
-p number of phy's per switch port [default=$PHYS_PER_PORT] -p number of phy's per switch port [default=$PHYS_PER_PORT]
@ -417,6 +418,45 @@ scsi_handler() {
echo ${CHAN}${SLOT}${PART} echo ${CHAN}${SLOT}${PART}
} }
# Figure out the name for the enclosure symlink
enclosure_handler () {
# We get all the info we need from udev's DEVPATH variable:
#
# DEVPATH=/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/subsystem/devices/0:0:0:0/scsi_generic/sg0
# Get the enclosure ID ("0:0:0:0")
ENC=$(basename $(readlink -m "/sys/$DEVPATH/../.."))
if [ ! -d /sys/class/enclosure/$ENC ] ; then
# Not an enclosure, bail out
return
fi
# Get the long sysfs device path to our enclosure. Looks like:
# /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0/ ... /enclosure/0:0:0:0
ENC_DEVICE=$(readlink /sys/class/enclosure/$ENC)
# Grab the full path to the hosts port dir:
# /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0
PORT_DIR=$(echo $ENC_DEVICE | grep -Eo '.+host[0-9]+/port-[0-9]+:[0-9]+')
# Get the port number
PORT_ID=$(echo $PORT_DIR | grep -Eo "[0-9]+$")
# The PCI directory is two directories up from the port directory
# /sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0
PCI_ID_LONG=$(basename $(readlink -m "/sys/$PORT_DIR/../.."))
# Strip down the PCI address from 0000:05:00.0 to 05:00.0
PCI_ID=$(echo "$PCI_ID_LONG" | sed -r 's/^[0-9]+://g')
# Name our device according to vdev_id.conf (like "L0" or "U1").
NAME=$(awk "/channel/{if (\$1 == \"channel\" && \$2 == \"$PCI_ID\" && \
\$3 == \"$PORT_ID\") {print \$4int(count[\$4])}; count[\$4]++}" $CONFIG)
echo "${NAME}"
}
alias_handler () { alias_handler () {
# Special handling is needed to correctly append a -part suffix # Special handling is needed to correctly append a -part suffix
# to partitions of device mapper devices. The DEVTYPE attribute # to partitions of device mapper devices. The DEVTYPE attribute
@ -472,7 +512,7 @@ alias_handler () {
done done
} }
while getopts 'c:d:g:mp:h' OPTION; do while getopts 'c:d:eg:mp:h' OPTION; do
case ${OPTION} in case ${OPTION} in
c) c)
CONFIG=${OPTARG} CONFIG=${OPTARG}
@ -480,6 +520,16 @@ while getopts 'c:d:g:mp:h' OPTION; do
d) d)
DEV=${OPTARG} DEV=${OPTARG}
;; ;;
e)
# When udev sees a scsi_generic device, it calls this script with -e to
# create the enclosure device symlinks only. We also need
# "enclosure_symlinks yes" set in vdev_id.config to actually create the
# symlink.
ENCLOSURE_MODE=$(awk '{if ($1 == "enclosure_symlinks") print $2}' $CONFIG)
if [ "$ENCLOSURE_MODE" != "yes" ] ; then
exit 0
fi
;;
g) g)
TOPOLOGY=$OPTARG TOPOLOGY=$OPTARG
;; ;;
@ -499,7 +549,7 @@ if [ ! -r $CONFIG ] ; then
exit 0 exit 0
fi fi
if [ -z "$DEV" ] ; then if [ -z "$DEV" -a -z "$ENCLOSURE_MODE" ] ; then
echo "Error: missing required option -d" echo "Error: missing required option -d"
exit 1 exit 1
fi fi
@ -512,12 +562,30 @@ if [ -z "$BAY" ] ; then
BAY=`awk "\\$1 == \"slot\" {print \\$2; exit}" $CONFIG` BAY=`awk "\\$1 == \"slot\" {print \\$2; exit}" $CONFIG`
fi fi
TOPOLOGY=${TOPOLOGY:-sas_direct}
# Should we create /dev/by-enclosure symlinks?
if [ "$ENCLOSURE_MODE" = "yes" -a "$TOPOLOGY" = "sas_direct" ] ; then
ID_ENCLOSURE=$(enclosure_handler)
if [ -z "$ID_ENCLOSURE" ] ; then
exit 0
fi
# Just create the symlinks to the enclosure devices and then exit.
ENCLOSURE_PREFIX=$(awk '/enclosure_symlinks_prefix/{print $2}' $CONFIG)
if [ -z "$ENCLOSURE_PREFIX" ] ; then
ENCLOSURE_PREFIX="enc"
fi
echo "ID_ENCLOSURE=$ID_ENCLOSURE"
echo "ID_ENCLOSURE_PATH=by-enclosure/$ENCLOSURE_PREFIX-$ID_ENCLOSURE"
exit 0
fi
# First check if an alias was defined for this device. # First check if an alias was defined for this device.
ID_VDEV=`alias_handler` ID_VDEV=`alias_handler`
if [ -z "$ID_VDEV" ] ; then if [ -z "$ID_VDEV" ] ; then
BAY=${BAY:-bay} BAY=${BAY:-bay}
TOPOLOGY=${TOPOLOGY:-sas_direct}
case $TOPOLOGY in case $TOPOLOGY in
sas_direct|sas_switch) sas_direct|sas_switch)
ID_VDEV=`sas_handler` ID_VDEV=`sas_handler`

View File

@ -2,6 +2,9 @@ multipath no
topology sas_direct topology sas_direct
phys_per_port 4 phys_per_port 4
# Additionally create /dev/by-enclousure/ symlinks for enclosure devices
enclosure_symlinks yes
# PCI_ID HBA PORT CHANNEL NAME # PCI_ID HBA PORT CHANNEL NAME
channel 85:00.0 1 A channel 85:00.0 1 A
channel 85:00.0 0 B channel 85:00.0 0 B

View File

@ -38,6 +38,19 @@ defined by udev. This may be an absolute path or the base filename.
Maps a physical path to a channel name (typically representing a single Maps a physical path to a channel name (typically representing a single
disk enclosure). disk enclosure).
.TP
\fIenclosure_symlinks\fR <yes|no>
Additionally create /dev/by-enclosure symlinks to the disk enclosure
sg devices using the naming scheme from from vdev_id.conf.
\fIenclosure_symlinks\fR is only allowed for sas_direct mode.
.TP
\fIenclosure_symlinks_prefix\fR <prefix>
Specify the prefix for the enclosure symlinks in the form of:
/dev/by-enclosure/<prefix>-<channel><num>
Defaults to "enc" if not specified.
.TP
\fIpci_slot\fR - specifies the PCI SLOT of the HBA \fIpci_slot\fR - specifies the PCI SLOT of the HBA
hosting the disk enclosure being mapped, as found in the output of hosting the disk enclosure being mapped, as found in the output of
.BR lspci (8). .BR lspci (8).
@ -169,6 +182,27 @@ definitions - one per physical path.
channel 86:00.0 0 B channel 86:00.0 0 B
.fi .fi
.P .P
A configuration with enclosure_symlinks enabled.
.P
.nf
multipath yes
enclosure_symlinks yes
# PCI_ID HBA PORT CHANNEL NAME
channel 05:00.0 1 U
channel 05:00.0 0 L
channel 06:00.0 1 U
channel 06:00.0 0 L
.fi
In addition to the disks symlinks, this configuration will create:
.P
.nf
/dev/by-enclosure/enc-L0
/dev/by-enclosure/enc-L1
/dev/by-enclosure/enc-U0
/dev/by-enclosure/enc-U1
.fi
.P
A configuration using device link aliases. A configuration using device link aliases.
.P .P
.nf .nf

View File

@ -8,3 +8,7 @@ ENV{DEVTYPE}=="partition", IMPORT{program}="@udevdir@/vdev_id -d %k"
KERNEL=="*[!0-9]", ENV{SUBSYSTEM}=="block", ENV{ID_VDEV}=="?*", SYMLINK+="$env{ID_VDEV_PATH}" KERNEL=="*[!0-9]", ENV{SUBSYSTEM}=="block", ENV{ID_VDEV}=="?*", SYMLINK+="$env{ID_VDEV_PATH}"
KERNEL=="*[0-9]", ENV{SUBSYSTEM}=="block", ENV{DEVTYPE}=="partition", ENV{ID_VDEV}=="?*", SYMLINK+="$env{ID_VDEV_PATH}-part%n" KERNEL=="*[0-9]", ENV{SUBSYSTEM}=="block", ENV{DEVTYPE}=="partition", ENV{ID_VDEV}=="?*", SYMLINK+="$env{ID_VDEV_PATH}-part%n"
KERNEL=="dm-[0-9]*", ENV{SUBSYSTEM}=="block", ENV{ID_VDEV}=="?*", SYMLINK+="$env{ID_VDEV_PATH}" KERNEL=="dm-[0-9]*", ENV{SUBSYSTEM}=="block", ENV{ID_VDEV}=="?*", SYMLINK+="$env{ID_VDEV_PATH}"
# Enclosure device symlink rules
ENV{SUBSYSTEM}=="scsi_generic", IMPORT{program}="@udevdir@/vdev_id -e"
ENV{SUBSYSTEM}=="scsi_generic", ENV{ID_ENCLOSURE}=="?*", SYMLINK+="$env{ID_ENCLOSURE_PATH}"