mirror of
https://github.com/reactos/reactos.git
synced 2025-07-30 21:51:47 +00:00
[FSRTL]
Fix my lock implementation to a degree. - Have a single list associated with the CSQ. - Remove some confusion from when the lock information was a generic table. - Make the compare function not be confused by attempts to give strange offsets and lengths. - Make the uninitialize function complete all lock requests as specified. - Remove my unneeded attempt to shoehorn in an eresource. svn path=/trunk/; revision=56026
This commit is contained in:
parent
bd9aa57445
commit
d9d0e1ad2a
1 changed files with 73 additions and 59 deletions
|
@ -9,11 +9,9 @@
|
|||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define RESOURCE_OF_LOCK(L) ((PERESOURCE)&((L)->Unknown1))
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList;
|
||||
|
@ -37,6 +35,7 @@ typedef struct _LOCK_INFORMATION
|
|||
RTL_GENERIC_TABLE RangeTable;
|
||||
IO_CSQ Csq;
|
||||
KSPIN_LOCK CsqLock;
|
||||
LIST_ENTRY CsqList;
|
||||
PFILE_LOCK BelongsTo;
|
||||
}
|
||||
LOCK_INFORMATION, *PLOCK_INFORMATION;
|
||||
|
@ -57,7 +56,7 @@ FsRtlCompleteLockIrpReal(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteRoutine,
|
|||
static PVOID NTAPI LockAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
|
||||
{
|
||||
PVOID Result;
|
||||
Result = ExAllocatePoolWithTag(NonPagedPool, Bytes, 'FLCK');
|
||||
Result = ExAllocatePoolWithTag(NonPagedPool, Bytes, 'LTAB');
|
||||
DPRINT("LockAllocate(%d) => %p\n", Bytes, Result);
|
||||
return Result;
|
||||
}
|
||||
|
@ -65,7 +64,7 @@ static PVOID NTAPI LockAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
|
|||
static VOID NTAPI LockFree(PRTL_GENERIC_TABLE Table, PVOID Buffer)
|
||||
{
|
||||
DPRINT("LockFree(%p)\n", Buffer);
|
||||
ExFreePoolWithTag(Buffer, 'FLCK');
|
||||
ExFreePoolWithTag(Buffer, 'LTAB');
|
||||
}
|
||||
|
||||
static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare
|
||||
|
@ -75,10 +74,10 @@ static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare
|
|||
RTL_GENERIC_COMPARE_RESULTS Result;
|
||||
DPRINT("Starting to compare element %x to element %x\n", PtrA, PtrB);
|
||||
Result =
|
||||
(A->Exclusive.FileLock.EndingByte.QuadPart <
|
||||
(A->Exclusive.FileLock.StartingByte.QuadPart <
|
||||
B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericLessThan :
|
||||
(A->Exclusive.FileLock.StartingByte.QuadPart >
|
||||
B->Exclusive.FileLock.EndingByte.QuadPart) ? GenericGreaterThan :
|
||||
B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericGreaterThan :
|
||||
GenericEqual;
|
||||
DPRINT("Compare(%x:%x) %x-%x to %x-%x => %d\n",
|
||||
A,B,
|
||||
|
@ -97,8 +96,8 @@ static NTSTATUS NTAPI LockInsertIrpEx
|
|||
PIRP Irp,
|
||||
PVOID InsertContext)
|
||||
{
|
||||
PCOMBINED_LOCK_ELEMENT LockElement = InsertContext;
|
||||
InsertTailList(&LockElement->Exclusive.ListEntry, &Irp->Tail.Overlay.ListEntry);
|
||||
PLOCK_INFORMATION LockInfo = CONTAINING_RECORD(Csq, LOCK_INFORMATION, Csq);
|
||||
InsertTailList(&LockInfo->CsqList, &Irp->Tail.Overlay.ListEntry);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -113,45 +112,51 @@ static PIRP NTAPI LockPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext)
|
|||
// lock that can be acquired, now that the lock matching PeekContext
|
||||
// has been removed.
|
||||
COMBINED_LOCK_ELEMENT LockElement;
|
||||
PCOMBINED_LOCK_ELEMENT WhereUnlocked = PeekContext, Matching;
|
||||
PCOMBINED_LOCK_ELEMENT WhereUnlock = PeekContext;
|
||||
PLOCK_INFORMATION LockInfo = CONTAINING_RECORD(Csq, LOCK_INFORMATION, Csq);
|
||||
PFILE_LOCK FileLock = LockInfo->BelongsTo;
|
||||
if (!PeekContext)
|
||||
return CONTAINING_RECORD
|
||||
(Irp->Tail.Overlay.ListEntry.Flink,
|
||||
IRP,
|
||||
Tail.Overlay.ListEntry);
|
||||
else
|
||||
{
|
||||
PLIST_ENTRY Following;
|
||||
if (!FileLock->LockInformation)
|
||||
{
|
||||
return CONTAINING_RECORD
|
||||
(Irp->Tail.Overlay.ListEntry.Flink,
|
||||
IRP,
|
||||
Tail.Overlay.ListEntry);
|
||||
}
|
||||
for (Following = Irp->Tail.Overlay.ListEntry.Flink;
|
||||
Following != &WhereUnlocked->Exclusive.ListEntry;
|
||||
Following = Following->Flink)
|
||||
{
|
||||
PIRP Irp = CONTAINING_RECORD(Following, IRP, Tail.Overlay.ListEntry);
|
||||
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
LockElement.Exclusive.FileLock.StartingByte =
|
||||
IoStack->Parameters.LockControl.ByteOffset;
|
||||
LockElement.Exclusive.FileLock.EndingByte.QuadPart =
|
||||
LockElement.Exclusive.FileLock.StartingByte.QuadPart +
|
||||
IoStack->Parameters.LockControl.Length->QuadPart;
|
||||
Matching = RtlLookupElementGenericTable
|
||||
(FileLock->LockInformation, &LockElement);
|
||||
if (!Matching)
|
||||
{
|
||||
// This IRP is fine...
|
||||
return Irp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
PLIST_ENTRY Following;
|
||||
if (!Irp)
|
||||
{
|
||||
Irp = CONTAINING_RECORD
|
||||
(LockInfo->CsqList.Flink,
|
||||
IRP,
|
||||
Tail.Overlay.ListEntry);
|
||||
Following = &Irp->Tail.Overlay.ListEntry;
|
||||
}
|
||||
else
|
||||
Following = Irp->Tail.Overlay.ListEntry.Flink;
|
||||
|
||||
for (;
|
||||
Following != &LockInfo->CsqList;
|
||||
Following = Following->Flink)
|
||||
{
|
||||
PIRP Irp = CONTAINING_RECORD(Following, IRP, Tail.Overlay.ListEntry);
|
||||
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
BOOLEAN Matching;
|
||||
LockElement.Exclusive.FileLock.StartingByte =
|
||||
IoStack->Parameters.LockControl.ByteOffset;
|
||||
LockElement.Exclusive.FileLock.EndingByte.QuadPart =
|
||||
LockElement.Exclusive.FileLock.StartingByte.QuadPart +
|
||||
IoStack->Parameters.LockControl.Length->QuadPart;
|
||||
/* If a context was specified, it's a range to check to unlock */
|
||||
if (WhereUnlock)
|
||||
{
|
||||
Matching = LockCompare
|
||||
(&LockInfo->RangeTable, &LockElement, WhereUnlock) != GenericEqual;
|
||||
}
|
||||
/* Else get any completable IRP */
|
||||
else
|
||||
{
|
||||
Matching = !!RtlLookupElementGenericTable
|
||||
(&LockInfo->RangeTable, &LockElement);
|
||||
}
|
||||
if (!Matching)
|
||||
{
|
||||
// This IRP is fine...
|
||||
return Irp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
|
@ -258,7 +263,7 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
|||
/* Initialize the lock, if necessary */
|
||||
if (!FileLock->LockInformation)
|
||||
{
|
||||
LockInfo = ExAllocatePool(PagedPool, sizeof(LOCK_INFORMATION));
|
||||
LockInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(LOCK_INFORMATION), 'FLCK');
|
||||
FileLock->LockInformation = LockInfo;
|
||||
if (!FileLock)
|
||||
return FALSE;
|
||||
|
@ -273,6 +278,7 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
|||
NULL);
|
||||
|
||||
KeInitializeSpinLock(&LockInfo->CsqLock);
|
||||
InitializeListHead(&LockInfo->CsqList);
|
||||
|
||||
IoCsqInitializeEx
|
||||
(&LockInfo->Csq,
|
||||
|
@ -360,10 +366,6 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
|||
/* Assume all is cool, and lock is set */
|
||||
IoStatus->Status = STATUS_SUCCESS;
|
||||
|
||||
// Initialize our resource ... We'll use this to mediate access to the
|
||||
// irp queue.
|
||||
ExInitializeResourceLite(RESOURCE_OF_LOCK(&Conflict->Exclusive));
|
||||
|
||||
if (Irp)
|
||||
{
|
||||
/* Complete the request */
|
||||
|
@ -520,9 +522,9 @@ FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock,
|
|||
return STATUS_RANGE_NOT_LOCKED;
|
||||
// this is definitely the thing we want
|
||||
RtlCopyMemory(&Find, Entry, sizeof(Find));
|
||||
RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
|
||||
NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find);
|
||||
if (NextMatchingLockIrp)
|
||||
RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
|
||||
while (NextMatchingLockIrp)
|
||||
{
|
||||
// Got a new lock irp... try to do the new lock operation
|
||||
// Note that we pick an operation that would succeed at the time
|
||||
|
@ -583,13 +585,13 @@ FsRtlFastUnlockAllByKey(IN PFILE_LOCK FileLock,
|
|||
IN PVOID Context OPTIONAL)
|
||||
{
|
||||
PCOMBINED_LOCK_ELEMENT Entry;
|
||||
PRTL_GENERIC_TABLE InternalInfo = FileLock->LockInformation;
|
||||
PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
|
||||
|
||||
// XXX Synchronize somehow
|
||||
if (!FileLock->LockInformation) return STATUS_RANGE_NOT_LOCKED; // no locks
|
||||
for (Entry = RtlEnumerateGenericTable(InternalInfo, TRUE);
|
||||
for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
|
||||
Entry;
|
||||
Entry = RtlEnumerateGenericTable(InternalInfo, FALSE))
|
||||
Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
|
||||
{
|
||||
LARGE_INTEGER Length;
|
||||
// We'll take the first one to be the list head, and free the others first...
|
||||
|
@ -743,6 +745,7 @@ FsRtlInitializeFileLock (IN PFILE_LOCK FileLock,
|
|||
IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
|
||||
{
|
||||
/* Setup the lock */
|
||||
RtlZeroMemory(FileLock, sizeof(*FileLock));
|
||||
FileLock->FastIoIsQuestionable = FALSE;
|
||||
FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
|
||||
FileLock->UnlockRoutine = UnlockRoutine;
|
||||
|
@ -758,8 +761,19 @@ FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
|
|||
{
|
||||
if (FileLock->LockInformation)
|
||||
{
|
||||
ASSERT(!RtlNumberGenericTableElements(FileLock->LockInformation));
|
||||
ExFreePool(FileLock->LockInformation);
|
||||
PIRP Irp;
|
||||
PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
|
||||
PCOMBINED_LOCK_ELEMENT Entry;
|
||||
// MSDN: this completes any remaining lock IRPs
|
||||
while ((Entry = RtlGetElementGenericTable(&InternalInfo->RangeTable, 0)) != NULL)
|
||||
{
|
||||
RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
|
||||
}
|
||||
while ((Irp = IoCsqRemoveNextIrp(&InternalInfo->Csq, NULL)) != NULL)
|
||||
{
|
||||
FsRtlProcessFileLock(FileLock, Irp, NULL);
|
||||
}
|
||||
ExFreePoolWithTag(InternalInfo, 'FLCK');
|
||||
FileLock->LockInformation = NULL;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue