Keeping Track of Block Device Drivers

When a block device file is being opened, the kernel must determine whether the device file is already open. In fact, if the file is already open, the kernel must not initialize the corresponding block device driver.

This problem is as easy as it appears at first look. On the one hand, we stated in the earlier section Section 13.2 that block device files that have the same major number are usually associated with the same block device driver. However, each block device driver that handles more than one minor number can be considered several specialized block device drivers, so this case doesn't create problems. In the rest of this section, when we use the term "block device driver," we mean the kernel layer that handles I/O data transfers from/to a hardware device specified by both a major number and a minor number.

A real complication, however, is that block device files that have the same major and minor numbers but different pathnames are regarded by the VFS as different files, but they really refer to the same block device driver. Therefore, the kernel cannot determine whether a block device driver is already in use by simply checking for the existence in the inode cache of an object for the block device file.

To keep track of which block device drivers are currently in use, the kernel uses a hash table indexed by the major and minor numbers. Every time a block device driver is being used, the kernel checks whether the corresponding block device driver identified by the major and minor numbers is already stored in the hash table. If so, the block device driver is already in use; notice that the hash function works on the major and minor numbers of the block device file, thus it doesn't matter whether the block device driver was previously activated by accessing a given block device file, or another one that has the same major and minor numbers. Conversely, if a block device driver associated with the given major and minor numbers is not found, the kernel inserts a new element into the hash table.

The hash table array is stored in bdev_hashtable variable; it includes 64 lists of block device descriptors. Each descriptor is a block_device data structure whose fields are shown in Table 13-4.

Table 13-4. The fields of the block device descriptor

Type

Field

Description

struct list head

bd hash

Pointers for the hash table list

atomic t

bd count

Usage counter for the block device descriptor

struct inode *

bd inode

Pointer to the main inode object of the block device driver

dev t

bd dev

Major and minor numbers of the block device

int

bd openers

Counter of how many times the block device driver has been opened

struct block device operations *

bd_op

Pointer to the block device driver operation table

struct semaphore

bd sem

Semaphore protecting the block device driver

struct list head

bd_inodes

List of inodes of opened block device files for this driver

The bd_inodes field of the block device descriptor stores the head (the first dummy element) of a doubly linked circular list of inodes relative to opened block device files that refer to the block device driver. The i_devices field of the inode object stores the pointers for the previous and next element in this list.

Each block device descriptor stores in the bd_inode field the address of a special block device inode object for the driver. This inode doesn't correspond to a disk file; rather, it belongs to the bdev special filesystem (see Section 12.3.1). Essentially, the block device inode stores the "master copy" of the information shared by all inode objects of the block device files that refer to the same block device.

Was this article helpful?

0 0

Post a comment