There are several things in Linux that make dealing with block devices much stranger than one would hope. Here's the ones I can think of quickly:
Depending on which subsystem is implementing a block device, there are several differences in the way block devices and their partitions are manifest:
- device node numbering
There are several schemes for numbering device nodes
- major number with assigned minors (sda is 8:0, sda1 is 8:1 , sdb is 8:16 ) This means you're limited to 15 partitions on scsi devices, and 63 for "ide" when not using libata.
- major number is in /proc/devices, minor numbers are assigned at device creation
- ioctl() calls
The kernel's internal partitioning scheme is managed with some IOCTLs, such as BLKRRPART, BLKPG/BLKPG_ADD_PARTITION, and BLKPG/BLKPG_DEL_PARTITION, which only work on some devices. They work on hd* (ide without libata), sd* (scsi), md_d* (partitionable md), but not on md (non-partitionable md) or device-mapper devices (i.e. multipath or dmraid)
- device node naming
There are several schemes for naming devices. These aren't just userland, they're also the related to the names in e.g. /sys/block/ (${driver} below is not necessarily the name of the driver, but rather an identifying tag it uses)
- (cciss, sx8, etc.):
/dev | /dev/${driver}/c${controller}d${drivenumber}[p${partnumber}] |
/sys | /sys/block/${driver}!c${controller}d${drivenumber}[/${driver}!c${controller}d${drivenumber}p${partnumber}] |
- (sd, hd):
/dev | /dev/${driver}${diskletter}[${partnumber}] |
/sys | /sys/block/${driver}${driveletter}[/${driver}${driveletter}${partnumber}] |
- md (no partitions):
/dev | /dev/md${mdnumber} |
/sys | /sys/block/md${mdnumber} |
- mdp (partitionable md):
/dev | /dev/md_d${mdpnumber}[p${partnumber}] |
/sys | /sys/block/md_d${mdpnumber}[/md_d${mdpnumber}p${partnumber}] |
- lvm (no partitions, dm device):
/dev | all of: |
/dev/dm-${dmnumber} (a real block device node} | |
/dev/mapper/${volgroupname}-${logvolname} (a real block device node) | |
/dev/${volgroupname}/${logvolname} (a symlink into /dev/mapper) | |
/sys | /sys/block/dm-${dmnumber} |
- dmraid and mpath (partitioned dm device):
both the main device and the partitions are device-mapper rules; the partitions don't show up in /proc/partitions, etc.
/dev | all of: |
/dev/dm-${dmnumber} (a real block device node) | |
/dev/${arbitrary name}[${arbitrary part delimiter}${arbitrary part specifier, usually an integer}] (usually a real block device node for a dm object) | |
/sys | /sys/block/dm-${dmnumber} |
- loopback devices:
/dev | /dev/loop${loopnumber} (just the loopback device) |
/dev | /dev/loop${loopnumber}${arbitrary part delimiter}${arbitrary part specifier} (partition, via device-mapper, created by e.g. kpartx) |
/sys | /sys/block/loop${loopnumber} |
/sys | /sys/dm-${dmnumber} (for a partition) |
- sysfs wackiness
sysfs has /sys/block/$device/{holders,slaves} directories to represent which devices depend on which others. If a device uses the kernel's partitioning, these don't reflect the device<->partition relationship.
- hotplug wackiness
When a device is added, you get a bunch of hotplug events. The last one for a particular block device has SUBSYSTEM="block", and is basically the "this device is ready" event. SCSI devices (including SATA and PATA with libata) have a files /sys/block/$device/{device,model}. These don't get probed until after the hotplug event. Also, UUIDs/serial numbers/etc aren't probed at all.
- probing of md/mdp devices
two weird things here:
- to activate an md or mdp device, you have to mknod it first, then use mdadm on the created node.
- mdp's _partitions_ show up the normal ways (i.e. uevents to notify userland)
- md0 always exists (i.e. there's always a /sys/block/md0), even before you activate any devices.
I'm sure there's more here that sucks.