Author: arty Date: Mon Mar 5 09:49:06 2012 New Revision: 56026
URL: http://svn.reactos.org/svn/reactos?rev=56026&view=rev Log: [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.
Modified: trunk/reactos/ntoskrnl/fsrtl/filelock.c
Modified: trunk/reactos/ntoskrnl/fsrtl/filelock.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/filelock.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/fsrtl/filelock.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/fsrtl/filelock.c [iso-8859-1] Mon Mar 5 09:49:06 2012 @@ -9,10 +9,8 @@ /* INCLUDES ******************************************************************/
#include <ntoskrnl.h> -#define NDEBUG +//#define NDEBUG #include <debug.h> - -#define RESOURCE_OF_LOCK(L) ((PERESOURCE)&((L)->Unknown1))
/* GLOBALS *******************************************************************/
@@ -37,6 +35,7 @@ RTL_GENERIC_TABLE RangeTable; IO_CSQ Csq; KSPIN_LOCK CsqLock; + LIST_ENTRY CsqList; PFILE_LOCK BelongsTo; } LOCK_INFORMATION, *PLOCK_INFORMATION; @@ -57,7 +56,7 @@ 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 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 @@ 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 @@ 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 @@ // 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 @@ /* 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 @@ NULL);
KeInitializeSpinLock(&LockInfo->CsqLock); + InitializeListHead(&LockInfo->CsqList);
IoCsqInitializeEx (&LockInfo->Csq, @@ -360,10 +366,6 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ { 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; } }