Opening Block Device Files

When a user application opens the device file of a block device, the virtual filesystem invokes the open function of the file_operations structure and arrives at blkdev_open. Figure 6-13 shows the associated code flow diagram.

9Note that this implies that reading data from the block device is already required to work when the device is registered with disk_add!

Figure 6-13: Code flow diagram for blkdev_open.

bd_acquire first finds the matching block_device instance for the device. The pointer to the instance can be read directly from inode->i_bdev if the device has already been used. Otherwise, it is created using the dev_t information. Afterward do_open carries out the main portion of the task, described below. If exclusive access to the block device is requested by setting the flag o_excl, then the block device is claimed with bd_claim. This sets the file instance associated with the device file as current holder of the block device.

Figure 6-14: Code flow diagram for do_open.

The first step of do_open is to call get_gendisk. This delivers the gendisk instance that belongs to the block device. Recall that the gendisk structure describes the partitions of the block device as discussed in Section 6.2.5. However, if the block device is opened for the first time, the information is not yet complete. Nevertheless, the device-specific block_device_operations that are required to work with the device can already be found in the generic hard disk structure.

The kernel then needs to proceed differently depending on the type and state of the block device, as is shown in Figure 6-14. Things are simpler if the block device has been opened before, as can be inferred from the openers count block_device->bd_openers.

□ disk->fops->open invokes the appropriate open function for the file to perform hardware-specific initialization tasks.

□ If the partition information has become invalid as indicated by block_device->bd_invalidated, rescan_partitions is called to re-read the partition information. Partition information can become invalid if a removable medium is exchanged.

If the device has not been opened before, some more work is required. First suppose that not a partition, but the main block device is opened — which may nevertheless contain partitions. In this case, the required actions are modulo some bookkeeping details identical to the case shown above: disk->fops->open handles the low-level work of opening the device, and rescan_partitions reads the partition table if the existing information is invalid.

This is, however, usually the first time that partition information is read in. When a new disk is registered using add_disk, the kernel sets gendisk->bd_invalidated to 1, which signals an invalid partition table on the block device (in fact, since there is no partition table at all, it cannot really be called valid!). Then a fake file is constructed as a parameter passed to do_open, and this, in turn, triggers reading the partition table.

If the opened block device represents a partition that has not been opened before, the kernel needs to associate the block_device instance for the partition with the block_device that contains the partition. Essentially this works as follows:

fs/block_dev.c struct hd_struct *p; struct block_device *whole; whole = bdget_disk(disk, 0);

bdev->bd_contains = whole; p = disk->part[part - 1];

After finding the block_device instance that represents the whole disk that includes the partition, a link between partition and container is set up using block_device->bd_contains. Note that the kernel can find the whole block device starting from the partition's block device, but not vice versa! Additionally, the partition information in hd_struct is now shared between the generic hard disk and the block_device instance for the partition, as indicated in Figure 6-10.

Continue reading here: Request Structure

Was this article helpful?

0 0