]> git.proxmox.com Git - mirror_zfs-debian.git/blame - cmd/zpool_layout/zpool_layout
Call udevadm trigger more safely
[mirror_zfs-debian.git] / cmd / zpool_layout / zpool_layout
CommitLineData
c9c0d073
BB
1#!/bin/bash
2#
3# Set BUSES and PORTS to match the topology of your system. As each
4# port is enumerated it will be assigned the next channel name. The
5# current script enumerates each port on a bus before moving on to
6# enumerate the next bus.
7#
8# Every distribution, version of udev, and type of attached storage
9# seems to result in slightly different formatting of the by-path
10# name. For this reason you may need to adjust the parsing below
11# to suit your needs. This is one of the reasons to use a custom
12# /etc/zfs/zdev.conf file, it allows the by-path naming convertion
13# to change and still keep the simple <channel><rank> naming.
14#
a5b4d635 15AWK=${AWK:-/bin/awk}
c9c0d073
BB
16CONFIG=${CONFIG:-/etc/zfs/zdev.conf}
17BUSES=( 01 02 03 )
18PORTS=( 4 0 )
19CHANNELS=( 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 )
a5b4d635
BB
20TRIGGER="no"
21MAPPING=linux
22
c9c0d073
BB
23
24usage() {
25 cat << EOF
a5b4d635
BB
26Usage: zpool_layout [-th] [-c file] [-b buses] [-p ports] [-n channels] [-m map]
27 -c Alternate config file [default=${CONFIG}]
28 -b Enumerate buses [default="${BUSES[*]}"]
29 -p Enumerate ports [default="${PORTS[*]}"]
c9c0d073 30 -n Channel names [default="A..Z"]
a5b4d635
BB
31 -t Trigger and wait for udev to settle [default=${TRIGGER}]
32 -m Slot mapping [default=${MAPPING}]
c9c0d073
BB
33 -h Show this message
34EOF
35 exit 0
36}
37
a5b4d635 38while getopts 'c:b:p:n:m:th' OPTION; do
c9c0d073
BB
39 case ${OPTION} in
40 c)
41 CONFIG=${OPTARG}
42 ;;
43 b)
44 BUSES=(${OPTARG})
45 ;;
46 p)
47 PORTS=(${OPTARG})
48 ;;
49 n)
50 CHANNELS=(${OPTARG})
51 ;;
a5b4d635
BB
52 m)
53 MAPPING=`readlink -e ${OPTARG}`
54 ;;
c9c0d073 55 t)
a5b4d635 56 TRIGGER=yes
c9c0d073
BB
57 ;;
58 h)
59 usage
60 ;;
61 esac
62done
63
a5b4d635
BB
64# Verify mapping file exists if specified.
65# Linux-Slot Custom-Slot
66if [ ${MAPPING} != "linux" ] && [ ! -e ${MAPPING} ]; then
67 echo "Error: Mapping file '${MAPPING}' does not exist"
68 exit 1
69fi
70
c9c0d073
BB
71# Save stdout as fd #8, then redirect stdout to the config file.
72exec 8>&1
73exec >${CONFIG}
74pushd /dev/disk/by-path >/dev/null
75
a5b4d635
BB
76map_slot() {
77 local LINUX_SLOT=$1
78 local MAPPED_SLOT=
79
80 if [ ${MAPPING} = "linux" ]; then
81 MAPPED_SLOT=${LINUX_SLOT}
82 else
83 MAPPED_SLOT=`${AWK} "\\$1 == ${LINUX_SLOT} && !/^#/ \
84 { print \\$2; exit }" $MAPPING`
85 fi
86 printf "%d" ${MAPPED_SLOT}
87}
88
c9c0d073
BB
89# Generate comment header.
90echo "#"
91echo "# Custom /dev/disk/by-path to /dev/disk/zpool mapping, "
92echo "# based of the following physical cable layout."
93echo "#"
94
95# Generate host port layout table for comment header.
96echo "# ------------------ Host Port Layout ---------------------"
97echo -n "# "
98for (( i=0; i<${#BUSES[*]}; i++ )); do
99 printf "%-8d" ${BUSES[$i]}
100done
101echo
102
103for (( i=0, k=0; i<${#PORTS[*]}; i++ )); do
104 printf "# Port %-2d " ${PORTS[$i]}
105
106 for (( j=0; j<${#BUSES[*]}; j++, k++ )); do
107 let k=$j*${#PORTS[*]}+$i
108 printf "%-8s" ${CHANNELS[$k]}
109 done
110 echo
111done
112echo "#"
113
114# Generate channel/disk layout table for comment header.
115echo "# ----------------- Channel/Disk Layout -------------------"
116echo "# Channel Disks"
117for (( i=0, k=0; i<${#BUSES[*]}; i++ )); do
118 for (( j=0; j<${#PORTS[*]}; j++, k++ )); do
119 printf "# %-9s" ${CHANNELS[$k]}
120 ls *:${BUSES[$i]}:*:${PORTS[$j]}* 2>/dev/null | \
121 cut -f7 -d'-' | sort -u -n | tr '\n' ','
122 echo
123 done
124done
125echo "#"
126
127# Generate mapping from <channel><rank> to by-path name.
c9c0d073
BB
128for (( i=0, k=0; i<${#BUSES[*]}; i++ )); do
129 for (( j=0; j<${#PORTS[*]}; j++, k++ )); do
a5b4d635
BB
130 BYPATH=(`ls *:${BUSES[$i]}:*:${PORTS[$j]}* 2>/dev/null | \
131 grep -v part | sort -n -k7 -t'-' | cut -f1-6 -d'-'`)
132 SLOTS=(`ls *:${BUSES[$i]}:*:${PORTS[$j]}* 2>/dev/null | \
133 grep -v part | sort -n -k7 -t'-' | cut -f7 -d'-'`)
134 TMP_FILE=`mktemp`
135
136 for (( l=0; l<${#SLOTS[*]}; l++ )); do
137 MAPPED_SLOT=`map_slot ${SLOTS[$l]}`
138 printf "%s%d\t%s-%d\n" \
139 ${CHANNELS[$k]} ${MAPPED_SLOT} \
140 ${BYPATH[$l]} ${SLOTS[$l]} >>${TMP_FILE}
141 done
c9c0d073
BB
142
143 echo
144 echo -n "# Channel ${CHANNELS[$k]}, "
145 echo "Bus ${BUSES[$i]}, Port ${PORTS[$j]}"
a5b4d635
BB
146 cat ${TMP_FILE} | sort -n -k2 -t${CHANNELS[$k]}
147 rm -f ${TMP_FILE}
c9c0d073
BB
148 done
149done
150
151# Restore stdout from fd #8 and close fd #8.
152exec 1>&8 8>&-
c9c0d073
BB
153popd >/dev/null
154
a5b4d635 155if [ ${TRIGGER} = "yes" ]; then
fa417e57 156 udevadm trigger --action=change --subsystem-match=block
c9c0d073
BB
157 udevadm settle
158fi
159
160exit 0