Figure 1.5 shows the Windows NT storage driver stack. Note that the figure depicts the architectural layering of the drivers, but depending on the situation, one or more layers may or may not be relevant. For example:
All layers are relevant when I/O is done to a physical disk such as an IDE or SCSI disk. The class and port layers are needed here, as are the file system and volume management layers. All of these layers are explained later in this section.
The volume management and file system layers are not relevant when I/O is done to a tape device.
Sections 1.7.1 through 1.7.7 explain the bus, port, and class, volume management, file system, and filter drivers shown in Figure 1.5.
A Windows NT
exposes functionality provided by a bus for the benefit of other drivers. The
implements device-specific functionality and insulates a class driver from the specifics of the hardware. A port driver
implement a set of specified functionality for the benefit of the class driver and
implement additional functionality. A port driver receives IRPs and
Windows NT ships with some predefined port drivers, including SCSIPort and 1394. Windows Server 2003 ships with an additional port driver called the Storport driver. For now, suffice to say that whereas the SCSIPort driver caters to older SCSI-2 and earlier devices, the Storport driver is intended to cater to
Port drivers in
A class driver implements general device-independent support for a range of devices. A class driver depends on either miniclass drivers or miniport drivers to provide device-specific functionality. Storage class drivers in particular are used to handle both SCSI and non-SCSI devices. Among other functions, a class driver does the following:
Creates a device FDO. An FDO is needed to use a device. Examples of data in the FDO include details of disk organization (partition table) and the DVD region.
Validates I/O request parameters.
In particular, a storage class driver also does the following:
Splits large read or write requests (received via IRP_MJ_READ and IRP_MJ_WRITE IRPs, respectively) into smaller multiple requests as needed to meet the capacity of the underlying HBA adapter.
Receives IRPs and
Plays an important role in power management, adding and removing devices, and setting timeout values for I/O on devices. In other words, storage class drivers are heavily involved in implementing PnP and power management.
Class drivers interact with port drivers at the next
Examples of storage class drivers in Windows NT include disk, tape, and CD-ROM class drivers; these can deal with various types of devices, including SCSI, IDE, USB, and 1394 devices.
From the point of view of the I/O Manager, a storage class driver is just like any other driver, so the storage class driver must follow all the requirements, such as having I/O startup, unload, and completion routines, and so on.
A storage class driver often behaves like a bus driver, enumerating child devices. A good example is the disk class driver (disk.sys) that reads the partition table on the disk and creates a device object for each disk partition that it finds.
Some class drivers define a miniclass driver interface. A miniclass driver, typically written by an independent hardware vendor, is simply a kernel mode DLL that interfaces with the class driver, typically provided by Microsoft. The miniclass driver registers its hardware adapters with the class driver, and the class driver creates a device object for each registered adapter. The miniclass driver does not have a device object and simply uses the device object of the class driver. Miniclass drivers typically help fill out details of the SCSI request blocks that the class driver builds. A good example is the tape miniclass driver.
Interestingly, with Windows 2000, Microsoft introduced a new library called ClassPnP . This library implements all PnP functionality common across class drivers. Some functionality is implemented entirely within the class library. For other functionality, the driver using the class library needs to provide callback routines that the class driver can invoke as needed. All of the Microsoft-provided class drivers (disk, tape, and CD-ROM class drivers) use the services of the ClassPnP library (implemented in the file classpnp.sys). This situation remains true for Windows XP and Windows Server 2003 products as well.
The description of various layers in Figure 1.5 is still incomplete. However, before the discussion of the volume management and file system layers, it will be useful to deviate a little and understand the device tree built up by the operating system. A good understanding of the device object tree will make it easier to understand storage-related topics such as high-availability multipath I/O (described in Chapter 9) and
As stated earlier, PnP plays a major role in device enumeration. PnP loads bus drivers one at a time and initiates device enumeration on these buses. As devices are
As drivers load and enumerate the devices for which they are responsible, they report the devices to PnP. PnP builds a tree linking the various driver objects in a proper fashion to show their logical and physical relationships. Note that PnP can only build a tree; it cannot support a device graph. That is, with PnP, a child node can have only a single parent; a node can never have multiple parents.
Figure 1.6 shows a simple configuration in the top left-hand corner. A Windows NT server with a single host bus adapter (HBA) and a single storage disk connected to that HBA. In the interest of keeping things simple and relevant, we will ignore other peripheral devices that would typically be connected to this Windows NT server.
Figure 1.6 shows a detailed overview of just some parts of Figure 1.5. In particular, Figure 1.6 does not show the volume management and file system layers. Figure 1.6 shows just the port and class driver layers corresponding to Figure 1.5. Starting from the bottom right-hand corner of Figure 1.6, the series of steps in building the device tree is as
Notice that two drivers cooperate to create a logical device instance such as the PCI bus driver and the SCSIPort driver. This is logical (as Spock would say), because the device interfaces to the PCI bus on one end and exposes a SCSI interface at the other end. Thus a single device has characteristics of PCI at one end of the card and SCSI at the other end, so it needs processing by both the PCI bus driver and the SCSIPort driver.
We can now return to Figure 1.5 and discuss the volume management layer. Volumes are a logical entity created to facilitate storage management. Physical disks ”for example, an IDE or SCSI disk ”may be logically divided into entities called
. A partition is simply a set of physically contiguous sectors on a disk. Partitions are then combined in some fashion to construct a volume. The advantage is that this combination can result in some enhanced functionality; for example, multiple partitions may be
Windows 2000, Windows XP, and Windows Server 2003 support three different volume managers: FtDisk, Microsoft Logical Disk Manager, and VERITAS Volume Manager. All three are described in detail in Chapter 6. For now, the example will take the simplest of the three, the Microsoft FtDisk Manager. A device tree with the other volume managers is presented in Chapter 6. To keep things simple, the device tree in Figure 1.7 pertains to a situation in which there is a single SCSI disk, organized into two partitions, and the two partitions are concatenated to form a single volume.
To understand how volume managers work, consider Figure 1.7, starting from the bottom right-hand corner. The PnP subsystem and PCI bus drivers cooperate to create the PDO and FDO for the PCI bus. Next the PCI bus driver enumerates devices on the PCI bus and creates a PDO for the SCSI adapter. The SCSIPort driver creates the FDO for the SCSI adapter. Next the SCSIPort port driver and disk class drivers create a PDO and an FDO for the one disk that is present in the system configuration. Until now, the description of Figure 1.7 has simply summarized the description for Figure 1.6.
The Partition Manager is an
Newly introduced in Figure 1.7 (as compared to Figure 1.6) is the Partition Manager. The Partition Manager
The Partition Manager passes details of the device objects it discovers (and "steals") to registered volume managers. For now, the discussion is limited to cases with just one volume manager. Chapter 6 discusses a similar situation, but with multiple volume managers involved. The volume manager inspects the devices represented by the device objects "stolen" by the Partition Manager and either claims or rejects ownership. In the example, the FtDisk driver claims ownership of these device objects. The FtDisk manager then inspects the volume configuration and determines that the volume has a single underlying partition, as well as ownership of the relevant partition. At that point the FtDisk driver will create a device object to represent the volume (called "Volume V01" in Figure 1.7). The file system can then be mounted on this volume. Details of operations involved in mounting a file system are described in Chapter 6.
What is noteworthy here is that there are actually two separate device stacks. One stack represents the logical entity, the volume; the other stack encompasses the physical devices in the system, such as the PCI bus, the SCSI adapter, and the disk drive. The volume manager acts as a bridge between the two stacks.
In Figure 1.7, the FtDisk driver sends all IRPs that it understands directly to the disk class driver. Of course, the FtDisk driver also transforms volume relative offsets to disk relative offsets before it does so. These I/O operations are shown with the thick dashed lines. The thin dotted line shows the private interface between the volume manager and the Partition Manager. In addition, the FtDisk driver sends I/O controls that it does not understand directly to the partition device object. This is shown with dashed-
File system drivers
are Windows NT device drivers that implement file system functionality. Although the file systems reside on physical media such as a disk or CD, the file system drivers
It fills in the next IRP stack location with necessary information to complete the I/O. Then it sends the IRP on to the class driver.
It builds a series of associated IRPs to accomplish the
A file system driver has metadata on the media. The metadata includes things such as file system access permissions and a file allocation table (location on disk). The file system driver receives the IRP that specifies a particular operation relative to a file, reads metadata if needed, and issues an IRP request that is now relative to a disk block rather than to a file. Windows NT ships with several file system drivers, including
FAT file system
Writing file system or file system filter drivers was a black art with Windows NT 3.X. Subsequently, Microsoft made available the Installable File System Kit, which provides necessary header files, some documentation, and samples for writing file system and file system filter drivers.
Both file system and file system filter drivers need to implement support for PnP IRPs, including power management, removal of media, and removal of the storage device itself, such as an external USB floppy.
Filter drivers are drivers that layer themselves over some device objects and perform preprocessing and/or postprocessing of I/O requests in order to modify the system behavior. Filter drivers are typically used for the following reasons:
To provide modularized functionality ”for example, CD-ROM audio filter driver
To add functionality such as CD-ROM burning/writing to a device
To add functionality to a file system ”for example, file system encryption filter drivers, reparse point filter drivers, and Single Instance Storage filter drivers (all of which are described in Chapter 6)
To add functionality such as AGP support and ACPI BIOS extensions support, both done through filter drivers, to a bus
To adjust I/O for hardware functionality
Filter drivers always create a device object that is attached to either a functional device object or a physical device object (both described in Section 1.4.2). This object is essential to the ability of the filter driver to receive I/O requests and perform pre- and/or postprocessing on the I/O request. Some filter drivers create a secondary device object, often called a control device object (CDO) because it is used to send control/management information to the filter driver from an
Lower filter drivers are much more difficult to write than upper filter drivers. One technical issue is related to deciding which errors should be propagated and from which particular I/O operations. Another problem is that all of the available samples relate to upper filter drivers, and hence no samples are available for lower filter drivers. In the rare instances that lower filter drivers are used, they provide protocol converter functionality or functionality to work around a particular device limitation.
Filter drivers have existed in Windows NT since the first commercial release of the operating system. The Windows NT Installable File System (IFS) Kit (http://www.microsoft.com/ddk/IFSKit) documents the filter driver architecture and is a good reference for developers.
Starting with Windows 2000, a significant change has been made in the way filter drivers are loaded. Previously, the person writing the filter driver had to do some extra work to make sure that the driver was loaded at the correct time. If the driver is loaded too early, the device to which the filter driver wants to attach will not yet have been created. If the driver is loaded too late, the device to which the driver wants to attach may already be claimed and attached to by another driver, forcing the filter driver to attach itself higher up the driver stack than it would like. With Windows 2000, the driver writer specifies whether the filter driver is above or below a particular functional or physical device object, and the Plug and Play Manager loads the driver at the correct time.
Ironically, Microsoft may have made creating a filter driver too easy. The driver stack chain is becoming a bit crowded, with implications for performance and memory hits (each IRP needs more stack locations, and IRPs are allocated out of nonpaged memory). Consider the known filter drivers already being loaded (these are discussed later in the book):
Encrypting file system (EFS) filter driver
Hierarchical Storage Management/Remote Storage Services filter driver
Single Instance Store (SIS) for Remote Installation Services (RIS) filter driver
Reparse point filter drivers that other vendors may have written
Virus-checking software filter drivers
On the other hand, writing a filter driver is also rather difficult. Consider a driver that wants to do some very simple encryption on data as it is written to disk and read from disk. All this driver really wants is to have a facility that allows it access to buffers before they are written and after they have been read. But the driver writer does not have a facility for simply registering a callback that accomplishes the desired functionality quickly. The driver writer needs to deal with all kinds of overhead, including handling