存储类驱动程序的 ReleaseQueue 例程

Unless a storage class driver ORs the SrbFlags for a given request with SRB_FLAGS_NO_QUEUE_FREEZE, the system port driver freezes a queue for a given logical unit after any of the following:

  • 执行请求时发生总线重置。

  • The logical unit returned SCSISTAT_CHECK_CONDITION or SCSISTAT_COMMAND_TERMINATED, which the class driver can find in the SRB's ScsiStatus member.

  • 请求超时。

  • 请求已由总线消息命令(如 SCSIMESS_ABORT)终止。

The port driver indicates that an LU-specific queue has been frozen by returning a request with SRB_STATUS_QUEUE_FROZEN in the SrbStatus member. 类驱动程序的新请求可以插入到队列中,但只要队列已冻结,则仅自动感知请求发送到逻辑单元。

在这些条件下冻结队列可让每个存储类驱动程序在执行其他排队作业之前分析错误。 例如,如果媒体已更改,可能需要取消排队作业。 To flush the queue, the driver can send a request with the SrbFlags ORed with SRB_FLAGS_BYPASS_FROZEN_QUEUE.

A ReleaseQueue routine allocates and sets up an IRP and an SRB to either release or flush a frozen queue. The Function member of the SRB must be set to SRB_FUNCTION_RELEASE_QUEUE or SRB_FUNCTION_FLUSH_QUEUE, which both releases a frozen queue and cancels all currently queued requests for the target logical unit. The port driver completes all requests in a flushed queue with their SrbStatus members set to SRB_STATUS_REQUEST_FLUSHED.

Failing to release a frozen queue makes the device inaccessible, so a driver's ReleaseQueue routine should be designed to succeed even in low memory conditions. A ReleaseQueue routine should first attempt to allocate memory for an SRB by calling ExAllocatePool with the NonPagedPool memory type and, if that allocation fails, use an SRB that was preallocated during driver initialization. 如果驱动程序在初始化设备扩展时分配要保留的 SRB,如 设置存储类驱动程序的设备扩展中所述,则其 ReleaseQueue 可以在内存池较低时使用该 SRB,如果可能需要多个并发发布作,则其 ReleaseQueue 可以使用该 SRB。

Note that a class driver's ReleaseQueue routine is called asynchronously, generally from its IoCompletion routine. A class driver's IoCompletion routine cannot call ReleaseQueue to flush a queue that is not frozen. However, it can call ReleaseQueue to release an unfrozen queue, and the port driver simply ignores such a request.