19cd1280799e79001ad8a3f81520d99b5a5f6907
[zfs.git] / cmd / zpool_layout / zpool_layout
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 #
15 CONFIG=${CONFIG:-/etc/zfs/zdev.conf}
16 BUSES=( 01 02 03 )
17 PORTS=( 4 0 )
18 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 )
19 TRIGGER=
20
21 usage() {
22         cat << EOF
23 Usage: zpool_layout [-th] [-c file] [-b buses] [-p ports] [-n channels]
24   -c    Alternate config file [default=/etc/zfs/zdev.conf]
25   -b    Enumerate buses [default="01 02 03"]
26   -p    Enumerate ports [default="4 0"]
27   -n    Channel names [default="A..Z"]
28   -t    Trigger and wait for udev to settle [default=no]
29   -h    Show this message
30 EOF
31         exit 0
32 }
33
34 while getopts 'c:b:p:n:th' OPTION; do
35         case ${OPTION} in
36         c)
37                 CONFIG=${OPTARG}
38                 ;;
39         b)
40                 BUSES=(${OPTARG})
41                 ;;
42         p)
43                 PORTS=(${OPTARG})
44                 ;;
45         n)
46                 CHANNELS=(${OPTARG})
47                 ;;
48         t)
49                 TRIGGER=1
50                 ;;
51         h)
52                 usage
53                 ;;
54         esac
55 done
56
57 # Save stdout as fd #8, then redirect stdout to the config file.
58 exec 8>&1
59 exec >${CONFIG}
60 pushd /dev/disk/by-path >/dev/null
61
62 # Generate comment header.
63 echo "#"
64 echo "# Custom /dev/disk/by-path to /dev/disk/zpool mapping, "
65 echo "# based of the following physical cable layout."
66 echo "#"
67
68 # Generate host port layout table for comment header.
69 echo "# ------------------ Host Port Layout ---------------------"
70 echo -n "#          "
71 for (( i=0; i<${#BUSES[*]}; i++ )); do
72         printf "%-8d" ${BUSES[$i]}
73 done
74 echo
75
76 for (( i=0, k=0; i<${#PORTS[*]}; i++ )); do
77         printf "# Port %-2d  " ${PORTS[$i]}
78
79         for (( j=0; j<${#BUSES[*]}; j++, k++ )); do
80                 let k=$j*${#PORTS[*]}+$i
81                 printf "%-8s" ${CHANNELS[$k]}
82         done
83         echo
84 done
85 echo "#"
86
87 # Generate channel/disk layout table for comment header.
88 echo "# ----------------- Channel/Disk Layout -------------------"
89 echo "# Channel  Disks"
90 for (( i=0, k=0; i<${#BUSES[*]}; i++ )); do
91         for (( j=0; j<${#PORTS[*]}; j++, k++ )); do
92                 printf "# %-9s" ${CHANNELS[$k]}
93                 ls *:${BUSES[$i]}:*:${PORTS[$j]}* 2>/dev/null | \
94                         cut -f7 -d'-' | sort -u -n | tr '\n' ','
95                 echo
96         done
97 done
98 echo "#"
99
100 # Generate mapping from <channel><rank> to by-path name.
101 TMP_FILE=`mktemp`
102 AWK=${AWK:-/bin/awk}
103
104 for (( i=0, k=0; i<${#BUSES[*]}; i++ )); do
105         for (( j=0; j<${#PORTS[*]}; j++, k++ )); do
106                 ls *:${BUSES[$i]}:*:${PORTS[$j]}*  2>/dev/null | \
107                         grep -v part | sort -n -k7 -t'-'>${TMP_FILE}
108
109                 echo
110                 echo -n "# Channel ${CHANNELS[$k]}, "
111                 echo "Bus ${BUSES[$i]}, Port ${PORTS[$j]}"
112                 ${AWK} -F '-' -v ch="${CHANNELS[$k]}" \
113                         '{print ch$7 "\t" $0 }' ${TMP_FILE}
114         done
115 done
116
117 # Restore stdout from fd #8 and close fd #8.
118 exec 1>&8 8>&-
119 rm -f ${TMP_FILE}
120 popd >/dev/null
121
122 if [ ${TRIGGER} ]; then
123         udevadm trigger
124         udevadm settle
125 fi
126
127 exit 0