https://git.reactos.org/?p=reactos.git;a=commitdiff;h=58ad5d9e02bbb08c3229e…
commit 58ad5d9e02bbb08c3229ee06ed25f64e13c2a2f0
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Wed Dec 9 12:24:23 2020 +0100
Commit: Jérôme Gardou <jerome.gardou(a)reactos.org>
CommitDate: Wed Dec 9 12:24:23 2020 +0100
[SCSIPORT] Fix locking the device extension.
From MSDN:
It is an error to call KeReleaseSpinLockFromDpcLevel if the specified spin lock was
acquired by calling KeAcquireSpinLock because the caller's original IRQL is not
restored, which can cause deadlocks or fatal page faults.
---
drivers/storage/port/scsiport/fdo.c | 8 ++------
drivers/storage/port/scsiport/scsi.c | 32 ++++++++++++++++++--------------
drivers/storage/port/scsiport/scsiport.h | 3 ++-
3 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/drivers/storage/port/scsiport/fdo.c b/drivers/storage/port/scsiport/fdo.c
index 2cc89ea7353..052d5f62fa5 100644
--- a/drivers/storage/port/scsiport/fdo.c
+++ b/drivers/storage/port/scsiport/fdo.c
@@ -150,12 +150,8 @@ FdoSendInquiry(
/* Acquire the spinlock */
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
- /* Process the request */
- SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
-
- /* SpiGetNextRequestFromLun() releases the spinlock,
- so we just lower irql back to what it was before */
- KeLowerIrql(Irql);
+ /* Process the request. SpiGetNextRequestFromLun will unlock for us */
+ SpiGetNextRequestFromLun(DeviceExtension, LunExtension, &Irql);
}
/* Check if data overrun happened */
diff --git a/drivers/storage/port/scsiport/scsi.c b/drivers/storage/port/scsiport/scsi.c
index 6cfd1ba29f3..0aa7d36a3d5 100644
--- a/drivers/storage/port/scsiport/scsi.c
+++ b/drivers/storage/port/scsiport/scsi.c
@@ -258,11 +258,8 @@ ScsiPortDispatchScsi(
if (lunExt->SrbInfo.Srb == NULL)
{
- /* Get next logical unit request */
- SpiGetNextRequestFromLun(portExt, lunExt);
-
- /* SpiGetNextRequestFromLun() releases the spinlock */
- KeLowerIrql(Irql);
+ /* Get next logical unit request. SpiGetNextRequestFromLun releases the
lock. */
+ SpiGetNextRequestFromLun(portExt, lunExt, &Irql);
}
else
{
@@ -344,7 +341,9 @@ ScsiPortDispatchScsi(
VOID
SpiGetNextRequestFromLun(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
- _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension)
+ _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension,
+ _Inout_opt_ PKIRQL OldIrql
+)
{
PIO_STACK_LOCATION IrpStack;
PIRP NextIrp;
@@ -357,7 +356,10 @@ SpiGetNextRequestFromLun(
!(LunExtension->Flags & SCSI_PORT_LU_ACTIVE))
{
/* Release the spinlock and exit */
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+ if (OldIrql != NULL)
+ KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
+ else
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
return;
}
@@ -385,7 +387,10 @@ SpiGetNextRequestFromLun(
LunExtension->AttemptCount = 0;
/* Release the spinlock */
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+ if (OldIrql != NULL)
+ KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
+ else
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
/* Start the next pending request */
IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL,
NULL);
@@ -495,8 +500,7 @@ SpiSenseCompletionRoutine(
lunExt->Flags &= ~LUNEX_NEED_REQUEST_SENSE;
// SpiGetNextRequestFromLun releases the lock
- SpiGetNextRequestFromLun(portExt, lunExt);
- KeLowerIrql(irql);
+ SpiGetNextRequestFromLun(portExt, lunExt, &irql);
InitialSrb->SrbStatus &= ~SRB_STATUS_QUEUE_FROZEN;
}
@@ -774,8 +778,8 @@ SpiProcessCompletedRequest(
if (!(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) &&
LunExtension->RequestTimeout == -1)
{
- /* Start the next packet */
- SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
+ /* Start the next packet. SpiGetNextRequestFromLun will release the lock for
us */
+ SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
}
else
{
@@ -891,7 +895,7 @@ Error:
&& (Srb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE))
{
if (LunExtension->RequestTimeout == -1)
- SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
+ SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
else
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
}
@@ -1342,7 +1346,7 @@ TryAgain:
LunExtension->ReadyLun = NULL;
/* Get next request for this LUN */
- SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
+ SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
/* Still ready requests exist?
If yes - get spinlock, if no - stop here */
diff --git a/drivers/storage/port/scsiport/scsiport.h
b/drivers/storage/port/scsiport/scsiport.h
index a81ef4cbb41..d3ee010cab1 100644
--- a/drivers/storage/port/scsiport/scsiport.h
+++ b/drivers/storage/port/scsiport/scsiport.h
@@ -437,7 +437,8 @@ RegistryInitLunKey(
VOID
SpiGetNextRequestFromLun(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
- _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension);
+ _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension,
+ _Inout_opt_ PKIRQL OldIrql);
IO_DPC_ROUTINE ScsiPortDpcForIsr;
DRIVER_DISPATCH ScsiPortDispatchScsi;