Mapping the representations of a SCSI device in sysfs

Red Hat Enterprise Linux 9.2 LPAR mode z/VM guest

Each SCSI device that is configured is represented by multiple directories in sysfs, in particular, within the SCSI branch. Only manually configured LUNs are also represented within the zfcp branch.

You can find the FCP device bus-ID, the target WWPN, and the FCP LUN triplet that corresponds to a SCSI device in two ways: By traversing the sysfs directory tree or by using commands.
Note: The zfcp-specific sysfs attributes hba_id, wwpn, and fcp_lun are deprecated. Use the methods described here instead to find the addressing of a SCSI device.

About this task

The directory in the sysfs SCSI branch has the following form:
/sys/bus/scsi/devices/<scsi_host_no>:0:<scsi_id>:<scsi_lun>
where:
<scsi_host_no>
is the SCSI host number that corresponds to the FCP device.
<scsi_id>
is the SCSI ID of the target port.
<scsi_lun>
is the LUN of the SCSI device.

The value for <scsi_lun> depends on the storage device. Often, it is a single-digit number, but for some storage devices it has numerous digits.

For manually configured FCP LUNs, see Manually configured FCP LUNs and their SCSI devices for details about the directory in the zfcp branch.

Before you begin

You must identify the SCSI device in sysfs. For example, use readlink to find the path in sysfs with all symbolic links resolved:
# readlink -e /sys/bus/scsi/devices/2:0:1:1074741413
/sys/devices/css0/0.0.000a/0.0.1800/host2/rport-2:0-1/target2:0:1/2:0:1:1074741413

Using sysfs

Note: Do not assume a stable sysfs structure. The following procedure accommodates changes in sysfs.
This example shows how you can traverse the directory tree to find the FCP device bus-ID, the target WWPN, and the FCP LUN that correspond to a SCSI device name. The example assumes:
SCSI device
2:0:1:1074741413
FCP LUN
0x40a5400f00000000
target WWPN
0x50050763030bd327
FCP device bus-ID
0.0.1800
  1. Obtain the hexadecimal FCP LUN.
    1. Start at the SCSI device directory or anywhere in the subtree below the SCSI device. Ascend the sysfs tree until you find the SCSI device. To do this, test every subdirectory for a symbolic link named subsystem that points to a relative directory path whose last entry is scsi. Search for the symbolic link named subsystem:
      # ls -dl subsystem
      lrwxrwxrwx 1 root root 0 Oct 19 16:08 subsystem -> ../../../../../../../../bus/scsi
      The subsystem symbolic link points to a directory tree where the last subdirectory is scsi.
    2. Confirm that this is a SCSI device by reading the DEVTYPE line within the uevent attribute. The value must be scsi_device.
      # grep "^DEVTYPE=" uevent
      DEVTYPE=scsi_device
      The last part of the current directory name is then the decimal SCSI LUN, for example, assuming you have found this directory:
      # pwd 
      /sys/devices/css0/0.0.000a/0.0.1800/host2/rport-2:0-1/target2:0:1/2:0:1:1074741413
      
      Here, the SCSI LUN is 1074741413.
    3. Transform the SCSI LUN to the FCP LUN as follows:
      Step Example
      Take decimal LUN in decimal notation: 1074741413
      Convert to hexadecimal notation: 0x400f40a5
      Pad with 0 from the left to obtain a 64-bit value: 0x00000000400f40a5
      Divide into 16-bit blocks (LUN levels): 0x0000|0000|400f|40a5
      Reverse the order of the blocks: 0x40a5|400f|0000|0000
      The resulting hexadecimal number is the FCP LUN: 0x40a5400f00000000
      The Linux kernel function int_to_scsilun() in drivers/scsi/scsi_common.c converts a decimal SCSI LUN to obtain the hexadecimal FCP LUN according to this algorithm. The conversion works in both directions.
    4. Confirm that the path includes a directory rport-<no>. For example, assuming you have found this directory:
      # pwd 
      /sys/devices/css0/0.0.000a/0.0.1800/host2/rport-2:0-1/target2:0:1/2:0:1:1074741413
      
      If there is no rport directory, the transport is not fibre channel and thus not zfcp-related. Abandon the search.

    Table 1 lists the libudev functions that you can use instead of manually traversing the sysfs.

    Table 1. Useful udev functions
    Name Task
    udev_device_get_parent() Ascend the sysfs tree.
    udev_device_get_subsystem() Retrieve subsystem name.
    udev_device_get_devtype() Retrieve device type.
    udev_device_get_syspath() Check if rport is a subdirectory.
  2. Obtain the target WWPN.
    1. Continue ascending the sysfs tree the same way until you find the SCSI target. To do this, test every subdirectory for a symbolic link named subsystem that points to a relative directory path whose last entry is scsi. Search for the symbolic link named subsystem:
      # ls -dl subsystem
      lrwxrwxrwx 1 root root 0 Oct 19 16:08 subsystem -> ../../../../../../../bus/scsi
      
    2. Confirm that this is a SCSI target by reading the DEVTYPE line within the uevent attribute. The value must be scsi_target.
      
      # grep "^DEVTYPE=" uevent
      DEVTYPE=scsi_target
      For example, assuming you have found this directory:
      # pwd
      /sys/devices/css0/0.0.000a/0.0.1800/host2/rport-2:0-1/target2:0:1
    3. The SCSI target has a subdirectory fc_transport. Descend this subtree until you find a subdirectory that matches the SCSI target name. In this example, you would descend to fc_transport/target2:0:1.
    4. In the found target, read the port_name attribute:
      # cat port_name
      0x50050763030bd327

      The value of the port_name is the target WWPN.

    Table 2. Useful udev functions
    Name Task
    udev_device_get_parent_with_subsystem_devtype(dev, scsi, scsi_target) Find the SCSI target.
    udev_device_new_from_subsystem_sysname (udev_device_get_udev(scsidev), "fc_transport", udev_device_get_sysname(targetdev)) Find a matching target in the fc_transport branch.
    udev_device_get_sysattr_value() Read the port_name attribute.
  3. Obtain the FCP device-bus ID. Keep ascending the sysfs tree. Search for the symbolic link "subsystem" that points to a relative path where the last subdirectory is ccw.
    For example:
    # ls -dl subsystem
    lrwxrwxrwx 1 root root 0 Oct 19 16:08 subsystem -> ../../../../bus/ccw
    Then the name of the last directory in the current path is the FCP device-bus ID, for example:
    # pwd
    /sys/devices/css0/0.0.000a/0.0.1800
    Here, 0.0.1800 is the FCP device-bus ID.

