mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-28 11:59:34 +03:00
6ee44e32be
The zpool_id and zpool_layout helper scripts have been updated to use the more common /usr/bin/awk symlink. On Fedora/Redhat systems there are both /bin/awk and /usr/bin/awk symlinks to your installed version of awk. On Debian/Ubuntu systems only the /usr/bin/awk symlink exists. Additionally, add the '\<' token to the beginning of the regex pattern to prevent partial matches. This pattern only appears to work with gawk despite the mawk man page claiming to support this extended regex. Thus you will need to have gawk installed to use these optional helper scripts. A comment has been added to the script to reflect this reality.
161 lines
4.0 KiB
Bash
Executable File
161 lines
4.0 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:-/usr/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 --action=change --subsystem-match=block
|
|
udevadm settle
|
|
fi
|
|
|
|
exit 0
|