1716fd348SMartin Matuska#!/bin/sh 2716fd348SMartin Matuska# 3716fd348SMartin Matuska# vdev_id: udev helper to generate user-friendly names for JBOD disks 4716fd348SMartin Matuska# 5716fd348SMartin Matuska# This script parses the file /etc/zfs/vdev_id.conf to map a 6716fd348SMartin Matuska# physical path in a storage topology to a channel name. The 7716fd348SMartin Matuska# channel name is combined with a disk enclosure slot number to 8716fd348SMartin Matuska# create an alias that reflects the physical location of the drive. 9716fd348SMartin Matuska# This is particularly helpful when it comes to tasks like replacing 10716fd348SMartin Matuska# failed drives. Slot numbers may also be re-mapped in case the 11716fd348SMartin Matuska# default numbering is unsatisfactory. The drive aliases will be 12716fd348SMartin Matuska# created as symbolic links in /dev/disk/by-vdev. 13716fd348SMartin Matuska# 14716fd348SMartin Matuska# The currently supported topologies are sas_direct and sas_switch. 15716fd348SMartin Matuska# A multipath mode is supported in which dm-mpath devices are 16716fd348SMartin Matuska# handled by examining the first-listed running component disk. In 17716fd348SMartin Matuska# multipath mode the configuration file should contain a channel 18716fd348SMartin Matuska# definition with the same name for each path to a given enclosure. 19716fd348SMartin Matuska# 20716fd348SMartin Matuska# The alias keyword provides a simple way to map already-existing 21716fd348SMartin Matuska# device symlinks to more convenient names. It is suitable for 22716fd348SMartin Matuska# small, static configurations or for sites that have some automated 23716fd348SMartin Matuska# way to generate the mapping file. 24716fd348SMartin Matuska# 25716fd348SMartin Matuska# 26716fd348SMartin Matuska# Some example configuration files are given below. 27716fd348SMartin Matuska 28716fd348SMartin Matuska# # 29716fd348SMartin Matuska# # Example vdev_id.conf - sas_direct. 30716fd348SMartin Matuska# # 31716fd348SMartin Matuska# 32716fd348SMartin Matuska# multipath no 33716fd348SMartin Matuska# topology sas_direct 34716fd348SMartin Matuska# phys_per_port 4 35716fd348SMartin Matuska# slot bay 36716fd348SMartin Matuska# 37716fd348SMartin Matuska# # PCI_ID HBA PORT CHANNEL NAME 38716fd348SMartin Matuska# channel 85:00.0 1 A 39716fd348SMartin Matuska# channel 85:00.0 0 B 40716fd348SMartin Matuska# channel 86:00.0 1 C 41716fd348SMartin Matuska# channel 86:00.0 0 D 42716fd348SMartin Matuska# 43716fd348SMartin Matuska# # Custom mapping for Channel A 44716fd348SMartin Matuska# 45716fd348SMartin Matuska# # Linux Mapped 46716fd348SMartin Matuska# # Slot Slot Channel 47716fd348SMartin Matuska# slot 1 7 A 48716fd348SMartin Matuska# slot 2 10 A 49716fd348SMartin Matuska# slot 3 3 A 50716fd348SMartin Matuska# slot 4 6 A 51716fd348SMartin Matuska# 52716fd348SMartin Matuska# # Default mapping for B, C, and D 53716fd348SMartin Matuska# slot 1 4 54716fd348SMartin Matuska# slot 2 2 55716fd348SMartin Matuska# slot 3 1 56716fd348SMartin Matuska# slot 4 3 57716fd348SMartin Matuska 58716fd348SMartin Matuska# # 59716fd348SMartin Matuska# # Example vdev_id.conf - sas_switch 60716fd348SMartin Matuska# # 61716fd348SMartin Matuska# 62716fd348SMartin Matuska# topology sas_switch 63716fd348SMartin Matuska# 64716fd348SMartin Matuska# # SWITCH PORT CHANNEL NAME 65716fd348SMartin Matuska# channel 1 A 66716fd348SMartin Matuska# channel 2 B 67716fd348SMartin Matuska# channel 3 C 68716fd348SMartin Matuska# channel 4 D 69716fd348SMartin Matuska 70716fd348SMartin Matuska# # 71716fd348SMartin Matuska# # Example vdev_id.conf - multipath 72716fd348SMartin Matuska# # 73716fd348SMartin Matuska# 74716fd348SMartin Matuska# multipath yes 75716fd348SMartin Matuska# 76716fd348SMartin Matuska# # PCI_ID HBA PORT CHANNEL NAME 77716fd348SMartin Matuska# channel 85:00.0 1 A 78716fd348SMartin Matuska# channel 85:00.0 0 B 79716fd348SMartin Matuska# channel 86:00.0 1 A 80716fd348SMartin Matuska# channel 86:00.0 0 B 81716fd348SMartin Matuska 82716fd348SMartin Matuska# # 83716fd348SMartin Matuska# # Example vdev_id.conf - multipath / multijbod-daisychaining 84716fd348SMartin Matuska# # 85716fd348SMartin Matuska# 86716fd348SMartin Matuska# multipath yes 87716fd348SMartin Matuska# multijbod yes 88716fd348SMartin Matuska# 89716fd348SMartin Matuska# # PCI_ID HBA PORT CHANNEL NAME 90716fd348SMartin Matuska# channel 85:00.0 1 A 91716fd348SMartin Matuska# channel 85:00.0 0 B 92716fd348SMartin Matuska# channel 86:00.0 1 A 93716fd348SMartin Matuska# channel 86:00.0 0 B 94716fd348SMartin Matuska 95716fd348SMartin Matuska# # 96716fd348SMartin Matuska# # Example vdev_id.conf - multipath / mixed 97716fd348SMartin Matuska# # 98716fd348SMartin Matuska# 99716fd348SMartin Matuska# multipath yes 100716fd348SMartin Matuska# slot mix 101716fd348SMartin Matuska# 102716fd348SMartin Matuska# # PCI_ID HBA PORT CHANNEL NAME 103716fd348SMartin Matuska# channel 85:00.0 3 A 104716fd348SMartin Matuska# channel 85:00.0 2 B 105716fd348SMartin Matuska# channel 86:00.0 3 A 106716fd348SMartin Matuska# channel 86:00.0 2 B 107716fd348SMartin Matuska# channel af:00.0 0 C 108716fd348SMartin Matuska# channel af:00.0 1 C 109716fd348SMartin Matuska 110716fd348SMartin Matuska# # 111716fd348SMartin Matuska# # Example vdev_id.conf - alias 112716fd348SMartin Matuska# # 113716fd348SMartin Matuska# 114716fd348SMartin Matuska# # by-vdev 115716fd348SMartin Matuska# # name fully qualified or base name of device link 116716fd348SMartin Matuska# alias d1 /dev/disk/by-id/wwn-0x5000c5002de3b9ca 117716fd348SMartin Matuska# alias d2 wwn-0x5000c5002def789e 118716fd348SMartin Matuska 119716fd348SMartin MatuskaPATH=/bin:/sbin:/usr/bin:/usr/sbin 120716fd348SMartin MatuskaCONFIG=/etc/zfs/vdev_id.conf 121716fd348SMartin MatuskaPHYS_PER_PORT= 122716fd348SMartin MatuskaDEV= 123716fd348SMartin MatuskaTOPOLOGY= 124716fd348SMartin MatuskaBAY= 125716fd348SMartin MatuskaENCL_ID="" 126716fd348SMartin MatuskaUNIQ_ENCL_ID="" 12787bf66d4SMartin MatuskaZPAD=1 128716fd348SMartin Matuska 129716fd348SMartin Matuskausage() { 130716fd348SMartin Matuska cat << EOF 131716fd348SMartin MatuskaUsage: vdev_id [-h] 132716fd348SMartin Matuska vdev_id <-d device> [-c config_file] [-p phys_per_port] 133716fd348SMartin Matuska [-g sas_direct|sas_switch|scsi] [-m] 134716fd348SMartin Matuska 135716fd348SMartin Matuska -c specify name of an alternative config file [default=$CONFIG] 136716fd348SMartin Matuska -d specify basename of device (i.e. sda) 137716fd348SMartin Matuska -e Create enclose device symlinks only (/dev/by-enclosure) 138716fd348SMartin Matuska -g Storage network topology [default="$TOPOLOGY"] 139716fd348SMartin Matuska -m Run in multipath mode 140716fd348SMartin Matuska -j Run in multijbod mode 141716fd348SMartin Matuska -p number of phy's per switch port [default=$PHYS_PER_PORT] 142716fd348SMartin Matuska -h show this summary 143716fd348SMartin MatuskaEOF 144716fd348SMartin Matuska exit 1 145716fd348SMartin Matuska # exit with error to avoid processing usage message by a udev rule 146716fd348SMartin Matuska} 147716fd348SMartin Matuska 148716fd348SMartin Matuskamap_slot() { 149716fd348SMartin Matuska LINUX_SLOT=$1 150716fd348SMartin Matuska CHANNEL=$2 151716fd348SMartin Matuska 152716fd348SMartin Matuska MAPPED_SLOT=$(awk -v linux_slot="$LINUX_SLOT" -v channel="$CHANNEL" \ 153716fd348SMartin Matuska '$1 == "slot" && $2 == linux_slot && \ 154716fd348SMartin Matuska ($4 ~ "^"channel"$" || $4 ~ /^$/) { print $3; exit}' $CONFIG) 155716fd348SMartin Matuska if [ -z "$MAPPED_SLOT" ] ; then 156716fd348SMartin Matuska MAPPED_SLOT=$LINUX_SLOT 157716fd348SMartin Matuska fi 15887bf66d4SMartin Matuska printf "%0${ZPAD}d" "${MAPPED_SLOT}" 159716fd348SMartin Matuska} 160716fd348SMartin Matuska 161716fd348SMartin Matuskamap_channel() { 162716fd348SMartin Matuska MAPPED_CHAN= 163716fd348SMartin Matuska PCI_ID=$1 164716fd348SMartin Matuska PORT=$2 165716fd348SMartin Matuska 166716fd348SMartin Matuska case $TOPOLOGY in 167716fd348SMartin Matuska "sas_switch") 168716fd348SMartin Matuska MAPPED_CHAN=$(awk -v port="$PORT" \ 169716fd348SMartin Matuska '$1 == "channel" && $2 == port \ 170716fd348SMartin Matuska { print $3; exit }' $CONFIG) 171716fd348SMartin Matuska ;; 172716fd348SMartin Matuska "sas_direct"|"scsi") 173716fd348SMartin Matuska MAPPED_CHAN=$(awk -v pciID="$PCI_ID" -v port="$PORT" \ 174716fd348SMartin Matuska '$1 == "channel" && $2 == pciID && $3 == port \ 175716fd348SMartin Matuska {print $4}' $CONFIG) 176716fd348SMartin Matuska ;; 177716fd348SMartin Matuska esac 178716fd348SMartin Matuska printf "%s" "${MAPPED_CHAN}" 179716fd348SMartin Matuska} 180716fd348SMartin Matuska 181716fd348SMartin Matuskaget_encl_id() { 182716fd348SMartin Matuska set -- $(echo $1) 183716fd348SMartin Matuska count=$# 184716fd348SMartin Matuska 185716fd348SMartin Matuska i=1 186716fd348SMartin Matuska while [ $i -le $count ] ; do 187716fd348SMartin Matuska d=$(eval echo '$'{$i}) 188716fd348SMartin Matuska id=$(cat "/sys/class/enclosure/${d}/id") 189716fd348SMartin Matuska ENCL_ID="${ENCL_ID} $id" 190716fd348SMartin Matuska i=$((i + 1)) 191716fd348SMartin Matuska done 192716fd348SMartin Matuska} 193716fd348SMartin Matuska 194716fd348SMartin Matuskaget_uniq_encl_id() { 195716fd348SMartin Matuska for uuid in ${ENCL_ID}; do 196716fd348SMartin Matuska found=0 197716fd348SMartin Matuska 198716fd348SMartin Matuska for count in ${UNIQ_ENCL_ID}; do 199716fd348SMartin Matuska if [ $count = $uuid ]; then 200716fd348SMartin Matuska found=1 201716fd348SMartin Matuska break 202716fd348SMartin Matuska fi 203716fd348SMartin Matuska done 204716fd348SMartin Matuska 205716fd348SMartin Matuska if [ $found -eq 0 ]; then 206716fd348SMartin Matuska UNIQ_ENCL_ID="${UNIQ_ENCL_ID} $uuid" 207716fd348SMartin Matuska fi 208716fd348SMartin Matuska done 209716fd348SMartin Matuska} 210716fd348SMartin Matuska 211716fd348SMartin Matuska# map_jbod explainer: The bsg driver knows the difference between a SAS 212716fd348SMartin Matuska# expander and fanout expander. Use hostX instance along with top-level 213716fd348SMartin Matuska# (whole enclosure) expander instances in /sys/class/enclosure and 214716fd348SMartin Matuska# matching a field in an array of expanders, using the index of the 215716fd348SMartin Matuska# matched array field as the enclosure instance, thereby making jbod IDs 216716fd348SMartin Matuska# dynamic. Avoids reliance on high overhead userspace commands like 217716fd348SMartin Matuska# multipath and lsscsi and instead uses existing sysfs data. $HOSTCHAN 218716fd348SMartin Matuska# variable derived from devpath gymnastics in sas_handler() function. 219716fd348SMartin Matuskamap_jbod() { 220716fd348SMartin Matuska DEVEXP=$(ls -l "/sys/block/$DEV/device/" | grep enclos | awk -F/ '{print $(NF-1) }') 221716fd348SMartin Matuska DEV=$1 222716fd348SMartin Matuska 223716fd348SMartin Matuska # Use "set --" to create index values (Arrays) 224716fd348SMartin Matuska set -- $(ls -l /sys/class/enclosure | grep -v "^total" | awk '{print $9}') 225716fd348SMartin Matuska # Get count of total elements 226716fd348SMartin Matuska JBOD_COUNT=$# 227716fd348SMartin Matuska JBOD_ITEM=$* 228716fd348SMartin Matuska 229716fd348SMartin Matuska # Build JBODs (enclosure) id from sys/class/enclosure/<dev>/id 230716fd348SMartin Matuska get_encl_id "$JBOD_ITEM" 231716fd348SMartin Matuska # Different expander instances for each paths. 232716fd348SMartin Matuska # Filter out and keep only unique id. 233716fd348SMartin Matuska get_uniq_encl_id 234716fd348SMartin Matuska 235716fd348SMartin Matuska # Identify final 'mapped jbod' 236716fd348SMartin Matuska j=0 237716fd348SMartin Matuska for count in ${UNIQ_ENCL_ID}; do 238716fd348SMartin Matuska i=1 239716fd348SMartin Matuska j=$((j + 1)) 240716fd348SMartin Matuska while [ $i -le $JBOD_COUNT ] ; do 241716fd348SMartin Matuska d=$(eval echo '$'{$i}) 242716fd348SMartin Matuska id=$(cat "/sys/class/enclosure/${d}/id") 243716fd348SMartin Matuska if [ "$d" = "$DEVEXP" ] && [ $id = $count ] ; then 244716fd348SMartin Matuska MAPPED_JBOD=$j 245716fd348SMartin Matuska break 246716fd348SMartin Matuska fi 247716fd348SMartin Matuska i=$((i + 1)) 248716fd348SMartin Matuska done 249716fd348SMartin Matuska done 250716fd348SMartin Matuska 251716fd348SMartin Matuska printf "%d" "${MAPPED_JBOD}" 252716fd348SMartin Matuska} 253716fd348SMartin Matuska 254716fd348SMartin Matuskasas_handler() { 255716fd348SMartin Matuska if [ -z "$PHYS_PER_PORT" ] ; then 256716fd348SMartin Matuska PHYS_PER_PORT=$(awk '$1 == "phys_per_port" \ 257716fd348SMartin Matuska {print $2; exit}' $CONFIG) 258716fd348SMartin Matuska fi 259716fd348SMartin Matuska PHYS_PER_PORT=${PHYS_PER_PORT:-4} 260716fd348SMartin Matuska 261716fd348SMartin Matuska if ! echo "$PHYS_PER_PORT" | grep -q -E '^[0-9]+$' ; then 262716fd348SMartin Matuska echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric" 263716fd348SMartin Matuska exit 1 264716fd348SMartin Matuska fi 265716fd348SMartin Matuska 266716fd348SMartin Matuska if [ -z "$MULTIPATH_MODE" ] ; then 267716fd348SMartin Matuska MULTIPATH_MODE=$(awk '$1 == "multipath" \ 268716fd348SMartin Matuska {print $2; exit}' $CONFIG) 269716fd348SMartin Matuska fi 270716fd348SMartin Matuska 271716fd348SMartin Matuska if [ -z "$MULTIJBOD_MODE" ] ; then 272716fd348SMartin Matuska MULTIJBOD_MODE=$(awk '$1 == "multijbod" \ 273716fd348SMartin Matuska {print $2; exit}' $CONFIG) 274716fd348SMartin Matuska fi 275716fd348SMartin Matuska 276716fd348SMartin Matuska # Use first running component device if we're handling a dm-mpath device 277716fd348SMartin Matuska if [ "$MULTIPATH_MODE" = "yes" ] ; then 278716fd348SMartin Matuska # If udev didn't tell us the UUID via DM_NAME, check /dev/mapper 279716fd348SMartin Matuska if [ -z "$DM_NAME" ] ; then 280716fd348SMartin Matuska DM_NAME=$(ls -l --full-time /dev/mapper | 281716fd348SMartin Matuska grep "$DEV"$ | awk '{print $9}') 282716fd348SMartin Matuska fi 283716fd348SMartin Matuska 284716fd348SMartin Matuska # For raw disks udev exports DEVTYPE=partition when 285716fd348SMartin Matuska # handling partitions, and the rules can be written to 286716fd348SMartin Matuska # take advantage of this to append a -part suffix. For 287716fd348SMartin Matuska # dm devices we get DEVTYPE=disk even for partitions so 288716fd348SMartin Matuska # we have to append the -part suffix directly in the 289716fd348SMartin Matuska # helper. 290716fd348SMartin Matuska if [ "$DEVTYPE" != "partition" ] ; then 291*b1c1ee44SMartin Matuska # WWNs end with number -> p<partition>, alphabet -> <partition> 292*b1c1ee44SMartin Matuska # '3' + (WWN length 16) = 17 293*b1c1ee44SMartin Matuska PART=${DM_NAME:17} 294*b1c1ee44SMartin Matuska if [[ $PART = "p"* ]]; then 295716fd348SMartin Matuska # Match p[number], remove the 'p' and prepend "-part" 296716fd348SMartin Matuska PART=$(echo "$DM_NAME" | 297716fd348SMartin Matuska awk 'match($0,/p[0-9]+$/) {print "-part"substr($0,RSTART+1,RLENGTH-1)}') 298*b1c1ee44SMartin Matuska elif [[ $PART != "" ]]; then 299*b1c1ee44SMartin Matuska PART="-part"${PART} 300*b1c1ee44SMartin Matuska fi 301716fd348SMartin Matuska fi 302716fd348SMartin Matuska 303716fd348SMartin Matuska # Strip off partition information. 304*b1c1ee44SMartin Matuska DM_NAME=${DM_NAME:0:17} 305716fd348SMartin Matuska if [ -z "$DM_NAME" ] ; then 306716fd348SMartin Matuska return 307716fd348SMartin Matuska fi 308716fd348SMartin Matuska 309716fd348SMartin Matuska # Utilize DM device name to gather subordinate block devices 310716fd348SMartin Matuska # using sysfs to avoid userspace utilities 311716fd348SMartin Matuska 312716fd348SMartin Matuska # If our DEVNAME is something like /dev/dm-177, then we may be 313716fd348SMartin Matuska # able to get our DMDEV from it. 314716fd348SMartin Matuska DMDEV=$(echo $DEVNAME | sed 's;/dev/;;g') 315*b1c1ee44SMartin Matuska if [ -n "$DMDEV" ]; then 316*b1c1ee44SMartin Matuska DEV=$(ls /sys/block/$DMDEV/slaves) 317*b1c1ee44SMartin Matuska for elm in "${DEV[@]}"; do 318*b1c1ee44SMartin Matuska if [[ $elm == "dm-"* ]]; then 319*b1c1ee44SMartin Matuska DMDEV=$elm 320*b1c1ee44SMartin Matuska break 321*b1c1ee44SMartin Matuska fi 322*b1c1ee44SMartin Matuska done 323*b1c1ee44SMartin Matuska fi 324*b1c1ee44SMartin Matuska 325716fd348SMartin Matuska if [ ! -e /sys/block/$DMDEV/slaves/* ] ; then 326716fd348SMartin Matuska # It's not there, try looking in /dev/mapper 327716fd348SMartin Matuska DMDEV=$(ls -l --full-time /dev/mapper | grep $DM_NAME | 328*b1c1ee44SMartin Matuska awk '{gsub("../", " "); print $NF}' | head -n 1) 329716fd348SMartin Matuska fi 330716fd348SMartin Matuska 331716fd348SMartin Matuska # Use sysfs pointers in /sys/block/dm-X/slaves because using 332716fd348SMartin Matuska # userspace tools creates lots of overhead and should be avoided 333716fd348SMartin Matuska # whenever possible. Use awk to isolate lowest instance of 334716fd348SMartin Matuska # sd device member in dm device group regardless of string 335716fd348SMartin Matuska # length. 336716fd348SMartin Matuska DEV=$(ls "/sys/block/$DMDEV/slaves" | awk ' 337716fd348SMartin Matuska { len=sprintf ("%20s",length($0)); gsub(/ /,0,str); a[NR]=len "_" $0; } 338716fd348SMartin Matuska END { 339716fd348SMartin Matuska asort(a) 340716fd348SMartin Matuska print substr(a[1],22) 341716fd348SMartin Matuska }') 342716fd348SMartin Matuska 343716fd348SMartin Matuska if [ -z "$DEV" ] ; then 344716fd348SMartin Matuska return 345716fd348SMartin Matuska fi 346716fd348SMartin Matuska fi 347716fd348SMartin Matuska 348716fd348SMartin Matuska if echo "$DEV" | grep -q ^/devices/ ; then 349716fd348SMartin Matuska sys_path=$DEV 350716fd348SMartin Matuska else 351716fd348SMartin Matuska sys_path=$(udevadm info -q path -p "/sys/block/$DEV" 2>/dev/null) 352716fd348SMartin Matuska fi 353716fd348SMartin Matuska 354716fd348SMartin Matuska # Use positional parameters as an ad-hoc array 355716fd348SMartin Matuska set -- $(echo "$sys_path" | tr / ' ') 356716fd348SMartin Matuska num_dirs=$# 357716fd348SMartin Matuska scsi_host_dir="/sys" 358716fd348SMartin Matuska 359716fd348SMartin Matuska # Get path up to /sys/.../hostX 360716fd348SMartin Matuska i=1 361716fd348SMartin Matuska 362716fd348SMartin Matuska while [ $i -le "$num_dirs" ] ; do 363716fd348SMartin Matuska d=$(eval echo '$'{$i}) 364716fd348SMartin Matuska scsi_host_dir="$scsi_host_dir/$d" 365716fd348SMartin Matuska echo "$d" | grep -q -E '^host[0-9]+$' && break 366716fd348SMartin Matuska i=$((i + 1)) 367716fd348SMartin Matuska done 368716fd348SMartin Matuska 369716fd348SMartin Matuska # Lets grab the SAS host channel number and save it for JBOD sorting later 370716fd348SMartin Matuska HOSTCHAN=$(echo "$d" | awk -F/ '{ gsub("host","",$NF); print $NF}') 371716fd348SMartin Matuska 372716fd348SMartin Matuska if [ $i = "$num_dirs" ] ; then 373716fd348SMartin Matuska return 374716fd348SMartin Matuska fi 375716fd348SMartin Matuska 376716fd348SMartin Matuska PCI_ID=$(eval echo '$'{$((i -1))} | awk -F: '{print $2":"$3}') 377716fd348SMartin Matuska 378716fd348SMartin Matuska # In sas_switch mode, the directory four levels beneath 379716fd348SMartin Matuska # /sys/.../hostX contains symlinks to phy devices that reveal 380716fd348SMartin Matuska # the switch port number. In sas_direct mode, the phy links one 381716fd348SMartin Matuska # directory down reveal the HBA port. 382716fd348SMartin Matuska port_dir=$scsi_host_dir 383716fd348SMartin Matuska 384716fd348SMartin Matuska case $TOPOLOGY in 385716fd348SMartin Matuska "sas_switch") j=$((i + 4)) ;; 386716fd348SMartin Matuska "sas_direct") j=$((i + 1)) ;; 387716fd348SMartin Matuska esac 388716fd348SMartin Matuska 389716fd348SMartin Matuska i=$((i + 1)) 390716fd348SMartin Matuska 391716fd348SMartin Matuska while [ $i -le $j ] ; do 392716fd348SMartin Matuska port_dir="$port_dir/$(eval echo '$'{$i})" 393716fd348SMartin Matuska i=$((i + 1)) 394716fd348SMartin Matuska done 395716fd348SMartin Matuska 396716fd348SMartin Matuska PHY=$(ls -vd "$port_dir"/phy* 2>/dev/null | head -1 | awk -F: '{print $NF}') 397716fd348SMartin Matuska if [ -z "$PHY" ] ; then 398716fd348SMartin Matuska PHY=0 399716fd348SMartin Matuska fi 400716fd348SMartin Matuska PORT=$((PHY / PHYS_PER_PORT)) 401716fd348SMartin Matuska 402716fd348SMartin Matuska # Look in /sys/.../sas_device/end_device-X for the bay_identifier 403716fd348SMartin Matuska # attribute. 404716fd348SMartin Matuska end_device_dir=$port_dir 405716fd348SMartin Matuska 406716fd348SMartin Matuska while [ $i -lt "$num_dirs" ] ; do 407716fd348SMartin Matuska d=$(eval echo '$'{$i}) 408716fd348SMartin Matuska end_device_dir="$end_device_dir/$d" 409716fd348SMartin Matuska if echo "$d" | grep -q '^end_device' ; then 410716fd348SMartin Matuska end_device_dir="$end_device_dir/sas_device/$d" 411716fd348SMartin Matuska break 412716fd348SMartin Matuska fi 413716fd348SMartin Matuska i=$((i + 1)) 414716fd348SMartin Matuska done 415716fd348SMartin Matuska 416716fd348SMartin Matuska # Add 'mix' slot type for environments where dm-multipath devices 417716fd348SMartin Matuska # include end-devices connected via SAS expanders or direct connection 418716fd348SMartin Matuska # to SAS HBA. A mixed connectivity environment such as pool devices 419716fd348SMartin Matuska # contained in a SAS JBOD and spare drives or log devices directly 420716fd348SMartin Matuska # connected in a server backplane without expanders in the I/O path. 421716fd348SMartin Matuska SLOT= 422716fd348SMartin Matuska 423716fd348SMartin Matuska case $BAY in 424716fd348SMartin Matuska "bay") 425716fd348SMartin Matuska SLOT=$(cat "$end_device_dir/bay_identifier" 2>/dev/null) 426716fd348SMartin Matuska ;; 427716fd348SMartin Matuska "mix") 428716fd348SMartin Matuska if [ $(cat "$end_device_dir/bay_identifier" 2>/dev/null) ] ; then 429716fd348SMartin Matuska SLOT=$(cat "$end_device_dir/bay_identifier" 2>/dev/null) 430716fd348SMartin Matuska else 431716fd348SMartin Matuska SLOT=$(cat "$end_device_dir/phy_identifier" 2>/dev/null) 432716fd348SMartin Matuska fi 433716fd348SMartin Matuska ;; 434716fd348SMartin Matuska "phy") 435716fd348SMartin Matuska SLOT=$(cat "$end_device_dir/phy_identifier" 2>/dev/null) 436716fd348SMartin Matuska ;; 437716fd348SMartin Matuska "port") 438716fd348SMartin Matuska d=$(eval echo '$'{$i}) 439716fd348SMartin Matuska SLOT=$(echo "$d" | sed -e 's/^.*://') 440716fd348SMartin Matuska ;; 441716fd348SMartin Matuska "id") 442716fd348SMartin Matuska i=$((i + 1)) 443716fd348SMartin Matuska d=$(eval echo '$'{$i}) 444716fd348SMartin Matuska SLOT=$(echo "$d" | sed -e 's/^.*://') 445716fd348SMartin Matuska ;; 446716fd348SMartin Matuska "lun") 447716fd348SMartin Matuska i=$((i + 2)) 448716fd348SMartin Matuska d=$(eval echo '$'{$i}) 449716fd348SMartin Matuska SLOT=$(echo "$d" | sed -e 's/^.*://') 450716fd348SMartin Matuska ;; 45187bf66d4SMartin Matuska "bay_lun") 45287bf66d4SMartin Matuska # Like 'bay' but with the LUN number appened. Added for SAS 45387bf66d4SMartin Matuska # multi-actuator HDDs, where one physical drive has multiple 45487bf66d4SMartin Matuska # LUNs, thus multiple logical drives share the same bay number 45587bf66d4SMartin Matuska i=$((i + 2)) 45687bf66d4SMartin Matuska d=$(eval echo '$'{$i}) 45787bf66d4SMartin Matuska LUN="-lun$(echo "$d" | sed -e 's/^.*://')" 45887bf66d4SMartin Matuska SLOT=$(cat "$end_device_dir/bay_identifier" 2>/dev/null) 45987bf66d4SMartin Matuska ;; 460716fd348SMartin Matuska "ses") 461716fd348SMartin Matuska # look for this SAS path in all SCSI Enclosure Services 462716fd348SMartin Matuska # (SES) enclosures 463716fd348SMartin Matuska sas_address=$(cat "$end_device_dir/sas_address" 2>/dev/null) 464716fd348SMartin Matuska enclosures=$(lsscsi -g | \ 465716fd348SMartin Matuska sed -n -e '/enclosu/s/^.* \([^ ][^ ]*\) *$/\1/p') 466716fd348SMartin Matuska for enclosure in $enclosures; do 467716fd348SMartin Matuska set -- $(sg_ses -p aes "$enclosure" | \ 468716fd348SMartin Matuska awk "/device slot number:/{slot=\$12} \ 469716fd348SMartin Matuska /SAS address: $sas_address/\ 470716fd348SMartin Matuska {print slot}") 471716fd348SMartin Matuska SLOT=$1 472716fd348SMartin Matuska if [ -n "$SLOT" ] ; then 473716fd348SMartin Matuska break 474716fd348SMartin Matuska fi 475716fd348SMartin Matuska done 476716fd348SMartin Matuska ;; 477716fd348SMartin Matuska esac 478716fd348SMartin Matuska if [ -z "$SLOT" ] ; then 479716fd348SMartin Matuska return 480716fd348SMartin Matuska fi 481716fd348SMartin Matuska 482716fd348SMartin Matuska if [ "$MULTIJBOD_MODE" = "yes" ] ; then 483716fd348SMartin Matuska CHAN=$(map_channel "$PCI_ID" "$PORT") 484716fd348SMartin Matuska SLOT=$(map_slot "$SLOT" "$CHAN") 485716fd348SMartin Matuska JBOD=$(map_jbod "$DEV") 486716fd348SMartin Matuska 487716fd348SMartin Matuska if [ -z "$CHAN" ] ; then 488716fd348SMartin Matuska return 489716fd348SMartin Matuska fi 49087bf66d4SMartin Matuska echo "${CHAN}"-"${JBOD}"-"${SLOT}${LUN}${PART}" 491716fd348SMartin Matuska else 492716fd348SMartin Matuska CHAN=$(map_channel "$PCI_ID" "$PORT") 493716fd348SMartin Matuska SLOT=$(map_slot "$SLOT" "$CHAN") 494716fd348SMartin Matuska 495716fd348SMartin Matuska if [ -z "$CHAN" ] ; then 496716fd348SMartin Matuska return 497716fd348SMartin Matuska fi 49887bf66d4SMartin Matuska echo "${CHAN}${SLOT}${LUN}${PART}" 499716fd348SMartin Matuska fi 500716fd348SMartin Matuska} 501716fd348SMartin Matuska 502716fd348SMartin Matuskascsi_handler() { 503716fd348SMartin Matuska if [ -z "$FIRST_BAY_NUMBER" ] ; then 504716fd348SMartin Matuska FIRST_BAY_NUMBER=$(awk '$1 == "first_bay_number" \ 505716fd348SMartin Matuska {print $2; exit}' $CONFIG) 506716fd348SMartin Matuska fi 507716fd348SMartin Matuska FIRST_BAY_NUMBER=${FIRST_BAY_NUMBER:-0} 508716fd348SMartin Matuska 509716fd348SMartin Matuska if [ -z "$PHYS_PER_PORT" ] ; then 510716fd348SMartin Matuska PHYS_PER_PORT=$(awk '$1 == "phys_per_port" \ 511716fd348SMartin Matuska {print $2; exit}' $CONFIG) 512716fd348SMartin Matuska fi 513716fd348SMartin Matuska PHYS_PER_PORT=${PHYS_PER_PORT:-4} 514716fd348SMartin Matuska 515716fd348SMartin Matuska if ! echo "$PHYS_PER_PORT" | grep -q -E '^[0-9]+$' ; then 516716fd348SMartin Matuska echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric" 517716fd348SMartin Matuska exit 1 518716fd348SMartin Matuska fi 519716fd348SMartin Matuska 520716fd348SMartin Matuska if [ -z "$MULTIPATH_MODE" ] ; then 521716fd348SMartin Matuska MULTIPATH_MODE=$(awk '$1 == "multipath" \ 522716fd348SMartin Matuska {print $2; exit}' $CONFIG) 523716fd348SMartin Matuska fi 524716fd348SMartin Matuska 525716fd348SMartin Matuska # Use first running component device if we're handling a dm-mpath device 526716fd348SMartin Matuska if [ "$MULTIPATH_MODE" = "yes" ] ; then 527716fd348SMartin Matuska # If udev didn't tell us the UUID via DM_NAME, check /dev/mapper 528716fd348SMartin Matuska if [ -z "$DM_NAME" ] ; then 529716fd348SMartin Matuska DM_NAME=$(ls -l --full-time /dev/mapper | 530716fd348SMartin Matuska grep "$DEV"$ | awk '{print $9}') 531716fd348SMartin Matuska fi 532716fd348SMartin Matuska 533716fd348SMartin Matuska # For raw disks udev exports DEVTYPE=partition when 534716fd348SMartin Matuska # handling partitions, and the rules can be written to 535716fd348SMartin Matuska # take advantage of this to append a -part suffix. For 536716fd348SMartin Matuska # dm devices we get DEVTYPE=disk even for partitions so 537716fd348SMartin Matuska # we have to append the -part suffix directly in the 538716fd348SMartin Matuska # helper. 539716fd348SMartin Matuska if [ "$DEVTYPE" != "partition" ] ; then 540*b1c1ee44SMartin Matuska # WWNs end with number -> p<partition>, alphabet -> <partition> 541*b1c1ee44SMartin Matuska # '3' + (WWN length 16) = 17 542*b1c1ee44SMartin Matuska PART=${DM_NAME:17} 543*b1c1ee44SMartin Matuska if [[ $PART = "p"* ]]; then 544716fd348SMartin Matuska # Match p[number], remove the 'p' and prepend "-part" 545716fd348SMartin Matuska PART=$(echo "$DM_NAME" | 546716fd348SMartin Matuska awk 'match($0,/p[0-9]+$/) {print "-part"substr($0,RSTART+1,RLENGTH-1)}') 547*b1c1ee44SMartin Matuska elif [[ $PART != "" ]]; then 548*b1c1ee44SMartin Matuska PART="-part"${PART} 549*b1c1ee44SMartin Matuska fi 550716fd348SMartin Matuska fi 551716fd348SMartin Matuska 552716fd348SMartin Matuska # Strip off partition information. 553*b1c1ee44SMartin Matuska DM_NAME=${DM_NAME:0:17} 554716fd348SMartin Matuska if [ -z "$DM_NAME" ] ; then 555716fd348SMartin Matuska return 556716fd348SMartin Matuska fi 557716fd348SMartin Matuska 558716fd348SMartin Matuska # Get the raw scsi device name from multipath -ll. Strip off 559716fd348SMartin Matuska # leading pipe symbols to make field numbering consistent. 560716fd348SMartin Matuska DEV=$(multipath -ll "$DM_NAME" | 561716fd348SMartin Matuska awk '/running/{gsub("^[|]"," "); print $3 ; exit}') 562716fd348SMartin Matuska if [ -z "$DEV" ] ; then 563716fd348SMartin Matuska return 564716fd348SMartin Matuska fi 565716fd348SMartin Matuska fi 566716fd348SMartin Matuska 567716fd348SMartin Matuska if echo "$DEV" | grep -q ^/devices/ ; then 568716fd348SMartin Matuska sys_path=$DEV 569716fd348SMartin Matuska else 570716fd348SMartin Matuska sys_path=$(udevadm info -q path -p "/sys/block/$DEV" 2>/dev/null) 571716fd348SMartin Matuska fi 572716fd348SMartin Matuska 573716fd348SMartin Matuska # expect sys_path like this, for example: 574716fd348SMartin Matuska # /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 575716fd348SMartin Matuska 576716fd348SMartin Matuska # Use positional parameters as an ad-hoc array 577716fd348SMartin Matuska set -- $(echo "$sys_path" | tr / ' ') 578716fd348SMartin Matuska num_dirs=$# 579716fd348SMartin Matuska scsi_host_dir="/sys" 580716fd348SMartin Matuska 581716fd348SMartin Matuska # Get path up to /sys/.../hostX 582716fd348SMartin Matuska i=1 583716fd348SMartin Matuska 584716fd348SMartin Matuska while [ $i -le "$num_dirs" ] ; do 585716fd348SMartin Matuska d=$(eval echo '$'{$i}) 586716fd348SMartin Matuska scsi_host_dir="$scsi_host_dir/$d" 587716fd348SMartin Matuska 588716fd348SMartin Matuska echo "$d" | grep -q -E '^host[0-9]+$' && break 589716fd348SMartin Matuska i=$((i + 1)) 590716fd348SMartin Matuska done 591716fd348SMartin Matuska 592716fd348SMartin Matuska if [ $i = "$num_dirs" ] ; then 593716fd348SMartin Matuska return 594716fd348SMartin Matuska fi 595716fd348SMartin Matuska 596716fd348SMartin Matuska PCI_ID=$(eval echo '$'{$((i -1))} | awk -F: '{print $2":"$3}') 597716fd348SMartin Matuska 598716fd348SMartin Matuska # In scsi mode, the directory two levels beneath 599716fd348SMartin Matuska # /sys/.../hostX reveals the port and slot. 600716fd348SMartin Matuska port_dir=$scsi_host_dir 601716fd348SMartin Matuska j=$((i + 2)) 602716fd348SMartin Matuska 603716fd348SMartin Matuska i=$((i + 1)) 604716fd348SMartin Matuska while [ $i -le $j ] ; do 605716fd348SMartin Matuska port_dir="$port_dir/$(eval echo '$'{$i})" 606716fd348SMartin Matuska i=$((i + 1)) 607716fd348SMartin Matuska done 608716fd348SMartin Matuska 609716fd348SMartin Matuska set -- $(echo "$port_dir" | sed -e 's/^.*:\([^:]*\):\([^:]*\)$/\1 \2/') 610716fd348SMartin Matuska PORT=$1 611716fd348SMartin Matuska SLOT=$(($2 + FIRST_BAY_NUMBER)) 612716fd348SMartin Matuska 613716fd348SMartin Matuska if [ -z "$SLOT" ] ; then 614716fd348SMartin Matuska return 615716fd348SMartin Matuska fi 616716fd348SMartin Matuska 617716fd348SMartin Matuska CHAN=$(map_channel "$PCI_ID" "$PORT") 618716fd348SMartin Matuska SLOT=$(map_slot "$SLOT" "$CHAN") 619716fd348SMartin Matuska 620716fd348SMartin Matuska if [ -z "$CHAN" ] ; then 621716fd348SMartin Matuska return 622716fd348SMartin Matuska fi 623716fd348SMartin Matuska echo "${CHAN}${SLOT}${PART}" 624716fd348SMartin Matuska} 625716fd348SMartin Matuska 626716fd348SMartin Matuska# Figure out the name for the enclosure symlink 627716fd348SMartin Matuskaenclosure_handler () { 628716fd348SMartin Matuska # We get all the info we need from udev's DEVPATH variable: 629716fd348SMartin Matuska # 630716fd348SMartin Matuska # DEVPATH=/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/subsystem/devices/0:0:0:0/scsi_generic/sg0 631716fd348SMartin Matuska 632716fd348SMartin Matuska # Get the enclosure ID ("0:0:0:0") 633716fd348SMartin Matuska ENC="${DEVPATH%/*}" 634716fd348SMartin Matuska ENC="${ENC%/*}" 635716fd348SMartin Matuska ENC="${ENC##*/}" 636716fd348SMartin Matuska if [ ! -d "/sys/class/enclosure/$ENC" ] ; then 637716fd348SMartin Matuska # Not an enclosure, bail out 638716fd348SMartin Matuska return 639716fd348SMartin Matuska fi 640716fd348SMartin Matuska 641716fd348SMartin Matuska # Get the long sysfs device path to our enclosure. Looks like: 642716fd348SMartin Matuska # /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0/ ... /enclosure/0:0:0:0 643716fd348SMartin Matuska 644716fd348SMartin Matuska ENC_DEVICE=$(readlink "/sys/class/enclosure/$ENC") 645716fd348SMartin Matuska 646716fd348SMartin Matuska # Grab the full path to the hosts port dir: 647716fd348SMartin Matuska # /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0 648716fd348SMartin Matuska PORT_DIR=$(echo "$ENC_DEVICE" | grep -Eo '.+host[0-9]+/port-[0-9]+:[0-9]+') 649716fd348SMartin Matuska 650716fd348SMartin Matuska # Get the port number 651716fd348SMartin Matuska PORT_ID=$(echo "$PORT_DIR" | grep -Eo "[0-9]+$") 652716fd348SMartin Matuska 653716fd348SMartin Matuska # The PCI directory is two directories up from the port directory 654716fd348SMartin Matuska # /sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0 655716fd348SMartin Matuska PCI_ID_LONG="$(readlink -m "/sys/$PORT_DIR/../..")" 656716fd348SMartin Matuska PCI_ID_LONG="${PCI_ID_LONG##*/}" 657716fd348SMartin Matuska 658716fd348SMartin Matuska # Strip down the PCI address from 0000:05:00.0 to 05:00.0 659716fd348SMartin Matuska PCI_ID="${PCI_ID_LONG#[0-9]*:}" 660716fd348SMartin Matuska 661716fd348SMartin Matuska # Name our device according to vdev_id.conf (like "L0" or "U1"). 662716fd348SMartin Matuska NAME=$(awk "/channel/{if (\$1 == \"channel\" && \$2 == \"$PCI_ID\" && \ 663716fd348SMartin Matuska \$3 == \"$PORT_ID\") {print \$4\$3}}" $CONFIG) 664716fd348SMartin Matuska 665716fd348SMartin Matuska echo "${NAME}" 666716fd348SMartin Matuska} 667716fd348SMartin Matuska 668716fd348SMartin Matuskaalias_handler () { 669716fd348SMartin Matuska # Special handling is needed to correctly append a -part suffix 670716fd348SMartin Matuska # to partitions of device mapper devices. The DEVTYPE attribute 671716fd348SMartin Matuska # is normally set to "disk" instead of "partition" in this case, 672716fd348SMartin Matuska # so the udev rules won't handle that for us as they do for 673716fd348SMartin Matuska # "plain" block devices. 674716fd348SMartin Matuska # 675716fd348SMartin Matuska # For example, we may have the following links for a device and its 676716fd348SMartin Matuska # partitions, 677716fd348SMartin Matuska # 678716fd348SMartin Matuska # /dev/disk/by-id/dm-name-isw_dibgbfcije_ARRAY0 -> ../../dm-0 679716fd348SMartin Matuska # /dev/disk/by-id/dm-name-isw_dibgbfcije_ARRAY0p1 -> ../../dm-1 680716fd348SMartin Matuska # /dev/disk/by-id/dm-name-isw_dibgbfcije_ARRAY0p2 -> ../../dm-3 681716fd348SMartin Matuska # 682716fd348SMartin Matuska # and the following alias in vdev_id.conf. 683716fd348SMartin Matuska # 684716fd348SMartin Matuska # alias A0 dm-name-isw_dibgbfcije_ARRAY0 685716fd348SMartin Matuska # 686716fd348SMartin Matuska # The desired outcome is for the following links to be created 687716fd348SMartin Matuska # without having explicitly defined aliases for the partitions. 688716fd348SMartin Matuska # 689716fd348SMartin Matuska # /dev/disk/by-vdev/A0 -> ../../dm-0 690716fd348SMartin Matuska # /dev/disk/by-vdev/A0-part1 -> ../../dm-1 691716fd348SMartin Matuska # /dev/disk/by-vdev/A0-part2 -> ../../dm-3 692716fd348SMartin Matuska # 693716fd348SMartin Matuska # Warning: The following grep pattern will misidentify whole-disk 694716fd348SMartin Matuska # devices whose names end with 'p' followed by a string of 695716fd348SMartin Matuska # digits as partitions, causing alias creation to fail. This 696716fd348SMartin Matuska # ambiguity seems unavoidable, so devices using this facility 697716fd348SMartin Matuska # must not use such names. 698716fd348SMartin Matuska DM_PART= 699716fd348SMartin Matuska if echo "$DM_NAME" | grep -q -E 'p[0-9][0-9]*$' ; then 700716fd348SMartin Matuska if [ "$DEVTYPE" != "partition" ] ; then 701716fd348SMartin Matuska # Match p[number], remove the 'p' and prepend "-part" 702716fd348SMartin Matuska DM_PART=$(echo "$DM_NAME" | 703716fd348SMartin Matuska awk 'match($0,/p[0-9]+$/) {print "-part"substr($0,RSTART+1,RLENGTH-1)}') 704716fd348SMartin Matuska fi 705716fd348SMartin Matuska fi 706716fd348SMartin Matuska 707716fd348SMartin Matuska # DEVLINKS attribute must have been populated by already-run udev rules. 708716fd348SMartin Matuska for link in $DEVLINKS ; do 709716fd348SMartin Matuska # Remove partition information to match key of top-level device. 710716fd348SMartin Matuska if [ -n "$DM_PART" ] ; then 711716fd348SMartin Matuska link=$(echo "$link" | sed 's/p[0-9][0-9]*$//') 712716fd348SMartin Matuska fi 713716fd348SMartin Matuska # Check both the fully qualified and the base name of link. 714716fd348SMartin Matuska for l in $link ${link##*/} ; do 715716fd348SMartin Matuska if [ ! -z "$l" ]; then 716716fd348SMartin Matuska alias=$(awk -v var="$l" '($1 == "alias") && \ 717716fd348SMartin Matuska ($3 == var) \ 718716fd348SMartin Matuska { print $2; exit }' $CONFIG) 719716fd348SMartin Matuska if [ -n "$alias" ] ; then 720716fd348SMartin Matuska echo "${alias}${DM_PART}" 721716fd348SMartin Matuska return 722716fd348SMartin Matuska fi 723716fd348SMartin Matuska fi 724716fd348SMartin Matuska done 725716fd348SMartin Matuska done 726716fd348SMartin Matuska} 727716fd348SMartin Matuska 728716fd348SMartin Matuska# main 729716fd348SMartin Matuskawhile getopts 'c:d:eg:jmp:h' OPTION; do 730716fd348SMartin Matuska case ${OPTION} in 731716fd348SMartin Matuska c) 732716fd348SMartin Matuska CONFIG=${OPTARG} 733716fd348SMartin Matuska ;; 734716fd348SMartin Matuska d) 735716fd348SMartin Matuska DEV=${OPTARG} 736716fd348SMartin Matuska ;; 737716fd348SMartin Matuska e) 738716fd348SMartin Matuska # When udev sees a scsi_generic device, it calls this script with -e to 739716fd348SMartin Matuska # create the enclosure device symlinks only. We also need 740716fd348SMartin Matuska # "enclosure_symlinks yes" set in vdev_id.config to actually create the 741716fd348SMartin Matuska # symlink. 742716fd348SMartin Matuska ENCLOSURE_MODE=$(awk '{if ($1 == "enclosure_symlinks") \ 743716fd348SMartin Matuska print $2}' "$CONFIG") 744716fd348SMartin Matuska 745716fd348SMartin Matuska if [ "$ENCLOSURE_MODE" != "yes" ] ; then 746716fd348SMartin Matuska exit 0 747716fd348SMartin Matuska fi 748716fd348SMartin Matuska ;; 749716fd348SMartin Matuska g) 750716fd348SMartin Matuska TOPOLOGY=$OPTARG 751716fd348SMartin Matuska ;; 752716fd348SMartin Matuska p) 753716fd348SMartin Matuska PHYS_PER_PORT=${OPTARG} 754716fd348SMartin Matuska ;; 755716fd348SMartin Matuska j) 756716fd348SMartin Matuska MULTIJBOD_MODE=yes 757716fd348SMartin Matuska ;; 758716fd348SMartin Matuska m) 759716fd348SMartin Matuska MULTIPATH_MODE=yes 760716fd348SMartin Matuska ;; 761716fd348SMartin Matuska h) 762716fd348SMartin Matuska usage 763716fd348SMartin Matuska ;; 764716fd348SMartin Matuska esac 765716fd348SMartin Matuskadone 766716fd348SMartin Matuska 767716fd348SMartin Matuskaif [ ! -r "$CONFIG" ] ; then 768716fd348SMartin Matuska echo "Error: Config file \"$CONFIG\" not found" 769716fd348SMartin Matuska exit 1 770716fd348SMartin Matuskafi 771716fd348SMartin Matuska 772716fd348SMartin Matuskaif [ -z "$DEV" ] && [ -z "$ENCLOSURE_MODE" ] ; then 773716fd348SMartin Matuska echo "Error: missing required option -d" 774716fd348SMartin Matuska exit 1 775716fd348SMartin Matuskafi 776716fd348SMartin Matuska 777716fd348SMartin Matuskaif [ -z "$TOPOLOGY" ] ; then 778716fd348SMartin Matuska TOPOLOGY=$(awk '($1 == "topology") {print $2; exit}' "$CONFIG") 779716fd348SMartin Matuskafi 780716fd348SMartin Matuska 781716fd348SMartin Matuskaif [ -z "$BAY" ] ; then 782716fd348SMartin Matuska BAY=$(awk '($1 == "slot") {print $2; exit}' "$CONFIG") 783716fd348SMartin Matuskafi 784716fd348SMartin Matuska 78587bf66d4SMartin MatuskaZPAD=$(awk '($1 == "zpad_slot") {print $2; exit}' "$CONFIG") 78687bf66d4SMartin Matuska 787716fd348SMartin MatuskaTOPOLOGY=${TOPOLOGY:-sas_direct} 788716fd348SMartin Matuska 789716fd348SMartin Matuska# Should we create /dev/by-enclosure symlinks? 790716fd348SMartin Matuskaif [ "$ENCLOSURE_MODE" = "yes" ] && [ "$TOPOLOGY" = "sas_direct" ] ; then 791716fd348SMartin Matuska ID_ENCLOSURE=$(enclosure_handler) 792716fd348SMartin Matuska if [ -z "$ID_ENCLOSURE" ] ; then 793716fd348SMartin Matuska exit 0 794716fd348SMartin Matuska fi 795716fd348SMartin Matuska 796716fd348SMartin Matuska # Just create the symlinks to the enclosure devices and then exit. 797716fd348SMartin Matuska ENCLOSURE_PREFIX=$(awk '/enclosure_symlinks_prefix/{print $2}' "$CONFIG") 798716fd348SMartin Matuska if [ -z "$ENCLOSURE_PREFIX" ] ; then 799716fd348SMartin Matuska ENCLOSURE_PREFIX="enc" 800716fd348SMartin Matuska fi 801716fd348SMartin Matuska echo "ID_ENCLOSURE=$ID_ENCLOSURE" 802716fd348SMartin Matuska echo "ID_ENCLOSURE_PATH=by-enclosure/$ENCLOSURE_PREFIX-$ID_ENCLOSURE" 803716fd348SMartin Matuska exit 0 804716fd348SMartin Matuskafi 805716fd348SMartin Matuska 806716fd348SMartin Matuska# First check if an alias was defined for this device. 807716fd348SMartin MatuskaID_VDEV=$(alias_handler) 808716fd348SMartin Matuska 809716fd348SMartin Matuskaif [ -z "$ID_VDEV" ] ; then 810716fd348SMartin Matuska BAY=${BAY:-bay} 811716fd348SMartin Matuska case $TOPOLOGY in 812716fd348SMartin Matuska sas_direct|sas_switch) 813716fd348SMartin Matuska ID_VDEV=$(sas_handler) 814716fd348SMartin Matuska ;; 815716fd348SMartin Matuska scsi) 816716fd348SMartin Matuska ID_VDEV=$(scsi_handler) 817716fd348SMartin Matuska ;; 818716fd348SMartin Matuska *) 819716fd348SMartin Matuska echo "Error: unknown topology $TOPOLOGY" 820716fd348SMartin Matuska exit 1 821716fd348SMartin Matuska ;; 822716fd348SMartin Matuska esac 823716fd348SMartin Matuskafi 824716fd348SMartin Matuska 825716fd348SMartin Matuskaif [ -n "$ID_VDEV" ] ; then 826716fd348SMartin Matuska echo "ID_VDEV=${ID_VDEV}" 827716fd348SMartin Matuska echo "ID_VDEV_PATH=disk/by-vdev/${ID_VDEV}" 828716fd348SMartin Matuskafi 829