Today we are going to discuss the NT Storage Device Stack in brief. I am sure most of you would have encountered a server hang issue where the one of the Antivirus or Storage driver was pointed out to be the root cause of the issue. It is important to understand the layers which are in picture when you are trying to write a file to the disk, because every I/O operation in windows is done via IRPs (I/O Request Packets – Data structures representing the I/O) and these IRPs have to pass through all the layers to achieve the completion of the task and any of these layer can potentially block the I/O from completion mostly due to code bug or at times due to the workload.
NT-based operating system class and filter drivers for peripheral storage devices act as an interface between any intermediate or highest level drivers layered above the class or filter driver and a system-supplied port driver.
I/O requests from a user application or kernel component reach storage class drivers through I/O System Services and one or more intermediate or highest level drivers, such as a file system driver. Storage class drivers translate the standard IRPs they get into IRPs with system-defined SCSI request blocks (SRBs) containing SCSI command descriptor blocks (CDBs) before sending each IRP on to the next-lower driver. A storage port driver translates SRBs from class drivers into bus-specific commands which it sends to the storage HBA, through an I/O bus driver and possibly one or more filter drivers.
The following figure shows the layered architecture of NT-based operating system storage drivers.
NT-Based Operating System Storage Driver Architecture
Starting from the bottom of the figure, the following describes each type of storage driver:
1. A storage port driver defines an interface to all Windows NT storage class drivers, including the system-supplied disk, tape, CDROM, DVD, and changer class drivers. This port/class interface insulates class drivers from adapter-specific requirements of the host bus adapter to which their respective devices are connected. A storage port driver also synchronizes access to the bus for all drivers of devices on the corresponding HBA. The system supplies storage port drivers for SCSI, IDE, USB and IEEE 1394 adapters.
A storage port driver receives SRBs from the next higher driver (a storage class driver or intervening filter driver) and processes them as follows:
· The storage port driver for a SCSI bus passes SRBs with CDBs on to an operating system-independent, HBA-specific SCSI miniport driver, which is dynamically linked to the SCSI port driver and provides hardware-specific support for a particular SCSI HBA. For information about implementing a SCSI miniport driver, see SCSI Miniport Drivers.
· The storage port driver for an IDE/ATAPI or IEEE 1394 bus translates the SRBs received from the storage class driver into the format required by the underlying adapter—for example, repackaging CDBs according to a bus-specific transport protocol, or translating them into a different format, thereby insulating upper level drivers from peculiarities of the underlying bus.
2. An upper or lower storage filter driver supports device-specific functionality not provided by a system-supplied storage class driver. A lower filter storage driver monitors SRBs and/or IRPs issued by a storage class driver and modifies them as needed before passing them to the next-lower driver (a storage port driver or another storage filter driver).
For information about implementing a storage filter driver, see Storage Filter Drivers.
3. A storage class driver uses the SCSI port/class interface to control a device of its type on any bus for which the system provides a storage port driver. A class driver is specific to a particular class of device—for example, one class driver can run all CD-ROM devices on any supported bus; another can control all disk devices. The storage class driver handles I/O requests from user applications or drivers higher in the storage stack by building SRBs containing CDBs and issuing those SRBs to the next-lower driver (a storage port driver or intervening filter driver), just as if the device were a SCSI device.
The implementation of a storage class driver is transparent to upper level drivers. A class driver for a tape or medium changer device is implemented as a device-specific miniclass driver that links to a system-supplied class driver. System-supplied class drivers for other storage devices, such as disk and CD-ROM/DVD, are implemented as single monolithic drivers.
4. An upper filter storage driver intercepts IRPs from user applications and drivers higher in the storage stack and then possibly modifies them before passing them to the next-lower driver (a storage class driver or another storage filter driver). Filter drivers typically monitor performance of the underlying device.
The type of bus to which a device is attached and the implementation of its storage port driver are transparent to upper level drivers. A storage port driver might be implemented according to the port/miniport driver architecture, like the SCSI port driver; as a monolithic driver that controls a single, standard piece of hardware, such as the IDE/ATAPI port driver; or as a filter driver that translates SRBs into the format required by a different driver stack, such as the IEEE 1394 port driver.
Storage Drivers and Device Objects
The storage device stack consists of a tree of device objects created by the drivers that are involved in handling I/O to storage devices on the system. The root of this tree is a functional device object (FDO) for a storage adapter or for another driver stack integrated with the storage stack. The leaves of this tree are device objects for use by file systems and user-mode applications.
A PDO (Physical Device Object) or FDO (Functional Device Object) are simply the logical representation of the actual devices via a datastructure in the Windows Kernel. Only the Storage Miniport driver which plugs into the Storage Port Driver is aware of the actual device functionality and layout. The port driver creates a physical device object (PDO) to represent the physical port. Each class driver creates its own functional device object (FDO) to represent the keyboard or mouse device as a target for I/O requests.
Like any PnP driver, a storage class or storage filter driver adds itself to the tree in its AddDevice routine by creating a device object with IoCreateDevice and attaching it to the device stack with IoAttachDeviceToDeviceStack, using the pointer to the device object passed to the driver’s AddDevice routine by the PnP manager at initialization. IoAttachDeviceToDeviceStack attaches the new device object to the current top of the device stack.
Storage port drivers create physical device objects (PDOs) of type FILE_DEVICE_MASS_STORAGE. The disk class, CD-ROM class, tape class and changer class drivers create FDOs of types FILE_DEVICE_DISK, FILE_DEVICE_CD_ROM, FILE_DEVICE_TAPE, and FILE_DEVICE_CHANGER respectively.
The example below gives a perspective on how a Storage Device Stack is layered is below.
Device Object Example for a SCSI HBA
The following figure shows the device objects that are created for system with a PCI IEEE 1394 controller and a PCI SCSI adapter with a CD-ROM and partitionable disk device attached.
Device Object Example for an IEEE 1394 Controller
Device Object Example for a PCI IDE Controller
Device Object Example for a USB Mass Storage Device
This brings me to the end of this post, in the next post we will be discussing more about the the IRPs
Note: The content of this blog has been primarily picked up from MSDN and WDK Documentation AS IS