存储类驱动程序的 ReleaseQueue 例程

除非存储类驱动程序使用 SRB_FLAGS_NO_QUEUE_FREEZE 对给定请求进行 SrbFlag ,否则系统端口驱动程序在发生以下任一情况后会冻结给定逻辑单元的队列:

  • 逻辑单元执行请求时发生总线重置。

  • 逻辑单元返回SCSISTAT_CHECK_CONDITION或SCSISTAT_COMMAND_TERMINATED,类驱动程序可以在 SRB 的 ScsiStatus 成员中找到。

  • 请求已超时。

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

端口驱动程序通过返回 SrbStatus 成员中具有SRB_STATUS_QUEUE_FROZEN的请求来指示特定于 LU 的队列已被冻结。 类驱动程序中的新请求可以插入到队列中,但只要逻辑单元的队列被冻结,只会将自动感知请求发送到逻辑单元。

在这些条件下冻结队列可让每个存储类驱动程序在执行其他排队作业之前分析错误。 例如,如果媒体已更改,可能需要取消排队的作业。 若要刷新队列,驱动程序可以发送带有 SrbFlags ORed SRB_FLAGS_BYPASS_FROZEN_QUEUE的请求。

ReleaseQueue 例程分配并设置 IRP 和 SRB,以释放或刷新冻结的队列。 SRB 的 Function 成员必须设置为 SRB_FUNCTION_RELEASE_QUEUE 或 SRB_FUNCTION_FLUSH_QUEUE,这既会释放已冻结的队列,又会取消目标逻辑单元的所有当前排队请求。 端口驱动程序完成刷新队列中的所有请求,其 SrbStatus 成员设置为 SRB_STATUS_REQUEST_FLUSHED。

未能释放冻结的队列会使设备无法访问,因此驱动程序的 ReleaseQueue 例程应该设计为即使在内存不足的情况下也能成功。 ReleaseQueue 例程应首先尝试通过调用具有 NonPagedPool 内存类型的 ExAllocatePool 为 SRB 分配内存,如果分配失败,请使用在驱动程序初始化期间预先分配的 SRB。 如果驱动程序在初始化其设备扩展时分配 SRB 保留,如 设置存储类驱动程序的设备扩展中所述,则其 ReleaseQueue 可以在内存池不足时使用该 SRB,并在可能需要多个并发发布操作时使用适当的同步机制。

请注意,类驱动程序的 ReleaseQueue 例程以异步方式调用,通常从其 IoCompletion 例程调用。 类驱动程序的 IoCompletion 例程无法调用 ReleaseQueue 来刷新未冻结的队列。 但是,它可以调用 ReleaseQueue 来释放未冻结的队列,而端口驱动程序只是忽略此类请求。