mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-27 11:29:36 +03:00
a5b4d63582
By default the zpool_layout command would always use the slot number assigned by Linux when generating the zdev.conf file. This is a reasonable default there are cases when it makes sense to remap the slot id assigned by Linux using your own custom mapping. This commit adds support to zpool_layout to provide a custom slot mapping file. The file contains in the first column the Linux slot it and in the second column the custom slot mapping. By passing this map file with '-m map' to zpool_config the mapping will be applied when generating zdev.conf. Additionally, two sample mapping have been added which reflect different ways to map the slots in the dragon drawers.
161 lines
3.9 KiB
Bash
Executable File
161 lines
3.9 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Set BUSES and PORTS to match the topology of your system. As each
|
|
# port is enumerated it will be assigned the next channel name. The
|
|
# current script enumerates each port on a bus before moving on to
|
|
# enumerate the next bus.
|
|
#
|
|
# Every distribution, version of udev, and type of attached storage
|
|
# seems to result in slightly different formatting of the by-path
|
|
# name. For this reason you may need to adjust the parsing below
|
|
# to suit your needs. This is one of the reasons to use a custom
|
|
# /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="no"
|
|
MAPPING=linux
|
|
|
|
|
|
usage() {
|
|
cat << EOF
|
|
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=${TRIGGER}]
|
|
-m Slot mapping [default=${MAPPING}]
|
|
-h Show this message
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
while getopts 'c:b:p:n:m:th' OPTION; do
|
|
case ${OPTION} in
|
|
c)
|
|
CONFIG=${OPTARG}
|
|
;;
|
|
b)
|
|
BUSES=(${OPTARG})
|
|
;;
|
|
p)
|
|
PORTS=(${OPTARG})
|
|
;;
|
|
n)
|
|
CHANNELS=(${OPTARG})
|
|
;;
|
|
m)
|
|
MAPPING=`readlink -e ${OPTARG}`
|
|
;;
|
|
t)
|
|
TRIGGER=yes
|
|
;;
|
|
h)
|
|
usage
|
|
;;
|
|
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, "
|
|
echo "# based of the following physical cable layout."
|
|
echo "#"
|
|
|
|
# Generate host port layout table for comment header.
|
|
echo "# ------------------ Host Port Layout ---------------------"
|
|
echo -n "# "
|
|
for (( i=0; i<${#BUSES[*]}; i++ )); do
|
|
printf "%-8d" ${BUSES[$i]}
|
|
done
|
|
echo
|
|
|
|
for (( i=0, k=0; i<${#PORTS[*]}; i++ )); do
|
|
printf "# Port %-2d " ${PORTS[$i]}
|
|
|
|
for (( j=0; j<${#BUSES[*]}; j++, k++ )); do
|
|
let k=$j*${#PORTS[*]}+$i
|
|
printf "%-8s" ${CHANNELS[$k]}
|
|
done
|
|
echo
|
|
done
|
|
echo "#"
|
|
|
|
# Generate channel/disk layout table for comment header.
|
|
echo "# ----------------- Channel/Disk Layout -------------------"
|
|
echo "# Channel Disks"
|
|
for (( i=0, k=0; i<${#BUSES[*]}; i++ )); do
|
|
for (( j=0; j<${#PORTS[*]}; j++, k++ )); do
|
|
printf "# %-9s" ${CHANNELS[$k]}
|
|
ls *:${BUSES[$i]}:*:${PORTS[$j]}* 2>/dev/null | \
|
|
cut -f7 -d'-' | sort -u -n | tr '\n' ','
|
|
echo
|
|
done
|
|
done
|
|
echo "#"
|
|
|
|
# Generate mapping from <channel><rank> to by-path name.
|
|
for (( i=0, k=0; i<${#BUSES[*]}; i++ )); do
|
|
for (( j=0; j<${#PORTS[*]}; j++, k++ )); do
|
|
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]}"
|
|
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>&-
|
|
popd >/dev/null
|
|
|
|
if [ ${TRIGGER} = "yes" ]; then
|
|
udevadm trigger
|
|
udevadm settle
|
|
fi
|
|
|
|
exit 0
|