Author: arty
Date: Mon Jul 23 18:53:50 2012
New Revision: 56953
URL:
http://svn.reactos.org/svn/reactos?rev=56953&view=rev
Log:
[NTOSKRNL]
Fix some problems with the lock implementation
- Add a 'generation' to the lock IRPs so we know if we've reprocessed them on
any
specific turn when we unlock something else.
- Simplify coalescing of lock regions to just rebuilding the region by going through
the shared lock list and expanding a new region with any overlaps.
- Simplify coalescing new shared locks into larger regions in the same manner.
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?…
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/filelock.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/filelock.c [iso-8859-1] Mon Jul 23 18:53:50 2012
@@ -21,12 +21,12 @@
*/
typedef union _COMBINED_LOCK_ELEMENT
{
- struct
- {
- LIST_ENTRY dummy;
- FILE_SHARED_LOCK_ENTRY Shared;
- };
- FILE_EXCLUSIVE_LOCK_ENTRY Exclusive;
+ struct
+ {
+ LIST_ENTRY dummy;
+ FILE_SHARED_LOCK_ENTRY Shared;
+ };
+ FILE_EXCLUSIVE_LOCK_ENTRY Exclusive;
}
COMBINED_LOCK_ELEMENT, *PCOMBINED_LOCK_ELEMENT;
@@ -38,6 +38,7 @@
LIST_ENTRY CsqList;
PFILE_LOCK BelongsTo;
LIST_ENTRY SharedLocks;
+ ULONG Generation;
}
LOCK_INFORMATION, *PLOCK_INFORMATION;
@@ -224,6 +225,7 @@
IN PFILE_OBJECT FileObject OPTIONAL)
{
/* Check if we have a complete routine */
+ Irp->IoStatus.Information = 0;
if (CompleteRoutine)
{
/* Check if we have a file object */
@@ -260,55 +262,57 @@
else return &Entry->Exclusive.FileLock;
}
+VOID
+NTAPI
+FsRtlpExpandLockElement
+(PCOMBINED_LOCK_ELEMENT ToExpand,
+ PCOMBINED_LOCK_ELEMENT Conflict)
+{
+ if (ToExpand->Exclusive.FileLock.StartingByte.QuadPart >
+ Conflict->Exclusive.FileLock.StartingByte.QuadPart)
+ {
+ ToExpand->Exclusive.FileLock.StartingByte =
+ Conflict->Exclusive.FileLock.StartingByte;
+ }
+ if (ToExpand->Exclusive.FileLock.EndingByte.QuadPart <
+ Conflict->Exclusive.FileLock.EndingByte.QuadPart)
+ {
+ ToExpand->Exclusive.FileLock.EndingByte =
+ Conflict->Exclusive.FileLock.EndingByte;
+ }
+}
+
/* This function expands the conflicting range Conflict by removing and reinserting it,
then adds a shared range of the same size */
PCOMBINED_LOCK_ELEMENT
NTAPI
-FsRtlpSubsumeSharedLock
+FsRtlpRebuildSharedLockRange
(PFILE_LOCK FileLock,
PLOCK_INFORMATION LockInfo,
- PCOMBINED_LOCK_ELEMENT ToInsert,
PCOMBINED_LOCK_ELEMENT Conflict)
{
+ /* Starting at Conflict->StartingByte and going to Conflict->EndingByte
+ * capture and expand a shared range from the shared range list.
+ * Finish when we've incorporated all overlapping shared regions.
+ */
BOOLEAN InsertedNew = FALSE, RemovedOld;
- COMBINED_LOCK_ELEMENT NewElement;
- PLOCK_SHARED_RANGE SharedRange =
- ExAllocatePoolWithTag(NonPagedPool, sizeof(*SharedRange), 'FSRA');
-
- if (!SharedRange)
- return NULL;
-
- ASSERT(!Conflict->Exclusive.FileLock.ExclusiveLock);
- ASSERT(!ToInsert->Exclusive.FileLock.ExclusiveLock);
- SharedRange->Start = ToInsert->Exclusive.FileLock.StartingByte;
- SharedRange->End = ToInsert->Exclusive.FileLock.EndingByte;
- SharedRange->Key = ToInsert->Exclusive.FileLock.Key;
- SharedRange->ProcessId = ToInsert->Exclusive.FileLock.ProcessId;
- InsertTailList(&LockInfo->SharedLocks, &SharedRange->Entry);
-
- NewElement = *Conflict;
- if (ToInsert->Exclusive.FileLock.StartingByte.QuadPart >
- Conflict->Exclusive.FileLock.StartingByte.QuadPart)
- {
- NewElement.Exclusive.FileLock.StartingByte =
- Conflict->Exclusive.FileLock.StartingByte;
- }
- if (ToInsert->Exclusive.FileLock.EndingByte.QuadPart <
- Conflict->Exclusive.FileLock.EndingByte.QuadPart)
- {
- NewElement.Exclusive.FileLock.EndingByte =
- Conflict->Exclusive.FileLock.EndingByte;
- }
- RemovedOld = RtlDeleteElementGenericTable
- (&LockInfo->RangeTable,
- Conflict);
- ASSERT(RemovedOld);
+ COMBINED_LOCK_ELEMENT NewElement = *Conflict;
+ PCOMBINED_LOCK_ELEMENT Entry;
+ while ((Entry = RtlLookupElementGenericTable
+ (FileLock->LockInformation, &NewElement)))
+ {
+ FsRtlpExpandLockElement(&NewElement, Entry);
+ RemovedOld = RtlDeleteElementGenericTable
+ (&LockInfo->RangeTable,
+ Entry);
+ ASSERT(RemovedOld);
+ }
Conflict = RtlInsertElementGenericTable
(&LockInfo->RangeTable,
- ToInsert,
- sizeof(*ToInsert),
+ &NewElement,
+ sizeof(NewElement),
&InsertedNew);
- ASSERT(InsertedNew && Conflict);
+ ASSERT(InsertedNew);
return Conflict;
}
@@ -334,20 +338,27 @@
COMBINED_LOCK_ELEMENT ToInsert;
PCOMBINED_LOCK_ELEMENT Conflict;
PLOCK_INFORMATION LockInfo;
+ PLOCK_SHARED_RANGE NewSharedRange;
BOOLEAN InsertedNew;
-
- DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x, Length %08x%08x, Key %x,
FailImmediately %d, Exclusive %d)\n",
+ ULARGE_INTEGER UnsignedStart;
+ ULARGE_INTEGER UnsignedEnd;
+
+ DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key
%x, FailImmediately %d, Exclusive %d)\n",
&FileObject->FileName,
FileOffset->HighPart,
FileOffset->LowPart,
+ (int)FileOffset->QuadPart,
Length->HighPart,
Length->LowPart,
+ (int)Length->QuadPart,
Key,
FailImmediately,
ExclusiveLock);
- if (FileOffset->QuadPart < 0ll ||
- FileOffset->QuadPart + Length->QuadPart < FileOffset->QuadPart)
+ UnsignedStart.QuadPart = FileOffset->QuadPart;
+ UnsignedEnd.QuadPart = FileOffset->QuadPart + Length->QuadPart;
+
+ if (UnsignedEnd.QuadPart < UnsignedStart.QuadPart)
{
DPRINT("File offset out of range\n");
IoStatus->Status = STATUS_INVALID_PARAMETER;
@@ -416,11 +427,20 @@
{
if (Conflict->Exclusive.FileLock.ExclusiveLock || ExclusiveLock)
{
+ DPRINT("Conflict %08x%08x:%08x%08x Exc %d (Want Exc %d)\n",
+ Conflict->Exclusive.FileLock.StartingByte.HighPart,
+ Conflict->Exclusive.FileLock.StartingByte.LowPart,
+ Conflict->Exclusive.FileLock.EndingByte.HighPart,
+ Conflict->Exclusive.FileLock.EndingByte.LowPart,
+ Conflict->Exclusive.FileLock.ExclusiveLock,
+ ExclusiveLock);
if (FailImmediately)
{
+ DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
if (Irp)
{
+ DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
FsRtlCompleteLockIrpReal
(FileLock->CompleteLockIrpRoutine,
Context,
@@ -436,6 +456,7 @@
IoStatus->Status = STATUS_PENDING;
if (Irp)
{
+ Irp->IoStatus.Information = LockInfo->Generation;
IoMarkIrpPending(Irp);
IoCsqInsertIrpEx
(&LockInfo->Csq,
@@ -463,8 +484,10 @@
if (FailImmediately)
{
IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
+ DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
if (Irp)
{
+ DPRINT("STATUS_FILE_LOCK_CONFLICT:
Complete\n");
FsRtlCompleteLockIrpReal
(FileLock->CompleteLockIrpRoutine,
Context,
@@ -491,16 +514,14 @@
}
else
{
- /* We've made all overlapping shared ranges into one big
range
- * now we need to add a range entry for the new range */
DPRINT("Overlapping shared lock %wZ %08x%08x
%08x%08x\n",
&FileObject->FileName,
Conflict->Exclusive.FileLock.StartingByte.HighPart,
Conflict->Exclusive.FileLock.StartingByte.LowPart,
Conflict->Exclusive.FileLock.EndingByte.HighPart,
Conflict->Exclusive.FileLock.EndingByte.LowPart);
- Conflict = FsRtlpSubsumeSharedLock
- (FileLock, LockInfo, &ToInsert, Conflict);
+ Conflict = FsRtlpRebuildSharedLockRange
+ (FileLock, LockInfo, &ToInsert);
if (!Conflict)
{
IoStatus->Status = STATUS_NO_MEMORY;
@@ -514,77 +535,17 @@
&Status,
FileObject);
}
- return FALSE;
+ break;
}
}
}
}
/* We got here because there were only overlapping shared locks */
- DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n",
- &FileObject->FileName,
- Conflict->Exclusive.FileLock.StartingByte.HighPart,
- Conflict->Exclusive.FileLock.StartingByte.LowPart,
- Conflict->Exclusive.FileLock.EndingByte.HighPart,
- Conflict->Exclusive.FileLock.EndingByte.LowPart);
- if (!FsRtlpSubsumeSharedLock(FileLock, LockInfo, &ToInsert, Conflict))
- {
- IoStatus->Status = STATUS_NO_MEMORY;
- if (Irp)
- {
- FsRtlCompleteLockIrpReal
- (FileLock->CompleteLockIrpRoutine,
- Context,
- Irp,
- IoStatus->Status,
- &Status,
- FileObject);
- }
- return FALSE;
- }
- IoStatus->Status = STATUS_SUCCESS;
- if (Irp)
- {
- FsRtlCompleteLockIrpReal
- (FileLock->CompleteLockIrpRoutine,
- Context,
- Irp,
- IoStatus->Status,
- &Status,
- FileObject);
- }
- return TRUE;
- }
- }
- else if (!Conflict)
- {
- /* Conflict here is (or would be) the newly inserted element, but we ran
- * out of space probably. */
- IoStatus->Status = STATUS_NO_MEMORY;
- if (Irp)
- {
- FsRtlCompleteLockIrpReal
- (FileLock->CompleteLockIrpRoutine,
- Context,
- Irp,
- IoStatus->Status,
- &Status,
- FileObject);
- }
- return FALSE;
- }
- else
- {
- DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %d\n",
- &FileObject->FileName,
- Conflict->Exclusive.FileLock.StartingByte.HighPart,
- Conflict->Exclusive.FileLock.StartingByte.LowPart,
- Conflict->Exclusive.FileLock.EndingByte.HighPart,
- Conflict->Exclusive.FileLock.EndingByte.LowPart,
- Conflict->Exclusive.FileLock.ExclusiveLock);
- if (!ExclusiveLock)
- {
- PLOCK_SHARED_RANGE NewSharedRange;
+ /* A shared lock is both a range *and* a list entry. Insert the
+ entry here. */
+
+ DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
NewSharedRange =
ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange),
'FSRA');
if (!NewSharedRange)
@@ -608,6 +569,78 @@
NewSharedRange->Key = Key;
NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId;
InsertTailList(&LockInfo->SharedLocks,
&NewSharedRange->Entry);
+
+ DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n",
+ &FileObject->FileName,
+ Conflict->Exclusive.FileLock.StartingByte.HighPart,
+ Conflict->Exclusive.FileLock.StartingByte.LowPart,
+ Conflict->Exclusive.FileLock.EndingByte.HighPart,
+ Conflict->Exclusive.FileLock.EndingByte.LowPart);
+ IoStatus->Status = STATUS_SUCCESS;
+ if (Irp)
+ {
+ FsRtlCompleteLockIrpReal
+ (FileLock->CompleteLockIrpRoutine,
+ Context,
+ Irp,
+ IoStatus->Status,
+ &Status,
+ FileObject);
+ }
+ return TRUE;
+ }
+ }
+ else if (!Conflict)
+ {
+ /* Conflict here is (or would be) the newly inserted element, but we ran
+ * out of space probably. */
+ IoStatus->Status = STATUS_NO_MEMORY;
+ if (Irp)
+ {
+ FsRtlCompleteLockIrpReal
+ (FileLock->CompleteLockIrpRoutine,
+ Context,
+ Irp,
+ IoStatus->Status,
+ &Status,
+ FileObject);
+ }
+ return FALSE;
+ }
+ else
+ {
+ DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %d\n",
+ &FileObject->FileName,
+ Conflict->Exclusive.FileLock.StartingByte.HighPart,
+ Conflict->Exclusive.FileLock.StartingByte.LowPart,
+ Conflict->Exclusive.FileLock.EndingByte.HighPart,
+ Conflict->Exclusive.FileLock.EndingByte.LowPart,
+ Conflict->Exclusive.FileLock.ExclusiveLock);
+ if (!ExclusiveLock)
+ {
+ NewSharedRange =
+ ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange),
'FSRA');
+ if (!NewSharedRange)
+ {
+ IoStatus->Status = STATUS_NO_MEMORY;
+ if (Irp)
+ {
+ FsRtlCompleteLockIrpReal
+ (FileLock->CompleteLockIrpRoutine,
+ Context,
+ Irp,
+ IoStatus->Status,
+ &Status,
+ FileObject);
+ }
+ return FALSE;
+ }
+ DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
+ NewSharedRange->Start = ToInsert.Exclusive.FileLock.StartingByte;
+ NewSharedRange->End = ToInsert.Exclusive.FileLock.EndingByte;
+ NewSharedRange->Key = Key;
+ NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId;
+ InsertTailList(&LockInfo->SharedLocks,
&NewSharedRange->Entry);
}
/* Assume all is cool, and lock is set */
@@ -805,12 +838,14 @@
PCOMBINED_LOCK_ELEMENT Entry;
PIRP NextMatchingLockIrp;
PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
- DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x, Length %08x%08x, Key
%x)\n",
+ DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d),
Key %x)\n",
&FileObject->FileName,
FileOffset->HighPart,
FileOffset->LowPart,
+ (int)FileOffset->QuadPart,
Length->HighPart,
Length->LowPart,
+ (int)Length->QuadPart,
Key);
// The region to unlock must correspond exactly to a previously locked region
// -- msdn
@@ -819,6 +854,7 @@
Find.Exclusive.FileLock.StartingByte = *FileOffset;
Find.Exclusive.FileLock.EndingByte.QuadPart =
FileOffset->QuadPart + Length->QuadPart;
+ ASSERT(InternalInfo);
Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
if (!Entry) {
DPRINT("Range not locked %wZ\n", &FileObject->FileName);
@@ -879,11 +915,55 @@
}
if (FoundShared)
{
+ PLIST_ENTRY SharedRangeEntry;
+ PLOCK_SHARED_RANGE WatchSharedRange;
+ COMBINED_LOCK_ELEMENT RemadeElement;
+ PCOMBINED_LOCK_ELEMENT RemadeElementInserted = NULL;
Find.Exclusive.FileLock.StartingByte = SharedRange->Start;
Find.Exclusive.FileLock.EndingByte = SharedRange->End;
SharedEntry = SharedRange->Entry.Flink;
RemoveEntryList(&SharedRange->Entry);
ExFreePool(SharedRange);
+ /* We need to rebuild the list of shared ranges. */
+ DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n",
+ &FileObject->FileName,
+ Entry->Exclusive.FileLock.StartingByte.HighPart,
+ Entry->Exclusive.FileLock.StartingByte.LowPart,
+ Entry->Exclusive.FileLock.EndingByte.HighPart,
+ Entry->Exclusive.FileLock.EndingByte.LowPart);
+ /* Copy */
+ RemadeElement = *Entry;
+ RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
+ /* Put shared locks back in place */
+ for (SharedRangeEntry = InternalInfo->SharedLocks.Flink;
+ SharedRangeEntry != &InternalInfo->SharedLocks;
+ SharedRangeEntry = SharedRangeEntry->Flink)
+ {
+ COMBINED_LOCK_ELEMENT Find;
+ WatchSharedRange = CONTAINING_RECORD(SharedRangeEntry, LOCK_SHARED_RANGE,
Entry);
+ Find.Exclusive.FileLock.StartingByte = WatchSharedRange->Start;
+ Find.Exclusive.FileLock.EndingByte = WatchSharedRange->End;
+ if (LockCompare(&InternalInfo->RangeTable, &RemadeElement,
&Find) != GenericEqual)
+ {
+ DPRINT("Skipping range %08x%08x:%08x%08x\n",
+ Find.Exclusive.FileLock.StartingByte.HighPart,
+ Find.Exclusive.FileLock.StartingByte.LowPart,
+ Find.Exclusive.FileLock.EndingByte.HighPart,
+ Find.Exclusive.FileLock.EndingByte.LowPart);
+ continue;
+ }
+ DPRINT("Re-creating range %08x%08x:%08x%08x\n",
+ Find.Exclusive.FileLock.StartingByte.HighPart,
+ Find.Exclusive.FileLock.StartingByte.LowPart,
+ Find.Exclusive.FileLock.EndingByte.HighPart,
+ Find.Exclusive.FileLock.EndingByte.LowPart);
+ RtlZeroMemory(&RemadeElement, sizeof(RemadeElement));
+ RemadeElement.Exclusive.FileLock.StartingByte =
WatchSharedRange->Start;
+ RemadeElement.Exclusive.FileLock.EndingByte = WatchSharedRange->End;
+ RemadeElementInserted =
+ FsRtlpRebuildSharedLockRange
+ (FileLock, InternalInfo, &RemadeElement);
+ }
}
else
{
@@ -891,35 +971,36 @@
}
}
- if (IsListEmpty(&InternalInfo->SharedLocks)) {
- DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n",
- &FileObject->FileName,
- Entry->Exclusive.FileLock.StartingByte.HighPart,
- Entry->Exclusive.FileLock.StartingByte.LowPart,
- Entry->Exclusive.FileLock.EndingByte.HighPart,
- Entry->Exclusive.FileLock.EndingByte.LowPart);
- RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
- } else {
- DPRINT("Lock still has:\n");
- for (SharedEntry = InternalInfo->SharedLocks.Flink;
- SharedEntry != &InternalInfo->SharedLocks;
- SharedEntry = SharedEntry->Flink)
- {
- SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
- DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key
%x\n",
- &FileObject->FileName,
- SharedRange->Start.HighPart,
- SharedRange->Start.LowPart,
- SharedRange->End.HighPart,
- SharedRange->End.LowPart,
- SharedRange->Key);
- }
+ DPRINT("Lock still has:\n");
+ for (SharedEntry = InternalInfo->SharedLocks.Flink;
+ SharedEntry != &InternalInfo->SharedLocks;
+ SharedEntry = SharedEntry->Flink)
+ {
+ SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
+ DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n",
+ &FileObject->FileName,
+ SharedRange->Start.HighPart,
+ SharedRange->Start.LowPart,
+ SharedRange->End.HighPart,
+ SharedRange->End.LowPart,
+ SharedRange->Key);
}
// this is definitely the thing we want
- NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find);
- while (NextMatchingLockIrp)
- {
+ InternalInfo->Generation++;
+ while ((NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq,
&Find)))
+ {
+ if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation)
+ {
+ // We've already looked at this one, meaning that we looped.
+ // Put it back and exit.
+ IoCsqInsertIrpEx
+ (&InternalInfo->Csq,
+ NextMatchingLockIrp,
+ NULL,
+ NULL);
+ break;
+ }
// Got a new lock irp... try to do the new lock operation
// Note that we pick an operation that would succeed at the time
// we looked, but can't guarantee that it won't just be re-queued
@@ -943,17 +1024,37 @@
IN PEPROCESS Process,
IN PVOID Context OPTIONAL)
{
+ PLIST_ENTRY ListEntry;
PCOMBINED_LOCK_ELEMENT Entry;
- PRTL_GENERIC_TABLE InternalInfo = FileLock->LockInformation;
+ PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
// XXX Synchronize somehow
if (!FileLock->LockInformation) {
DPRINT("Not locked %wZ\n", &FileObject->FileName);
return STATUS_RANGE_NOT_LOCKED; // no locks
}
- for (Entry = RtlEnumerateGenericTable(InternalInfo, TRUE);
+ for (ListEntry = InternalInfo->SharedLocks.Flink;
+ ListEntry != &InternalInfo->SharedLocks;)
+ {
+ LARGE_INTEGER Length;
+ PLOCK_SHARED_RANGE Range = CONTAINING_RECORD(ListEntry, LOCK_SHARED_RANGE,
Entry);
+ Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
+ ListEntry = ListEntry->Flink;
+ if (Range->ProcessId != Process->UniqueProcessId)
+ continue;
+ FsRtlFastUnlockSingle
+ (FileLock,
+ FileObject,
+ &Range->Start,
+ &Length,
+ Range->ProcessId,
+ Range->Key,
+ Context,
+ 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...
@@ -985,6 +1086,7 @@
IN ULONG Key,
IN PVOID Context OPTIONAL)
{
+ PLIST_ENTRY ListEntry;
PCOMBINED_LOCK_ELEMENT Entry;
PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
@@ -992,6 +1094,26 @@
// XXX Synchronize somehow
if (!FileLock->LockInformation) return STATUS_RANGE_NOT_LOCKED; // no locks
+ for (ListEntry = InternalInfo->SharedLocks.Flink;
+ ListEntry != &InternalInfo->SharedLocks;)
+ {
+ PLOCK_SHARED_RANGE Range = CONTAINING_RECORD(ListEntry, LOCK_SHARED_RANGE,
Entry);
+ LARGE_INTEGER Length;
+ Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
+ ListEntry = ListEntry->Flink;
+ if (Range->ProcessId != Process->UniqueProcessId ||
+ Range->Key != Key)
+ continue;
+ FsRtlFastUnlockSingle
+ (FileLock,
+ FileObject,
+ &Range->Start,
+ &Length,
+ Range->ProcessId,
+ Range->Key,
+ Context,
+ TRUE);
+ }
for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
Entry;
Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))