summaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/Makefile.am2
-rw-r--r--cmd/Makefile.in2
-rw-r--r--cmd/sas_switch_id/Makefile.am1
-rwxr-xr-xcmd/sas_switch_id/sas_switch_id96
-rw-r--r--cmd/vdev_id/Makefile.am1
-rw-r--r--cmd/vdev_id/Makefile.in (renamed from cmd/sas_switch_id/Makefile.in)8
-rwxr-xr-xcmd/vdev_id/vdev_id291
-rw-r--r--cmd/zpool/zpool_vdev.c6
8 files changed, 301 insertions, 106 deletions
diff --git a/cmd/Makefile.am b/cmd/Makefile.am
index de2db4030..5c8afb4e7 100644
--- a/cmd/Makefile.am
+++ b/cmd/Makefile.am
@@ -1,2 +1,2 @@
SUBDIRS = zfs zpool zdb zinject ztest zpios mount_zfs
-SUBDIRS += zpool_layout zvol_id zpool_id sas_switch_id
+SUBDIRS += zpool_layout zvol_id zpool_id vdev_id
diff --git a/cmd/Makefile.in b/cmd/Makefile.in
index 0efcdb4a2..ffc2834f9 100644
--- a/cmd/Makefile.in
+++ b/cmd/Makefile.in
@@ -329,7 +329,7 @@ top_srcdir = @top_srcdir@
udevdir = @udevdir@
udevruledir = @udevruledir@
SUBDIRS = zfs zpool zdb zinject ztest zpios mount_zfs zpool_layout \
- zvol_id zpool_id sas_switch_id
+ zvol_id zpool_id vdev_id
all: all-recursive
.SUFFIXES:
diff --git a/cmd/sas_switch_id/Makefile.am b/cmd/sas_switch_id/Makefile.am
deleted file mode 100644
index b666bea0a..000000000
--- a/cmd/sas_switch_id/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-dist_udev_SCRIPTS = sas_switch_id
diff --git a/cmd/sas_switch_id/sas_switch_id b/cmd/sas_switch_id/sas_switch_id
deleted file mode 100755
index ecaabc028..000000000
--- a/cmd/sas_switch_id/sas_switch_id
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/sh
-#
-# sas_switch_id
-#
-# Callout script for multipathd to obtain disk UUIDs. Combine the UUID
-# from the scsi_id program with the SAS switch port number and enclosure
-# bay number, if available. This naming convention enables easier
-# identification of the physical drive location when multiple disk
-# enclosures are accessed via a SAS switch. For other storage
-# topologies just return the undecorated UUID of the drive.
-
-PHYS_PER_PORT=4
-DEV=
-
-usage() {
- cat << EOF
-Usage: sas_switch_id [-d disk] [-p phys_per_port]
- -d Basename of the disk device [default=none]
- -p Number of PHYs per switch port [default=${PHYS_PER_PORT}]
- -h Show this message
-EOF
- exit 0
-}
-
-while getopts 'd:p:h' OPTION; do
- case ${OPTION} in
- d)
- DEV=${OPTARG}
- ;;
- p)
- PHYS_PER_PORT=${OPTARG}
- ;;
- h)
- usage
- ;;
- esac
-done
-
-if [ -z "$DEV" ] ; then
- echo "Error: missing required option -d"
- exit 1
-fi
-
-UUID=`/lib/udev/scsi_id --whitelisted --device=/dev/$DEV`
-if [ $? != 0 -o -z "$UUID" ] ; then
- exit 1
-fi
-sys_path=`udevadm info -q path -p /sys/block/$DEV`
-dirs=(`echo "$sys_path" | tr / ' '`)
-switch_port_dir="/sys"
-
-# Get path up to /sys/.../hostX
-for (( i=0; i<${#dirs[*]}; i++ )); do
- d=${dirs[$i]}
- switch_port_dir=$switch_port_dir/$d
- echo $d | egrep -q -e '^host[0-9]+$' && break
-done
-
-if [ $i = ${#dirs[*]} ] ; then
- echo $UUID
- exit 0
-fi
-
-# The directory three levels beneath /sys/.../hostX contains
-# symlinks to phy devices that reveal the switch port number.
-# Lowest phy number is $PHYS_PER_PORT*switch_port_number.
-for (( j=(($i+1)) ; j<(($i+4)); j++ )); do
- switch_port_dir=$switch_port_dir/${dirs[$j]}
-done
-pushd $switch_port_dir > /dev/null
-PHY=`ls -d phy* 2>/dev/null | head -1 | awk -F: '{print $NF}'`
-PORT=$(( $PHY / $PHYS_PER_PORT ))
-popd > /dev/null
-if [ -z "$PHY" ] ; then
- echo $UUID
- exit 0
-fi
-
-# Look in /sys/.../sas_device/end_device-X for the bay_identifier
-# attribute.
-end_device_dir=$switch_port_dir
-for (( k=$j ; k<${#dirs[*]} ; k++ )); do
- d=${dirs[$k]}
- end_device_dir=$end_device_dir/$d
- if echo $d | egrep -q -e '^end_device' ; then
- end_device_dir=$end_device_dir/sas_device/$d
- break
- fi
-done
-SLOT=`cat $end_device_dir/bay_identifier 2>/dev/null`
-if [ -z "$SLOT" ] ; then
- echo $UUID
- exit 0
-fi
-
-echo "$UUID-switch-port:$PORT-slot:$SLOT"
diff --git a/cmd/vdev_id/Makefile.am b/cmd/vdev_id/Makefile.am
new file mode 100644
index 000000000..fb815faad
--- /dev/null
+++ b/cmd/vdev_id/Makefile.am
@@ -0,0 +1 @@
+dist_udev_SCRIPTS = vdev_id
diff --git a/cmd/sas_switch_id/Makefile.in b/cmd/vdev_id/Makefile.in
index 12be6784e..8f3b4ae6a 100644
--- a/cmd/sas_switch_id/Makefile.in
+++ b/cmd/vdev_id/Makefile.in
@@ -35,7 +35,7 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
-subdir = cmd/sas_switch_id
+subdir = cmd/vdev_id
DIST_COMMON = $(dist_udev_SCRIPTS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -313,7 +313,7 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
udevdir = @udevdir@
udevruledir = @udevruledir@
-dist_udev_SCRIPTS = sas_switch_id
+dist_udev_SCRIPTS = vdev_id
all: all-am
.SUFFIXES:
@@ -326,9 +326,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cmd/sas_switch_id/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cmd/vdev_id/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu cmd/sas_switch_id/Makefile
+ $(AUTOMAKE) --gnu cmd/vdev_id/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/cmd/vdev_id/vdev_id b/cmd/vdev_id/vdev_id
new file mode 100755
index 000000000..d2781972f
--- /dev/null
+++ b/cmd/vdev_id/vdev_id
@@ -0,0 +1,291 @@
+#!/bin/bash
+#
+# vdev_id: udev helper to generate user-friendly names for JBOD disks
+#
+# This script parses the file /etc/zfs/vdev_id.conf to map a
+# physical path in a storage topology to a channel name. The
+# channel name is combined with a disk enclosure slot number to
+# create an alias that reflects the physical location of the drive.
+# This is particularly helpful when it comes to tasks like replacing
+# failed drives. Slot numbers may also be re-mapped in case the
+# default numbering is unsatisfactory. The drive aliases will be
+# created as symbolic links in /dev/disk/by-vdev.
+#
+# The only currently supported topologies are sas_direct and
+# sas_switch. A multipath mode is supported in which dm-mpath
+# devices are handled by examining the first-listed running
+# component disk. In multipath mode the configuration file
+# should contain a channel definition with the same name for
+# each path to a given enclosure.
+
+#
+# Some example configuration files are given below.
+
+# #
+# # Example vdev_id.conf - sas_direct.
+# #
+#
+# multipath no
+# topology sas_direct
+# phys_per_port 4
+#
+# # PCI_ID HBA PORT CHANNEL NAME
+# channel 85:00.0 1 A
+# channel 85:00.0 0 B
+# channel 86:00.0 1 C
+# channel 86:00.0 0 D
+#
+# # Linux Mapped
+# # Slot Slot
+# slot 1 7
+# slot 2 10
+# slot 3 3
+# slot 4 6
+# slot 5 2
+# slot 6 8
+# slot 7 1
+# slot 8 4
+# slot 9 9
+# slot 10 5
+
+# #
+# # Example vdev_id.conf - sas_switch
+# #
+#
+# topology sas_switch
+#
+# # SWITCH PORT CHANNEL NAME
+# channel 1 A
+# channel 2 B
+# channel 3 C
+# channel 4 D
+
+# #
+# # Example vdev_id.conf - multipath
+# #
+#
+# multipath yes
+#
+# # PCI_ID HBA PORT CHANNEL NAME
+# channel 85:00.0 1 A
+# channel 85:00.0 0 B
+# channel 86:00.0 1 A
+# channel 86:00.0 0 B
+
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+CONFIG=/etc/zfs/vdev_id.conf
+PHYS_PER_PORT=
+DEV=
+SLOT_MAP=
+CHANNEL_MAP=
+MULTIPATH=
+TOPOLOGY=
+declare -i i j
+
+usage() {
+ cat << EOF
+Usage: vdev_id [-h]
+ vdev_id <-d device> [-c config_file] [-p phys_per_port]
+ [-g sas_direct|sas_switch] [-m]
+
+ -c specify name of alernate config file [default=$CONFIG]
+ -d specify basename of device (i.e. sda)
+ -g Storage network topology [default="$TOPOLOGY"]
+ -m Run in multipath mode
+ -p number of phy's per switch port [default=$PHYS_PER_PORT]
+ -h show this summary
+EOF
+ exit 0
+}
+
+map_slot() {
+ local LINUX_SLOT=$1
+ local MAPPED_SLOT=
+
+ MAPPED_SLOT=`awk "/^slot / && \\$2 == ${LINUX_SLOT} \
+ { print \\$3; exit }" $CONFIG`
+ if [ -z "$MAPPED_SLOT" ] ; then
+ MAPPED_SLOT=$LINUX_SLOT
+ fi
+ printf "%d" ${MAPPED_SLOT}
+}
+
+map_channel() {
+ local MAPPED_CHAN=
+ local PCI_ID=$1
+ local PORT=$2
+
+ case $TOPOLOGY in
+ "sas_switch")
+ MAPPED_CHAN=`awk "/^channel / && \\$2 == ${PORT} \
+ { print \\$3; exit }" $CONFIG`
+ ;;
+ "sas_direct")
+ MAPPED_CHAN=`awk "/^channel / && \\$2 == \"${PCI_ID}\" && \
+ \\$3 == ${PORT} { print \\$4; exit }" \
+ $CONFIG`
+ ;;
+ esac
+ printf "%s" ${MAPPED_CHAN}
+}
+
+while getopts 'c:s:d:g:mp:h' OPTION; do
+ case ${OPTION} in
+ c)
+ CONFIG=`readlink -e ${OPTARG}`
+ ;;
+ d)
+ DEV=${OPTARG}
+ ;;
+ g)
+ TOPOLOGY=$OPTARG
+ ;;
+ p)
+ PHYS_PER_PORT=${OPTARG}
+ ;;
+ m)
+ MULTIPATH_MODE=yes
+ ;;
+ s)
+ SLOT_MAP=`readlink -e ${OPTARG}`
+ if [ ! -r $SLOT_MAP ] ; then
+ echo "Error: $SLOT_MAP is nonexistant or unreadable"
+ exit 1
+ fi
+ ;;
+ h)
+ usage
+ ;;
+ esac
+done
+
+if [ ! -r $CONFIG ] ; then
+ exit 0
+fi
+
+if [ -z "$DEV" ] ; then
+ echo "Error: missing required option -d"
+ exit 1
+fi
+
+if [ -z "$TOPOLOGY" ] ; then
+ TOPOLOGY=`awk "/^topology /{print \\$2; exit}" $CONFIG`
+fi
+TOPOLOGY=${TOPOLOGY:-sas_direct}
+case $TOPOLOGY in
+ sas_direct|sas_switch)
+ ;;
+ *)
+ echo "Error: unknown topology $TOPOLOGY"
+ exit 1
+ ;;
+esac
+
+if [ -z "$PHYS_PER_PORT" ] ; then
+ PHYS_PER_PORT=`awk "/^phys_per_port /{print \\$2; exit}" $CONFIG`
+fi
+PHYS_PER_PORT=${PHYS_PER_PORT:-4}
+if ! echo $PHYS_PER_PORT | egrep -q '^[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 "/^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, find it in /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
+ exit 0
+ fi
+
+ # Get the raw scsi device name from multipath -l.
+ DEV=`multipath -l $DM_NAME |awk '/running/{print $3 ; exit}'`
+ if [ -z "$DEV" ] ; then
+ exit 0
+ 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
+
+dirs=(`echo "$sys_path" | tr / ' '`)
+scsi_host_dir="/sys"
+
+# Get path up to /sys/.../hostX
+for (( i=0; i<${#dirs[*]}; i++ )); do
+ d=${dirs[$i]}
+ scsi_host_dir="$scsi_host_dir/$d"
+ echo $d | egrep -q -e '^host[0-9]+$' && break
+done
+
+if [ $i = ${#dirs[*]} ] ; then
+ exit 0
+fi
+
+PCI_ID=`echo ${dirs[$(( $i - 1 ))]} | awk -F: '{print $2":"$3}'`
+
+# In sas_switch mode, the directory three levels beneath /sys/.../hostX
+# contains symlinks to phy devices that reveal the switch port number. In
+# sas_direct mode, the phy links one directory down reveal the HBA port.
+port_dir=$scsi_host_dir
+case $TOPOLOGY in
+ "sas_switch") j=$(($i+4)) ;;
+ "sas_direct") j=$(($i + 1)) ;;
+esac
+for (( i++; i<=$j; i++ )); do
+ port_dir="$port_dir/${dirs[$i]}"
+done
+
+PHY=`ls -d $port_dir/phy* 2>/dev/null | head -1 | awk -F: '{print $NF}'`
+if [ -z "$PHY" ] ; then
+ exit 0
+fi
+PORT=$(( $PHY / $PHYS_PER_PORT ))
+
+# Look in /sys/.../sas_device/end_device-X for the bay_identifier
+# attribute.
+end_device_dir=$port_dir
+for (( ; i<${#dirs[*]} ; i++ )); do
+ d=${dirs[$i]}
+ end_device_dir="$end_device_dir/$d"
+ if echo $d | egrep -q -e '^end_device' ; then
+ end_device_dir="$end_device_dir/sas_device/$d"
+ break
+ fi
+done
+
+SLOT=`cat $end_device_dir/bay_identifier 2>/dev/null`
+if [ -z "$SLOT" ] ; then
+ exit 0
+fi
+
+SLOT=`map_slot $SLOT`
+CHAN=`map_channel $PCI_ID $PORT`
+if [ -z "$CHAN" ] ; then
+ exit 0
+fi
+ID_VDEV=${CHAN}${SLOT}${PART}
+
+echo "ID_VDEV=${ID_VDEV}"
+echo "ID_VDEV_PATH=disk/by-vdev/${ID_VDEV}"
diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c
index a65847038..8c4fadebd 100644
--- a/cmd/zpool/zpool_vdev.c
+++ b/cmd/zpool/zpool_vdev.c
@@ -367,9 +367,9 @@ is_whole_disk(const char *path)
/*
* This may be a shorthand device path or it could be total gibberish.
* Check to see if it's a known device in /dev/, /dev/disk/by-id,
- * /dev/disk/by-label, /dev/disk/by-path, /dev/disk/by-uuid, or
- * /dev/disk/zpool/. As part of this check, see if we've been given
- * an entire disk (minus the slice number).
+ * /dev/disk/by-label, /dev/disk/by-path, /dev/disk/by-uuid,
+ * /dev/disk/by-vdev, or /dev/disk/zpool/. As part of this check, see
+ * if we've been given an entire disk (minus the slice number).
*/
static int
is_shorthand_path(const char *arg, char *path,