diff options
author | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2024-11-23 17:44:48 +0100 |
---|---|---|
committer | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2024-11-23 17:44:48 +0100 |
commit | 453ff2880e1e59e1471d3f16804315879128ce46 (patch) | |
tree | 9c7a143d1f5ff91d12e41718d562a430ef6f0e73 /src/Driver/EncryptedIoQueue.c | |
parent | 5a85c54c6ef556b96cc1ed844620a4ccee1b7837 (diff) | |
download | VeraCrypt-453ff2880e1e59e1471d3f16804315879128ce46.tar.gz VeraCrypt-453ff2880e1e59e1471d3f16804315879128ce46.zip |
Windows Driver: Make max work items count configurable. Increase default to 1024. Queue write IRPs.
- Made the maximum work items count configurable to allow flexibility based on system needs.
- Increased the default value of max work items count to 1024 to better handle high-throughput scenarios.
- Queue write IRPs in system worker thread to avoid potential deadlocks in write scenarios.
Diffstat (limited to 'src/Driver/EncryptedIoQueue.c')
-rw-r--r-- | src/Driver/EncryptedIoQueue.c | 76 |
1 files changed, 39 insertions, 37 deletions
diff --git a/src/Driver/EncryptedIoQueue.c b/src/Driver/EncryptedIoQueue.c index d68c3f09..91399c47 100644 --- a/src/Driver/EncryptedIoQueue.c +++ b/src/Driver/EncryptedIoQueue.c @@ -303,8 +303,43 @@ static VOID CompleteIrpWorkItemRoutine(PDEVICE_OBJECT DeviceObject, PVOID Contex } } +// Handles the completion of the original IRP. +static VOID HandleCompleteOriginalIrp(EncryptedIoQueue* queue, EncryptedIoRequest* request) +{ + NTSTATUS status = KeWaitForSingleObject(&queue->WorkItemSemaphore, Executive, KernelMode, FALSE, NULL); + if (queue->ThreadExitRequested) + return; + + if (!NT_SUCCESS(status)) + { + // Handle wait failure: we call the completion routine directly. + // This is not ideal since it can cause deadlock that we are trying to fix but it is better than losing the IRP. + CompleteOriginalIrp(request->Item, STATUS_INSUFFICIENT_RESOURCES, 0); + } + else + { + // Obtain a work item from the free list. + KIRQL oldIrql; + KeAcquireSpinLock(&queue->WorkItemLock, &oldIrql); + PLIST_ENTRY freeEntry = RemoveHeadList(&queue->FreeWorkItemsList); + KeReleaseSpinLock(&queue->WorkItemLock, oldIrql); + PCOMPLETE_IRP_WORK_ITEM workItem = CONTAINING_RECORD(freeEntry, COMPLETE_IRP_WORK_ITEM, ListEntry); + + // Increment ActiveWorkItems. + InterlockedIncrement(&queue->ActiveWorkItems); + KeResetEvent(&queue->NoActiveWorkItemsEvent); + // Prepare the work item. + workItem->Irp = request->Item->OriginalIrp; + workItem->Status = request->Item->Status; + workItem->Information = NT_SUCCESS(request->Item->Status) ? request->Item->OriginalLength : 0; + workItem->Item = request->Item; + + // Queue the work item. + IoQueueWorkItem(workItem->WorkItem, CompleteIrpWorkItemRoutine, DelayedWorkQueue, workItem); + } +} static VOID CompletionThreadProc(PVOID threadArg) { @@ -348,39 +383,7 @@ static VOID CompletionThreadProc(PVOID threadArg) if (request->CompleteOriginalIrp) { - // Wait for a work item to become available - NTSTATUS status = KeWaitForSingleObject(&queue->WorkItemSemaphore, Executive, KernelMode, FALSE, NULL); - if (queue->ThreadExitRequested) - break; - if (!NT_SUCCESS(status)) - { - // Handle wait failure: we call the completion routine directly. - // This is not ideal since it can cause deadlock that we are trying to fix but it is better than losing the IRP. - CompleteOriginalIrp(request->Item, STATUS_INSUFFICIENT_RESOURCES, 0); - } - else - { - // Obtain a work item from the free list - KIRQL oldIrql; - KeAcquireSpinLock(&queue->WorkItemLock, &oldIrql); - PLIST_ENTRY freeEntry = RemoveHeadList(&queue->FreeWorkItemsList); - KeReleaseSpinLock(&queue->WorkItemLock, oldIrql); - - PCOMPLETE_IRP_WORK_ITEM workItem = CONTAINING_RECORD(freeEntry, COMPLETE_IRP_WORK_ITEM, ListEntry); - - // Increment ActiveWorkItems - InterlockedIncrement(&queue->ActiveWorkItems); - KeResetEvent(&queue->NoActiveWorkItemsEvent); - - // Prepare the work item - workItem->Irp = request->Item->OriginalIrp; - workItem->Status = request->Item->Status; - workItem->Information = NT_SUCCESS(request->Item->Status) ? request->Item->OriginalLength : 0; - workItem->Item = request->Item; - - // Queue the work item - IoQueueWorkItem(workItem->WorkItem, CompleteIrpWorkItemRoutine, DelayedWorkQueue, workItem); - } + HandleCompleteOriginalIrp(queue, request); } ReleasePoolBuffer(queue, request); @@ -541,8 +544,7 @@ static VOID IoThreadProc (PVOID threadArg) if (request->CompleteOriginalIrp) { - CompleteOriginalIrp (request->Item, request->Item->Status, - NT_SUCCESS (request->Item->Status) ? request->Item->OriginalLength : 0); + HandleCompleteOriginalIrp(queue, request); } ReleasePoolBuffer (queue, request); @@ -1148,10 +1150,10 @@ retry_preallocated: // Initialize the free work item list InitializeListHead(&queue->FreeWorkItemsList); - KeInitializeSemaphore(&queue->WorkItemSemaphore, VC_MAX_WORK_ITEMS, VC_MAX_WORK_ITEMS); + KeInitializeSemaphore(&queue->WorkItemSemaphore, EncryptionMaxWorkItems, EncryptionMaxWorkItems); KeInitializeSpinLock(&queue->WorkItemLock); - queue->MaxWorkItems = VC_MAX_WORK_ITEMS; + queue->MaxWorkItems = EncryptionMaxWorkItems; queue->WorkItemPool = (PCOMPLETE_IRP_WORK_ITEM)TCalloc(sizeof(COMPLETE_IRP_WORK_ITEM) * queue->MaxWorkItems); if (!queue->WorkItemPool) { |