mirror of
https://github.com/bobranten/Ext4Fsd.git
synced 2026-03-16 05:10:37 -05:00
Merge pull request #93 from HorusGod007/fix/prevent-hang-on-device-removal
Fix system hang on USB/removable device removal
This commit is contained in:
@@ -400,8 +400,15 @@ Ext2ReadWriteBlocks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Ext2CanIWait()) {
|
if (Ext2CanIWait()) {
|
||||||
KeWaitForSingleObject( &(pContext->Event),
|
LARGE_INTEGER Timeout;
|
||||||
Executive, KernelMode, FALSE, NULL );
|
Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */
|
||||||
|
Status = KeWaitForSingleObject( &(pContext->Event),
|
||||||
|
Executive, KernelMode, FALSE, &Timeout );
|
||||||
|
if (Status == STATUS_TIMEOUT) {
|
||||||
|
/* Device likely removed — unblock and report error */
|
||||||
|
MasterIrp->IoStatus.Status = STATUS_IO_TIMEOUT;
|
||||||
|
MasterIrp->IoStatus.Information = 0;
|
||||||
|
}
|
||||||
KeClearEvent( &(pContext->Event) );
|
KeClearEvent( &(pContext->Event) );
|
||||||
} else {
|
} else {
|
||||||
bMasterCompleted = TRUE;
|
bMasterCompleted = TRUE;
|
||||||
@@ -496,16 +503,24 @@ Ext2ReadSync(
|
|||||||
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
KeWaitForSingleObject(
|
LARGE_INTEGER Timeout;
|
||||||
|
Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */
|
||||||
|
Status = KeWaitForSingleObject(
|
||||||
Event,
|
Event,
|
||||||
Suspended,
|
Suspended,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL
|
&Timeout
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (Status == STATUS_TIMEOUT) {
|
||||||
|
IoCancelIrp(Irp);
|
||||||
|
KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = STATUS_IO_TIMEOUT;
|
||||||
|
} else {
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
@@ -610,9 +625,17 @@ Ext2DiskIoControl (
|
|||||||
Status = IoCallDriver(DeviceObject, Irp);
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */
|
||||||
|
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &Timeout);
|
||||||
|
if (Status == STATUS_TIMEOUT) {
|
||||||
|
IoCancelIrp(Irp);
|
||||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = STATUS_IO_TIMEOUT;
|
||||||
|
} else {
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (OutputBufferSize) {
|
if (OutputBufferSize) {
|
||||||
*OutputBufferSize = (ULONG)(IoStatus.Information);
|
*OutputBufferSize = (ULONG)(IoStatus.Information);
|
||||||
@@ -644,14 +667,22 @@ Ext2DiskShutDown(PEXT2_VCB Vcb)
|
|||||||
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
KeWaitForSingleObject(&Event,
|
LARGE_INTEGER Timeout;
|
||||||
|
Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */
|
||||||
|
Status = KeWaitForSingleObject(&Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
&Timeout);
|
||||||
|
|
||||||
|
if (Status == STATUS_TIMEOUT) {
|
||||||
|
IoCancelIrp(Irp);
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = STATUS_IO_TIMEOUT;
|
||||||
|
} else {
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2019,15 +2019,23 @@ Ext2IsMediaWriteProtected (
|
|||||||
Status = IoCallDriver(TargetDevice, Irp);
|
Status = IoCallDriver(TargetDevice, Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */
|
||||||
|
|
||||||
(VOID) KeWaitForSingleObject( &Event,
|
Status = KeWaitForSingleObject( &Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
(PLARGE_INTEGER)NULL );
|
&Timeout );
|
||||||
|
|
||||||
|
if (Status == STATUS_TIMEOUT) {
|
||||||
|
IoCancelIrp(Irp);
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = STATUS_IO_TIMEOUT;
|
||||||
|
} else {
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (BOOLEAN)(Status == STATUS_MEDIA_WRITE_PROTECTED);
|
return (BOOLEAN)(Status == STATUS_MEDIA_WRITE_PROTECTED);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,11 +198,20 @@ Ext2PnpQueryRemove (
|
|||||||
IrpContext->Irp);
|
IrpContext->Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
KeWaitForSingleObject( &Event,
|
LARGE_INTEGER Timeout;
|
||||||
|
Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */
|
||||||
|
|
||||||
|
Status = KeWaitForSingleObject( &Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL );
|
&Timeout );
|
||||||
|
|
||||||
|
if (Status == STATUS_TIMEOUT) {
|
||||||
|
IoCancelIrp(IrpContext->Irp);
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
Status = IrpContext->Irp->IoStatus.Status;
|
Status = IrpContext->Irp->IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +258,9 @@ Ext2PnpRemove (
|
|||||||
Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
|
Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
|
|
||||||
|
/* Mark device removed early so concurrent I/O threads fail fast */
|
||||||
|
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup the Irp. We'll send it to the lower disk driver.
|
// Setup the Irp. We'll send it to the lower disk driver.
|
||||||
//
|
//
|
||||||
@@ -267,12 +279,19 @@ Ext2PnpRemove (
|
|||||||
IrpContext->Irp);
|
IrpContext->Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */
|
||||||
|
|
||||||
KeWaitForSingleObject( &Event,
|
Status = KeWaitForSingleObject( &Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL );
|
&Timeout );
|
||||||
|
|
||||||
|
if (Status == STATUS_TIMEOUT) {
|
||||||
|
IoCancelIrp(IrpContext->Irp);
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
Status = IrpContext->Irp->IoStatus.Status;
|
Status = IrpContext->Irp->IoStatus.Status;
|
||||||
}
|
}
|
||||||
@@ -282,7 +301,6 @@ Ext2PnpRemove (
|
|||||||
|
|
||||||
/* dismount volume */
|
/* dismount volume */
|
||||||
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
||||||
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
|
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
@@ -319,6 +337,9 @@ Ext2PnpSurpriseRemove (
|
|||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
|
|
||||||
|
/* Mark device removed early so concurrent I/O threads fail fast */
|
||||||
|
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup the Irp. We'll send it to the lower disk driver.
|
// Setup the Irp. We'll send it to the lower disk driver.
|
||||||
//
|
//
|
||||||
@@ -337,12 +358,19 @@ Ext2PnpSurpriseRemove (
|
|||||||
IrpContext->Irp);
|
IrpContext->Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */
|
||||||
|
|
||||||
KeWaitForSingleObject( &Event,
|
Status = KeWaitForSingleObject( &Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL );
|
&Timeout );
|
||||||
|
|
||||||
|
if (Status == STATUS_TIMEOUT) {
|
||||||
|
IoCancelIrp(IrpContext->Irp);
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
Status = IrpContext->Irp->IoStatus.Status;
|
Status = IrpContext->Irp->IoStatus.Status;
|
||||||
}
|
}
|
||||||
@@ -352,7 +380,6 @@ Ext2PnpSurpriseRemove (
|
|||||||
|
|
||||||
/* dismount volume */
|
/* dismount volume */
|
||||||
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
||||||
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
|
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
|
|||||||
@@ -879,6 +879,12 @@ Ext2Read (IN PEXT2_IRP_CONTEXT IrpContext)
|
|||||||
|
|
||||||
FileObject = IrpContext->FileObject;
|
FileObject = IrpContext->FileObject;
|
||||||
|
|
||||||
|
if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
|
||||||
|
Status = STATUS_NO_SUCH_DEVICE;
|
||||||
|
bCompleteRequest = TRUE;
|
||||||
|
__leave;
|
||||||
|
}
|
||||||
|
|
||||||
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
||||||
Vcb->LockFile != FileObject ) {
|
Vcb->LockFile != FileObject ) {
|
||||||
Status = STATUS_ACCESS_DENIED;
|
Status = STATUS_ACCESS_DENIED;
|
||||||
|
|||||||
@@ -1359,6 +1359,11 @@ Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext)
|
|||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
|
||||||
|
Status = STATUS_NO_SUCH_DEVICE;
|
||||||
|
__leave;
|
||||||
|
}
|
||||||
|
|
||||||
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
||||||
Vcb->LockFile != FileObject ) {
|
Vcb->LockFile != FileObject ) {
|
||||||
Status = STATUS_ACCESS_DENIED;
|
Status = STATUS_ACCESS_DENIED;
|
||||||
|
|||||||
Reference in New Issue
Block a user