Use reference counter and KEVENT instead of remove locks

Driver verifier doesn't like re-initializing remove locks.

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2019-07-31 21:53:20 +02:00 committed by Jason A. Donenfeld
parent 9e9f1ac9b3
commit 799413a776

View File

@ -150,7 +150,8 @@ typedef struct _TUN_CTX
struct struct
{ {
NET_BUFFER_LIST *Head, *Tail; NET_BUFFER_LIST *Head, *Tail;
IO_REMOVE_LOCK RemoveLock; volatile LONG64 Count;
KEVENT Empty;
} ActiveNbls; } ActiveNbls;
} Receive; } Receive;
} Device; } Device;
@ -399,8 +400,8 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net
NdisFreeNetBufferList(CompletedNbl); NdisFreeNetBufferList(CompletedNbl);
} }
if (WasNdisIndicated) if (WasNdisIndicated && InterlockedDecrement64(&Ctx->Device.Receive.ActiveNbls.Count) <= 0)
IoReleaseRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, Nbl); KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE);
} }
InterlockedAdd64((LONG64 *)&Ctx->Statistics.ifHCInOctets, ReceivedPacketsSize); InterlockedAdd64((LONG64 *)&Ctx->Statistics.ifHCInOctets, ReceivedPacketsSize);
@ -521,8 +522,8 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
if (!InterlockedGet(&Ctx->Running)) if (!InterlockedGet(&Ctx->Running))
goto skipNbl; goto skipNbl;
if (!NT_SUCCESS(IoAcquireRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, Nbl))) if (InterlockedIncrement64(&Ctx->Device.Receive.ActiveNbls.Count) == 1)
goto skipNbl; KeClearEvent(&Ctx->Device.Receive.ActiveNbls.Empty);
NdisMIndicateReceiveNetBufferLists( NdisMIndicateReceiveNetBufferLists(
Ctx->MiniportAdapterHandle, Ctx->MiniportAdapterHandle,
@ -542,8 +543,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
/* Wait for all NBLs to return: 1. To prevent race between proceeding and invalidating ring head. 2. To have /* Wait for all NBLs to return: 1. To prevent race between proceeding and invalidating ring head. 2. To have
* TunDispatchUnregisterBuffers() implicitly wait before releasing ring MDL used by NBL(s). */ * TunDispatchUnregisterBuffers() implicitly wait before releasing ring MDL used by NBL(s). */
if (NT_SUCCESS(IoAcquireRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, NULL))) KeWaitForSingleObject(&Ctx->Device.Receive.ActiveNbls.Empty, Executive, KernelMode, FALSE, NULL);
IoReleaseRemoveLockAndWait(&Ctx->Device.Receive.ActiveNbls.RemoveLock, NULL);
cleanup: cleanup:
InterlockedSetU(&Ring->Head, MAXULONG); InterlockedSetU(&Ring->Head, MAXULONG);
} }
@ -609,8 +609,6 @@ TunRegisterBuffers(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
!IS_POW2(Ctx->Device.Receive.Capacity) || !Rrb->Receive.TailMoved || !Rrb->Receive.Ring)) !IS_POW2(Ctx->Device.Receive.Capacity) || !Rrb->Receive.TailMoved || !Rrb->Receive.Ring))
goto cleanupSendUnlockPages; goto cleanupSendUnlockPages;
IoInitializeRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, TUN_MEMORY_TAG, 0, 0);
if (!NT_SUCCESS( if (!NT_SUCCESS(
Status = ObReferenceObjectByHandle( Status = ObReferenceObjectByHandle(
Rrb->Receive.TailMoved, Rrb->Receive.TailMoved,
@ -881,7 +879,6 @@ static NDIS_STATUS
TunRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters) TunRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters)
{ {
TUN_CTX *Ctx = (TUN_CTX *)MiniportAdapterContext; TUN_CTX *Ctx = (TUN_CTX *)MiniportAdapterContext;
IoInitializeRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, TUN_MEMORY_TAG, 0, 0);
InterlockedSet(&Ctx->Running, TRUE); InterlockedSet(&Ctx->Running, TRUE);
return NDIS_STATUS_SUCCESS; return NDIS_STATUS_SUCCESS;
} }
@ -898,8 +895,7 @@ TunPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_PAUSE_PARAMETERS Min
&Ctx->TransitionLock, &Ctx->TransitionLock,
ExAcquireSpinLockExclusive(&Ctx->TransitionLock)); /* Ensure above change is visible to all readers. */ ExAcquireSpinLockExclusive(&Ctx->TransitionLock)); /* Ensure above change is visible to all readers. */
if (NT_SUCCESS(IoAcquireRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, NULL))) KeWaitForSingleObject(&Ctx->Device.Receive.ActiveNbls.Empty, Executive, KernelMode, FALSE, NULL);
IoReleaseRemoveLockAndWait(&Ctx->Device.Receive.ActiveNbls.RemoveLock, NULL);
return NDIS_STATUS_SUCCESS; return NDIS_STATUS_SUCCESS;
} }
@ -963,6 +959,7 @@ TunInitializeEx(
KeInitializeEvent(&Ctx->Device.Disconnected, NotificationEvent, TRUE); KeInitializeEvent(&Ctx->Device.Disconnected, NotificationEvent, TRUE);
KeInitializeSpinLock(&Ctx->Device.Send.Lock); KeInitializeSpinLock(&Ctx->Device.Send.Lock);
KeInitializeSpinLock(&Ctx->Device.Receive.Lock); KeInitializeSpinLock(&Ctx->Device.Receive.Lock);
KeInitializeEvent(&Ctx->Device.Receive.ActiveNbls.Empty, NotificationEvent, TRUE);
NET_BUFFER_LIST_POOL_PARAMETERS NblPoolParameters = { NET_BUFFER_LIST_POOL_PARAMETERS NblPoolParameters = {
.Header = { .Type = NDIS_OBJECT_TYPE_DEFAULT, .Header = { .Type = NDIS_OBJECT_TYPE_DEFAULT,