Add [-m map] option to zpool_layout
[zfs.git] / cmd / zpool_layout / zpool_layout
index 19cd128..432c157 100755 (executable)
 # /etc/zfs/zdev.conf file, it allows the by-path naming convertion
 # to change and still keep the simple <channel><rank> naming.
 #
+AWK=${AWK:-/bin/awk}
 CONFIG=${CONFIG:-/etc/zfs/zdev.conf}
 BUSES=( 01 02 03 )
 PORTS=( 4 0 )
 CHANNELS=( A B C D E F G H I J K L M N O P Q R S T U V W X Y Z )
-TRIGGER=
+TRIGGER="no"
+MAPPING=linux
+
 
 usage() {
        cat << EOF
-Usage: zpool_layout [-th] [-c file] [-b buses] [-p ports] [-n channels]
-  -c    Alternate config file [default=/etc/zfs/zdev.conf]
-  -b    Enumerate buses [default="01 02 03"]
-  -p    Enumerate ports [default="4 0"]
+Usage: zpool_layout [-th] [-c file] [-b buses] [-p ports] [-n channels] [-m map]
+  -c    Alternate config file [default=${CONFIG}]
+  -b    Enumerate buses [default="${BUSES[*]}"]
+  -p    Enumerate ports [default="${PORTS[*]}"]
   -n    Channel names [default="A..Z"]
-  -t    Trigger and wait for udev to settle [default=no]
+  -t    Trigger and wait for udev to settle [default=${TRIGGER}]
+  -m    Slot mapping [default=${MAPPING}]
   -h    Show this message
 EOF
        exit 0
 }
 
-while getopts 'c:b:p:n:th' OPTION; do
+while getopts 'c:b:p:n:m:th' OPTION; do
        case ${OPTION} in
        c)
                CONFIG=${OPTARG}
@@ -45,8 +49,11 @@ while getopts 'c:b:p:n:th' OPTION; do
        n)
                CHANNELS=(${OPTARG})
                ;;
+       m)
+               MAPPING=`readlink -e ${OPTARG}`
+               ;;
        t)
-               TRIGGER=1
+               TRIGGER=yes
                ;;
        h)
                usage
@@ -54,11 +61,31 @@ while getopts 'c:b:p:n:th' OPTION; do
        esac
 done
 
+# Verify mapping file exists if specified.
+# Linux-Slot   Custom-Slot
+if [ ${MAPPING} != "linux" ] && [ ! -e ${MAPPING} ]; then
+       echo "Error: Mapping file '${MAPPING}' does not exist"
+       exit 1
+fi
+
 # Save stdout as fd #8, then redirect stdout to the config file.
 exec 8>&1
 exec >${CONFIG}
 pushd /dev/disk/by-path >/dev/null
 
+map_slot() {
+       local LINUX_SLOT=$1
+       local MAPPED_SLOT=
+
+       if [ ${MAPPING} = "linux" ]; then
+               MAPPED_SLOT=${LINUX_SLOT}
+       else
+               MAPPED_SLOT=`${AWK} "\\$1 == ${LINUX_SLOT} && !/^#/ \
+                       { print \\$2; exit }" $MAPPING`
+       fi
+       printf "%d" ${MAPPED_SLOT}
+}
+
 # Generate comment header.
 echo "#"
 echo "# Custom /dev/disk/by-path to /dev/disk/zpool mapping, "
@@ -98,28 +125,34 @@ done
 echo "#"
 
 # Generate mapping from <channel><rank> to by-path name.
-TMP_FILE=`mktemp`
-AWK=${AWK:-/bin/awk}
-
 for (( i=0, k=0; i<${#BUSES[*]}; i++ )); do
        for (( j=0; j<${#PORTS[*]}; j++, k++ )); do
-               ls *:${BUSES[$i]}:*:${PORTS[$j]}*  2>/dev/null | \
-                       grep -v part | sort -n -k7 -t'-'>${TMP_FILE}
+               BYPATH=(`ls *:${BUSES[$i]}:*:${PORTS[$j]}* 2>/dev/null | \
+                       grep -v part | sort -n -k7 -t'-' | cut -f1-6 -d'-'`)
+               SLOTS=(`ls *:${BUSES[$i]}:*:${PORTS[$j]}* 2>/dev/null |  \
+                       grep -v part | sort -n -k7 -t'-' | cut -f7 -d'-'`)
+               TMP_FILE=`mktemp`
+
+               for (( l=0; l<${#SLOTS[*]}; l++ )); do
+                       MAPPED_SLOT=`map_slot ${SLOTS[$l]}`
+                       printf "%s%d\t%s-%d\n" \
+                               ${CHANNELS[$k]} ${MAPPED_SLOT} \
+                               ${BYPATH[$l]} ${SLOTS[$l]} >>${TMP_FILE}
+               done
 
                echo
                echo -n "# Channel ${CHANNELS[$k]}, "
                echo "Bus ${BUSES[$i]}, Port ${PORTS[$j]}"
-               ${AWK} -F '-' -v ch="${CHANNELS[$k]}" \
-                       '{print ch$7 "\t" $0 }' ${TMP_FILE}
+               cat ${TMP_FILE} | sort -n -k2 -t${CHANNELS[$k]}
+               rm -f ${TMP_FILE}
        done
 done
 
 # Restore stdout from fd #8 and close fd #8.
 exec 1>&8 8>&-
-rm -f ${TMP_FILE}
 popd >/dev/null
 
-if [ ${TRIGGER} ]; then
+if [ ${TRIGGER} = "yes" ]; then
        udevadm trigger
        udevadm settle
 fi