Using commands

To map a SCSI device name to its corresponding FCP device bus-ID, target WWPN, and LUN, you can use one of the following commands. The example assumes:
SCSI device
2:0:1:1074741413
FCP LUN
0x40a5400f00000000
target WWPN
0x50050763030bd327
FCP device bus-ID
0.0.1800
  • Use the lszfcp with the -D option to list the FCP device-bus ID, the target WWPN, and the FCP LUN for all SCSI devices. For example:
    lszfcp -D
    ....
    0.0.1800/0x50050763030bd327/0x40a5400f00000000 2:0:1:1074741413
    ....
  • Use the lszdev command on device type zfcp-lun devices, and display the ID and ATTR:scsi_dev columns. For example:
    # lszdev zfcp-lun -a -c ID,ATTR:scsi_dev
    ID                                             ATTR:scsi_dev
    ...
    0.0.1800:0x50050763030bd327:0x40a5400f00000000 2:0:1:1074741413
    ...
  • Use the lsscsi command with the --transport and --lunhex options in verbose mode to get information about a SCSI device:

    # lsscsi -xxtv
    [2:0:1:0x40a5400f00000000]  disk    fc:0x50050763030bd327,0x249900   /dev/sda
      dir: /sys/bus/scsi/devices/2:0:1:1074741413  [/sys/devices/css0/0.0.000a/0.0.1800/host2
                                                    /rport-2:0-1/target2:0:1/2:0:1:1074741413]
    ...
    For details about the lsscsi command, see the man page.
Note: The details of the command output is subject to change. Do not rely on the output always being exactly as shown.

Figure 1 illustrates the sysfs structure of a SCSI device and how it corresponds to the lszfcp command output.

Warning: Do not rely on the sysfs structure in the example. The sysfs structure changes without notice.
Figure 1. Example SCSI device in sysfs and command output
sysfs structure for a SCSI disk. The device nodes points to a real path with two branches, the block device branch, and the fc_transport branch. Example values are given.