3 # provide the shortest possible unique hardware path to a device
4 # for the Linux Persistent Device Naming scheme
6 # Copyright (C) 2005-2006 SUSE Linux Products GmbH
8 # Hannes Reinecke <hare@suse.de>
10 # This program is free software; you can redistribute it and/or modify it
11 # under the terms of the GNU General Public License as published by the
12 # Free Software Foundation version 2 of the License.
14 # to be called from a udev rule to return the name for a symlink
15 # DEVPATH=<devpath>; path_id
18 # examples for all block devices on a system:
19 # for i in `find /sys/class/block`; do DEVPATH="`echo $i | sed -e 's@^/sys\|/dev@@g'`"; path_id; done
26 full_sysfs_device_path=
28 if [ -z "$DEVPATH" -a -z "$1" ] ; then
32 if [ -z "$DEVPATH" ] ; then
43 if [ ! -e $SYSFS$DEVPATH/dev ] ; then
49 cd "$SYSFS$DEVPATH/subsystem";
55 TYPE="${DEVPATH#/class/}"
67 local type offset port
70 for i in $type[0-9]* ; do
73 if [ "$port" -lt "$offset" ] ; then offset=$port ; fi
84 while [ ! -z "$host_dev_path" ] ; do
85 case "$host_dev_path" in
87 host_dev_path=${host_dev_path%/*}
103 platform_id=${DEV##*/}
105 while [ ! -z "$host_dev_path" ] ; do
106 case "$host_dev_path" in
108 host_dev_path=${host_dev_path%/*}
116 d="platform-$platform_id-$d"
118 d="platform-$platform_id"
128 serio_id=${DEV##*/serio}
130 while [ ! -z "$host_dev_path" ] ; do
131 case "$host_dev_path" in
133 host_dev_path=${host_dev_path%/*}
141 d="serio-$serio_id-$d"
152 local port idedev idecontroller
157 idecontroller=${idedev%/*}
158 # port info if the controller has more than one interface
161 : idedev $idedev kernel_port $port
170 echo "Error: $idedev is neither master or slave" >&2
174 offset="`get_port_offset ide ${port%.*}`"
176 : port offset $offset
177 port=$((${port%.*} - $offset))
179 d="ide-${port}:$channel-$d"
181 d="ide-${port}:$channel"
190 local cil controller_port controller_dev
195 target_id=${target_dev##*/target}
198 for tid in ${target_id}* ; do
199 target_num=$(( $target_num + 1 ))
201 controller_port=${target_dev%/*}
202 controller_dev="${controller_port%/*}"
203 : controller_dev $controller_dev
204 : controller_port $controller_port
205 # a host controller may have more than one interface/port
206 controller_port="${controller_port##*/host}"
209 controller_offset=$(get_port_offset host $controller_port)
211 controller_port=$(( $controller_port - $controller_offset))
212 scsi_id="scsi-${controller_port}:${cil}"
225 if [ -f "$D/ieee1394_id" ] ; then
226 read ieee1394_id < $D/ieee1394_id
228 if [ -z "$ieee1394_id" ] ; then
233 fw_host_dev=${DEV%/fw-host*}
234 # IEEE1394 devices are always endpoints
235 d="ieee1394-0x$ieee1394_id"
243 local cil controller_port controller_dev
245 fc_tgt_hcil="${DEV##*/}"
246 fc_tgt_lun="${fc_tgt_hcil##*:}"
247 fc_tgt_path="${DEV%/*}"
248 fc_tgt_num="${fc_tgt_path##*/}"
249 fc_tgt_dev="${fc_tgt_path}/fc_transport:${fc_tgt_num}"
250 if [ -e "$fc_tgt_dev/port_name" ]; then
251 read wwpn < $fc_tgt_dev/port_name
253 if [ -z "$wwpn" ] ; then
259 # Linux currently knows about 32bit luns
260 tmp_lun3=$(printf "%04x" $(($fc_tgt_lun & 0xFFFF)))
261 tmp_lun2=$(printf "%04x" $(( ($fc_tgt_lun >> 16) & 0xFFFF)))
264 if (($fc_tgt_lun == 0)) ; then
265 lun="0x0000000000000000"
267 lun="0x${tmp_lun3}${tmp_lun2}${tmp_lun1}${tmp_lun0}"
269 controller_dev="${fc_tgt_path%/host[0-9]*}"
270 # FC devices are always endpoints
271 d="fc-${wwpn}:${lun}"
279 local cil adapter controller_dev
281 sas_host_path="${DEV%%/phy*}"
282 sas_phy_path="${DEV#*/host*/}"
283 sas_phy_path="${sas_phy_path%%/target*}"
284 sas_phy_id="${sas_phy_path%%/*}"
285 sas_rphy_id="${sas_phy_path##*/}"
286 sas_phy_dev="/sys/class/sas_phy/${sas_phy_id}"
287 if [ -e "$sas_phy_dev/sas_address" ]; then
288 read phy_address < $sas_phy_dev/sas_address
289 read phy_port < $sas_phy_dev/port_identifier
290 read phy_id < $sas_phy_dev/phy_identifier
292 if [ -z "$phy_address" ] ; then
293 : no initiator address
298 sas_phy_address="$phy_address:$phy_port:$phy_id"
299 sas_rphy_dev="/sys/class/sas_device/${sas_rphy_id}"
300 if [ -e "$sas_rphy_dev/sas_address" ]; then
301 read rphy_address < $sas_rphy_dev/sas_address
302 read rphy_id < $sas_rphy_dev/phy_identifier
304 if [ -z "$rphy_address" ] ; then
305 : no initiator address
310 sas_rphy_address="$rphy_address:$rphy_id"
311 controller_dev="${sas_host_path%/host[0-9]*}"
312 # SAS devices are always endpoints
313 d="sas-${sas_phy_address}-${sas_rphy_address}"
320 local iscsi_session_dir
321 local iscsi_session iscsi_session_path
322 local iscsi_connection iscsi_connection_path
324 iscsi_session_dir="${DEV%%/target*}"
325 iscsi_session="${iscsi_session_dir##*/}"
326 iscsi_session_path=/sys/class/iscsi_session/${iscsi_session}
327 if [ ! -d "$iscsi_session_path" ] ; then
328 : no iSCSI session path
332 # Currently we're not doing MC/S
333 for conn in ${iscsi_session_dir}/connection* ; do
334 iscsi_conn_num=${conn##*:}
335 if [ "$iscsi_conn_num" = '0' ] ; then
336 iscsi_connection=$(basename $conn)
339 if [ -z "$iscsi_connection" ] ; then
340 : no iSCSI connection found
344 iscsi_connection_path=/sys/class/iscsi_connection/${iscsi_connection}
345 if [ ! -d "$iscsi_connection_path" ] ; then
346 : no iSCSI connection path
350 if [ -e "${iscsi_session_path}/targetname" ]; then
351 read iscsi_tgtname < ${iscsi_session_path}/targetname
353 if [ -z "$iscsi_tgtname" ] ; then
354 : No iSCSI Targetname
358 if [ -e "${iscsi_connection_path}/persistent_address" ] ; then
359 read iscsi_address < ${iscsi_connection_path}/persistent_address
361 if [ -z "$iscsi_address" ] ; then
362 : No iSCSI Target address
366 if [ -e "${iscsi_connection_path}/persistent_port" ] ; then
367 read iscsi_port < ${iscsi_connection_path}/persistent_port
369 d="ip-${iscsi_address}:${iscsi_port}-iscsi-${iscsi_tgtname}"
379 port_num=${port_id#*-}
381 while [ ! -z "$host_dev_path" ] ; do
382 case "$host_dev_path" in
384 usb_host_path=$host_dev_path
385 host_dev_path="${host_dev_path%/*}"
392 : host_dev_path $host_dev_path
393 usb_host_num=${usb_host_path##*/usb}
396 usb_host_offset=$(get_port_offset usb $usb_host_num)
397 usb_host_port=$(($usb_host_num - $usb_host_offset))
400 d="usb-$usb_host_port:$port_num-${d}"
402 d="usb-$usb_host_port:$port_num"
409 full_sysfs_path="$SYSFS$DEVPATH"
410 if [ -L $full_sysfs_path/subsystem ]; then
411 # new sysfs block layout
412 full_sysfs_path="${full_sysfs_path%/*}"
413 cd "$full_sysfs_path/subsystem";
416 subsys="${subsys##*/}"
417 if [ "$subsys" = "block" ]; then
418 # parent is "block", it's a partition, move one up
419 full_sysfs_path="${full_sysfs_path%/*}"
423 # old sysfs block layout
424 if [ ! -L $full_sysfs_path/device ] ; then
425 if [ -f $full_sysfs_path/range ] ; then return ; fi
426 full_sysfs_path="${full_sysfs_path%/*}"
427 : full_sysfs_path "$full_sysfs_path"
428 if [ ! -L $full_sysfs_path/device -o ! -f $full_sysfs_path/dev ] ; then
432 cd $full_sysfs_path/device
434 full_sysfs_device_path="`pwd -P`"
436 D=$full_sysfs_device_path
437 while [ ! -z "$D" ] ; do
439 */ide[0-9]/[0-9].[0-9]*|*/ide[0-9][0-9]/[0-9][0-9].[0-9]*)
443 if [ -r $full_sysfs_device_path/wwpn ]; then
444 read wwpn < $full_sysfs_device_path/wwpn
446 if [ -r $full_sysfs_device_path/fcp_lun ]; then
447 read lun < $full_sysfs_device_path/fcp_lun
449 if [ -r $full_sysfs_device_path/hba_id ]; then
450 read bus_id < $full_sysfs_device_path/hba_id
452 if [ "$bus_id" -a "$wwpn" -a "$lun" ]; then
454 d="ccw-$bus_id-zfcp-$wwpn:$lun"
465 */rport-[0-9]*:[0-9]*-[0-9]*/*)
468 */phy-[0-9]*:[0-9]*/*)
478 */host[0-9]*/[0-9]*:[0-9]*:[0-9]*:[0-9]*)
481 */usb[0-9]*/[0-9]*/*)
503 if [ "$TYPE" = "scsi_tape" ] ; then
504 devname=${full_sysfs_path##*/}
505 rewind="${devname%%st*}"
506 mode="${devname##*st}"
522 d="$d-${rewind}st${mode}"