1
0
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:
Bo Brantén
2026-03-05 02:06:45 +01:00
committed by GitHub
5 changed files with 98 additions and 21 deletions

View File

@@ -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;
} }

View File

@@ -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);
} }

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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;