aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Guest <[email protected]>2017-09-28 06:39:47 +1300
committerBrian Behlendorf <[email protected]>2017-09-27 10:39:47 -0700
commit269db7a4b3ef2bc14f3c2cf95f050479cbd69e72 (patch)
tree0db5488ac7ecbc7ca979eea49b600b6dba94a7d7
parent0c484ab5677ffaa3e0e2371456deb4f8eb370388 (diff)
vdev_id: extension for new scsi topology
On systems with SCSI rather than SAS disk topology, this change enables the vdev_id script to match against the block device path, and therefore create a vdev alias in /dev/disk/by-vdev. Reviewed-by: Tony Hutter <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Simon Guest <[email protected]> Closes #6592
-rwxr-xr-xcmd/vdev_id/vdev_id118
-rw-r--r--etc/zfs/Makefile.am3
-rw-r--r--etc/zfs/vdev_id.conf.scsi.example9
3 files changed, 127 insertions, 3 deletions
diff --git a/cmd/vdev_id/vdev_id b/cmd/vdev_id/vdev_id
index a2cba086e..9fa2d672c 100755
--- a/cmd/vdev_id/vdev_id
+++ b/cmd/vdev_id/vdev_id
@@ -100,7 +100,7 @@ usage() {
cat << EOF
Usage: vdev_id [-h]
vdev_id <-d device> [-c config_file] [-p phys_per_port]
- [-g sas_direct|sas_switch] [-m]
+ [-g sas_direct|sas_switch|scsi] [-m]
-c specify name of alernate config file [default=$CONFIG]
-d specify basename of device (i.e. sda)
@@ -135,7 +135,7 @@ map_channel() {
MAPPED_CHAN=`awk "\\$1 == \"channel\" && \\$2 == ${PORT} \
{ print \\$3; exit }" $CONFIG`
;;
- "sas_direct")
+ "sas_direct"|"scsi")
MAPPED_CHAN=`awk "\\$1 == \"channel\" && \
\\$2 == \"${PCI_ID}\" && \\$3 == ${PORT} \
{ print \\$4; exit }" $CONFIG`
@@ -289,6 +289,117 @@ sas_handler() {
echo ${CHAN}${SLOT}${PART}
}
+scsi_handler() {
+ if [ -z "$FIRST_BAY_NUMBER" ] ; then
+ FIRST_BAY_NUMBER=`awk "\\$1 == \"first_bay_number\" \
+ {print \\$2; exit}" $CONFIG`
+ fi
+ FIRST_BAY_NUMBER=${FIRST_BAY_NUMBER:-0}
+
+ if [ -z "$PHYS_PER_PORT" ] ; then
+ PHYS_PER_PORT=`awk "\\$1 == \"phys_per_port\" \
+ {print \\$2; exit}" $CONFIG`
+ fi
+ PHYS_PER_PORT=${PHYS_PER_PORT:-4}
+ if ! echo $PHYS_PER_PORT | grep -q -E '^[0-9]+$' ; then
+ echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric"
+ exit 1
+ fi
+
+ if [ -z "$MULTIPATH_MODE" ] ; then
+ MULTIPATH_MODE=`awk "\\$1 == \"multipath\" \
+ {print \\$2; exit}" $CONFIG`
+ fi
+
+ # Use first running component device if we're handling a dm-mpath device
+ if [ "$MULTIPATH_MODE" = "yes" ] ; then
+ # If udev didn't tell us the UUID via DM_NAME, check /dev/mapper
+ if [ -z "$DM_NAME" ] ; then
+ DM_NAME=`ls -l --full-time /dev/mapper |
+ awk "/\/$DEV$/{print \\$9}"`
+ fi
+
+ # For raw disks udev exports DEVTYPE=partition when
+ # handling partitions, and the rules can be written to
+ # take advantage of this to append a -part suffix. For
+ # dm devices we get DEVTYPE=disk even for partitions so
+ # we have to append the -part suffix directly in the
+ # helper.
+ if [ "$DEVTYPE" != "partition" ] ; then
+ PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'`
+ fi
+
+ # Strip off partition information.
+ DM_NAME=`echo $DM_NAME | sed 's/p[0-9][0-9]*$//'`
+ if [ -z "$DM_NAME" ] ; then
+ return
+ fi
+
+ # Get the raw scsi device name from multipath -ll. Strip off
+ # leading pipe symbols to make field numbering consistent.
+ DEV=`multipath -ll $DM_NAME |
+ awk '/running/{gsub("^[|]"," "); print $3 ; exit}'`
+ if [ -z "$DEV" ] ; then
+ return
+ fi
+ fi
+
+ if echo $DEV | grep -q ^/devices/ ; then
+ sys_path=$DEV
+ else
+ sys_path=`udevadm info -q path -p /sys/block/$DEV 2>/dev/null`
+ fi
+
+ # expect sys_path like this, for example:
+ # /devices/pci0000:00/0000:00:0b.0/0000:09:00.0/0000:0a:05.0/0000:0c:00.0/host3/target3:1:0/3:1:0:21/block/sdv
+
+ # Use positional parameters as an ad-hoc array
+ set -- $(echo "$sys_path" | tr / ' ')
+ num_dirs=$#
+ scsi_host_dir="/sys"
+
+ # Get path up to /sys/.../hostX
+ i=1
+ while [ $i -le $num_dirs ] ; do
+ d=$(eval echo \${$i})
+ scsi_host_dir="$scsi_host_dir/$d"
+ echo $d | grep -q -E '^host[0-9]+$' && break
+ i=$(($i + 1))
+ done
+
+ if [ $i = $num_dirs ] ; then
+ return
+ fi
+
+ PCI_ID=$(eval echo \${$(($i -1))} | awk -F: '{print $2":"$3}')
+
+ # In scsi mode, the directory two levels beneath
+ # /sys/.../hostX reveals the port and slot.
+ port_dir=$scsi_host_dir
+ j=$(($i + 2))
+
+ i=$(($i + 1))
+ while [ $i -le $j ] ; do
+ port_dir="$port_dir/$(eval echo \${$i})"
+ i=$(($i + 1))
+ done
+
+ set -- $(echo $port_dir | sed -e 's/^.*:\([^:]*\):\([^:]*\)$/\1 \2/')
+ PORT=$1
+ SLOT=$(($2 + $FIRST_BAY_NUMBER))
+
+ if [ -z "$SLOT" ] ; then
+ return
+ fi
+
+ CHAN=`map_channel $PCI_ID $PORT`
+ SLOT=`map_slot $SLOT $CHAN`
+ if [ -z "$CHAN" ] ; then
+ return
+ fi
+ echo ${CHAN}${SLOT}${PART}
+}
+
alias_handler () {
# Special handling is needed to correctly append a -part suffix
# to partitions of device mapper devices. The DEVTYPE attribute
@@ -394,6 +505,9 @@ if [ -z "$ID_VDEV" ] ; then
sas_direct|sas_switch)
ID_VDEV=`sas_handler`
;;
+ scsi)
+ ID_VDEV=`scsi_handler`
+ ;;
*)
echo "Error: unknown topology $TOPOLOGY"
exit 1
diff --git a/etc/zfs/Makefile.am b/etc/zfs/Makefile.am
index ff35469fe..52f6634df 100644
--- a/etc/zfs/Makefile.am
+++ b/etc/zfs/Makefile.am
@@ -4,6 +4,7 @@ pkgsysconf_DATA = \
vdev_id.conf.alias.example \
vdev_id.conf.sas_direct.example \
vdev_id.conf.sas_switch.example \
- vdev_id.conf.multipath.example
+ vdev_id.conf.multipath.example \
+ vdev_id.conf.scsi.example
EXTRA_DIST = $(pkgsysconf_DATA)
diff --git a/etc/zfs/vdev_id.conf.scsi.example b/etc/zfs/vdev_id.conf.scsi.example
new file mode 100644
index 000000000..b8c0ab2bf
--- /dev/null
+++ b/etc/zfs/vdev_id.conf.scsi.example
@@ -0,0 +1,9 @@
+multipath no
+topology scsi
+phys_per_port 1
+# Usually scsi disks are numbered from 0, but this can be offset, to
+# match the physical bay numbers, as follows:
+first_bay_number 1
+
+# PCI_ID HBA PORT CHANNEL NAME
+channel 0c:00.0 0 Y