]> granicus.if.org Git - zfs/commitdiff
Add enclosure_symlinks option to vdev_id
authorTony Hutter <hutter2@llnl.gov>
Sat, 15 Dec 2018 01:27:49 +0000 (17:27 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Sat, 15 Dec 2018 01:27:49 +0000 (17:27 -0800)
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

cmd/vdev_id/vdev_id
etc/zfs/vdev_id.conf.sas_direct.example
man/man5/vdev_id.conf.5
udev/rules.d/69-vdev.rules.in

index 4c7b270a85442ce23787d7359af2e1b81d7fa54f..3796ab4885d876ae76dbfa1eaeb76d49b267d99c 100755 (executable)
@@ -104,6 +104,7 @@ Usage: vdev_id [-h]
 
   -c    specify name of alernate config file [default=$CONFIG]
   -d    specify basename of device (i.e. sda)
+  -e    Create enclose device symlinks only (/dev/by-enclosure)
   -g    Storage network topology [default="$TOPOLOGY"]
   -m    Run in multipath mode
   -p    number of phy's per switch port [default=$PHYS_PER_PORT]
@@ -417,6 +418,45 @@ scsi_handler() {
        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 () {
        # Special handling is needed to correctly append a -part suffix
        # to partitions of device mapper devices.  The DEVTYPE attribute
@@ -472,7 +512,7 @@ alias_handler () {
        done
 }
 
-while getopts 'c:d:g:mp:h' OPTION; do
+while getopts 'c:d:eg:mp:h' OPTION; do
        case ${OPTION} in
        c)
                CONFIG=${OPTARG}
@@ -480,6 +520,16 @@ while getopts 'c:d:g:mp:h' OPTION; do
        d)
                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)
                TOPOLOGY=$OPTARG
                ;;
@@ -499,7 +549,7 @@ if [ ! -r $CONFIG ] ; then
        exit 0
 fi
 
-if [ -z "$DEV" ] ; then
+if [ -z "$DEV" -a -z "$ENCLOSURE_MODE" ] ; then
        echo "Error: missing required option -d"
        exit 1
 fi
@@ -512,12 +562,30 @@ if [ -z "$BAY" ] ; then
        BAY=`awk "\\$1 == \"slot\" {print \\$2; exit}" $CONFIG`
 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.
 ID_VDEV=`alias_handler`
 
 if [ -z "$ID_VDEV" ] ; then
        BAY=${BAY:-bay}
-       TOPOLOGY=${TOPOLOGY:-sas_direct}
        case $TOPOLOGY in
                sas_direct|sas_switch)
                        ID_VDEV=`sas_handler`
index 115ebd8d3b4fc9fa3dcd75e62c8f728a80757c66..0a6f130cb2d908d2462f3f103197e039b5689190 100644 (file)
@@ -2,6 +2,9 @@ multipath     no
 topology      sas_direct
 phys_per_port 4
 
+# Additionally create /dev/by-enclousure/ symlinks for enclosure devices
+enclosure_symlinks     yes
+
 #       PCI_ID  HBA PORT  CHANNEL NAME
 channel 85:00.0 1         A
 channel 85:00.0 0         B
index 50caa92c043e3784b1b5af08dd971d598ed781bf..5b7fbf0cad4906a953e166949eb948e439bef401 100644 (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
 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
 hosting the disk enclosure being mapped, as found in the output of
 .BR lspci (8).
@@ -169,6 +182,27 @@ definitions - one per physical path.
        channel 86:00.0  0         B
 .fi
 .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.
 .P
 .nf
index 2b9e5d600062afbb09c6fb9d59fb932e7a8f2efe..36a1a8ed5451fea4a8879425bd995d116155de15 100644 (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{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}"
+
+# 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}"