Tuesday, October 10, 2017

Disk naming

This topic may be technically verbose due to its nature.
In the past this knowledge was much more common and relevant.
Nowadays new technologies such as ZFS have greatly simplified matters.

Anyway, when dealing with local hardware (interfaces, buses, controllers, disks) and even remote storage (SAN) it's inevitably necessary to possess at least a basic understanding of the overall scheme adopted by Solaris when abstracting these kind of peripheral devices and remote storage resources.

I've always found this topic somewhat difficult to understand because no-one had enough patience or sufficiently broad understanding at the time to present me a reasonable big picture of things. That's why I'm now attempting to fulfill this gap by writing down my current knowledge on this matter and hopefully better paving the way for others interest on this subject too.

To summarize, all or most of these details get reflected on the disk naming schemes adopted by the system which one perceives while dealing with disks devices for ZFS storage pools. The most elementary example comes from the format command. For instance:

# echo |format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0. c1t0d0 ...
          /pci@0,0/pci8086,2829@d/disk@0,0
       1. c1t1d0 ...
          /pci@0,0/pci8086,2829@d/disk@1,0
       2. c1t2d0 ...
          /pci@0,0/pci8086,2829@d/disk@2,0
       3. c1t3d0 ...
          /pci@0,0/pci8086,2829@d/disk@3,0
       4. c1t4d0 ...
          /pci@0,0/pci8086,2829@d/disk@4,0
       5. c4t3d0 ...
          /pci@0,0/pci1000,8000@14/sd@3,0
       6. c5t7d0 ...
          /pci@0,0/pci1000,8000@16/sd@7,0


 At the very first time this information may seem quite complex!
  • What's the meaning of c1t0d0 ?
  • Worse, what the heck is /pci@0,0/pci8086,2829@d/disk@0,0 ?

Well, to start:
 
  • The first is a logical (disk) name.
    A system-wide convenient disk name simplification.
    Actually, a symbolic link at /dev/rdsk mapping into /devices.
       
  • The second is a physical (device) name.
    A file path abstraction associated to a hardware component.
    Such paths are rooted at the /devices special file-system.

LOGICAL NAMES

Let's first dig into the simpler logical names.
Logical names obey the more simple format:
c?[t?]d?[s?|p?]
Where each portion identifies the following:
c - controller #  (logical)
    Some identification assigned by the system.
    Not necessarily related to any physical ordering.

t - bus target # (physical)
    Optional: present only on bus-oriented controllers.
    Not present for direct controllers (which don't have a bus).
    Important to SCSI, iSCSI, SAS and SATA.

dLUN # (physical)

    Always 0, except when many LUNs exist on a single bus.
    For SCSI, SAS and SATA, always 0.

s - slice #
    Usually from 0 thru 6. Optional. Mutually exclusive with p.
    Slice 2 (s2) "conventionally" means the whole disk.
    Legacy; important for old SMI (VTOC) disks.

p - fdisk partition # (i86pc only)
    Ranging from 0 thru 4. Optional. Mutually exclusive with s.
    Partition 0 (p0) means the whole disk.
    Legacy; used with PCFS on some USB devices.
 
PHYSICAL NAMES

A physical name is much more difficult to understand, not necessarity with respect to its format, but to its relationship in system internals.

One can start by looking up the logical name:

# l /dev/rdsk/c1t0d0
l...  ... /dev/rdsk/c1t0d0 

       -> /devices/pci@0,0/pci8086,2829@d/disk@0,0:wd,raw

Looking at the physical name, in reverse order, one sees:
  1. The raw suffix.
    Any references to this entry means using the the device as a character device, in other words, as in a byte-by-byte mode.This raw view of the device is depicted by the letter r in rdsk device path name component.
      
  2. The wd suffix.
    I deduce this is an abbreviation to whole-disk.
    This deduction comes from the following straightforward observation:
     
    # prtconf -v |ggrep -B2 /dev/rdsk/c1t0d0 \
                 |grep -v spectype \
                 |tr -s ' '

     dev_path=/pci@0,0/pci8086,2829@d/disk@0,0:a,raw
     dev_link=/dev/rdsk/c1t0d0s0
    --
     ...
    --
     dev_path=/pci@0,0/pci8086,2829@d/disk@0,0:g,raw
     dev_link=/dev/rdsk/c1t0d0s6
    --
     dev_path=/pci@0,0/pci8086,2829@d/disk@0,0:q,raw
     dev_link=/dev/rdsk/c1t0d0p0
    --
     ...
    --
     dev_path=/pci@0,0/pci8086,2829@d/disk@0,0:u,raw
     dev_link=/dev/rdsk/c1t0d0p4
    --
     dev_path=/pci@0,0/pci8086,2829@d/disk@0,0:wd,raw
     dev_link=/dev/rdsk/c1t0d0
     
       
  3. A series of device path components denoting hardware nodes.
    The general form is: hardware-node@address.
    In the example:
     
      disk@0,0
      pci8086,2829@d
      pci@0,0
     

    The disk component is the most important one.
    Its general form is: disk@bus-target-#,LUN-#.
     
    Furthermore, the whole path is associated to a device-driver:
     
    # grep /pci@0,0/pci8086,2829@d/disk@0,0 /etc/path_to_inst
    "/pci@0,0/pci8086,2829@d/disk@0,0" 0 "sd"


    The device-driver name could also have been found by inspecting the entry's major-number (driver), 214, present on the special devfs file-system type of /devices
     
    # l /devices/pci\@0\,0/pci8086\,2829\@d/disk\@0\,0:wd,raw
    c...  214,  7  ...  /.../pci@0,0/pci8086,2829@d/disk...

     
    # grep 214 /etc/name_to_major |cut -d' ' -f1
    sd

    Just for completeness, in the example above, note that 7, to the right of 214, is the minor-number, denoting the driver instance unique id for that specific device.

    The controller's assigned # is undocumented, hence it's nearly impossible to fully understand something about that. With 4 SATA, 1 SCSI and 1 SAS disk, one gets:

    # prtconf -v |ggrep -B5 /dev/cfg \
                 |ggrep -E -v 'spectype|\(' \
                 |tr -s ' '

     dev_path=/pci@0,0/pci8086,2829@d:devctl
     dev_path=/pci@0,0/pci8086,2829@d:0
     dev_link=/dev/cfg/sata0/0
     dev_path=/pci@0,0/pci8086,2829@d:1
     dev_link=/dev/cfg/sata0/1
     dev_path=/pci@0,0/pci8086,2829@d:2
     dev_link=/dev/cfg/sata0/2
     dev_path=/pci@0,0/pci8086,2829@d:3
     dev_link=/dev/cfg/sata0/3
     dev_path=/pci@0,0/pci8086,2829@d:4
     dev_link=/dev/cfg/sata0/4
    --
     dev_path=/pci@0,0/pci1000,8000@14:devctl
     dev_path=/pci@0,0/pci1000,8000@14:scsi
     dev_link=/dev/cfg/c4
    --
     dev_path=/pci@0,0/pci1000,8000@16:devctl
     dev_path=/pci@0,0/pci1000,8000@16:scsi
     dev_link=/dev/cfg/c5
That's a reasonable kick-off, isn't it?