This article talks about how the device number management works in Linux block subsystem. However, the idea applies to character device number management too.
Note: I am referring to linux-3.17 source code.
The purpose of introducing device number management mechanism is to efficiently obtain the corresponding kobject by a given device number, then gendisk instance that represents the whole disk.
When creating a block device file under /dev/, the generic block layer uses the dev_t to find the corresponding gendisk, and then initializes the inode and block_device structures by gendisk instance.
First, I’d like to introduce the basic struct kobj_map in drivers/base/map.c:
There are total 255 probe entries in each kobj_map object. The probe instances of the same entry is linked by next pointer. One probe instance is unique according to dev and range parameters.
Then which entry should a device number be put is decided by the value of device major % 255, as a result, some device numbers will be placed in the same entry. And each of them has a probe instance, and is linked. The probe instances of the same device number is sorted by the range value, which make sure the most accurate instance overrides others and matches first when lookup.
For block subsystem, the kobj_map is defined in genhd.c:
Second, I’ll talk about how the device numbermanagement works in block subsystem.
1. bdev_map initialization
bdev_map is initialized during generic block layer initialization in genhd_device_init() defined in genhd.c:
Function kobj_map_init() is defined as below:
From the code fragment, we can see all the probe entries are malloc and initialized by default value.
2. device number registration
Any block device driver can call blk_register_region() to register the device number and region. Actually blk_register_region packages kobj_map() with bdev_map as kobj_map parameter.
Kobj_map() will create one probe instance that is set by the function input and inserted to bdev_map probe entries based on the devt and range values. What’s more, the probe function pointer and data is saved in probe instance, and will be used to obtain kobject instance when lookup.
For disk device, the input data value is gendisk instance, the probe function is exact_match() that converts gendisk to the corresponding kobject.
3. device number lookup
Block device driver calls get_gendisk() to obtain the gendisk instance based on the device number. get_gendisk() calls to kobj_lookup() to find the kobject in bdev_map.
Now, we know how the device number management works, and how the device number and gendisk instance get connected in Linux Block subsystem.