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:

wKioL1Yo0fCiTrxlAAFPlgZRX8M867.jpg

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:

wKiom1Yo0g7iJmUWAAArsxYGPAM961.jpg


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:

wKioL1Yo0mryTKDuAABRoOr8LaA225.jpg

Function kobj_map_init() is defined as below:

wKiom1Yo0nnBJWoiAAJlQiDCEgw142.jpg

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.

wKioL1Yo0sqgXJ-rAAILQsQruL4011.jpg

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.

wKioL1Yo0vzgGbFqAAMnMdPv9V4409.jpg

Now, we know how the device number management works, and how the device number and gendisk instance get connected in Linux Block subsystem.