mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 18:02:56 +00:00
[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. svn path=/trunk/; revision=56953
This commit is contained in:
parent
682ce04b5a
commit
c487b06067
1 changed files with 208 additions and 86 deletions
|
@ -21,12 +21,12 @@ PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList;
|
||||||
*/
|
*/
|
||||||
typedef union _COMBINED_LOCK_ELEMENT
|
typedef union _COMBINED_LOCK_ELEMENT
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
LIST_ENTRY dummy;
|
LIST_ENTRY dummy;
|
||||||
FILE_SHARED_LOCK_ENTRY Shared;
|
FILE_SHARED_LOCK_ENTRY Shared;
|
||||||
};
|
};
|
||||||
FILE_EXCLUSIVE_LOCK_ENTRY Exclusive;
|
FILE_EXCLUSIVE_LOCK_ENTRY Exclusive;
|
||||||
}
|
}
|
||||||
COMBINED_LOCK_ELEMENT, *PCOMBINED_LOCK_ELEMENT;
|
COMBINED_LOCK_ELEMENT, *PCOMBINED_LOCK_ELEMENT;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ typedef struct _LOCK_INFORMATION
|
||||||
LIST_ENTRY CsqList;
|
LIST_ENTRY CsqList;
|
||||||
PFILE_LOCK BelongsTo;
|
PFILE_LOCK BelongsTo;
|
||||||
LIST_ENTRY SharedLocks;
|
LIST_ENTRY SharedLocks;
|
||||||
|
ULONG Generation;
|
||||||
}
|
}
|
||||||
LOCK_INFORMATION, *PLOCK_INFORMATION;
|
LOCK_INFORMATION, *PLOCK_INFORMATION;
|
||||||
|
|
||||||
|
@ -224,6 +225,7 @@ FsRtlCompleteLockIrpReal(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteRoutine,
|
||||||
IN PFILE_OBJECT FileObject OPTIONAL)
|
IN PFILE_OBJECT FileObject OPTIONAL)
|
||||||
{
|
{
|
||||||
/* Check if we have a complete routine */
|
/* Check if we have a complete routine */
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
if (CompleteRoutine)
|
if (CompleteRoutine)
|
||||||
{
|
{
|
||||||
/* Check if we have a file object */
|
/* Check if we have a file object */
|
||||||
|
@ -260,55 +262,57 @@ FsRtlGetNextFileLock(IN PFILE_LOCK FileLock,
|
||||||
else return &Entry->Exclusive.FileLock;
|
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,
|
/* This function expands the conflicting range Conflict by removing and reinserting it,
|
||||||
then adds a shared range of the same size */
|
then adds a shared range of the same size */
|
||||||
PCOMBINED_LOCK_ELEMENT
|
PCOMBINED_LOCK_ELEMENT
|
||||||
NTAPI
|
NTAPI
|
||||||
FsRtlpSubsumeSharedLock
|
FsRtlpRebuildSharedLockRange
|
||||||
(PFILE_LOCK FileLock,
|
(PFILE_LOCK FileLock,
|
||||||
PLOCK_INFORMATION LockInfo,
|
PLOCK_INFORMATION LockInfo,
|
||||||
PCOMBINED_LOCK_ELEMENT ToInsert,
|
|
||||||
PCOMBINED_LOCK_ELEMENT Conflict)
|
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;
|
BOOLEAN InsertedNew = FALSE, RemovedOld;
|
||||||
COMBINED_LOCK_ELEMENT NewElement;
|
COMBINED_LOCK_ELEMENT NewElement = *Conflict;
|
||||||
PLOCK_SHARED_RANGE SharedRange =
|
PCOMBINED_LOCK_ELEMENT Entry;
|
||||||
ExAllocatePoolWithTag(NonPagedPool, sizeof(*SharedRange), 'FSRA');
|
while ((Entry = RtlLookupElementGenericTable
|
||||||
|
(FileLock->LockInformation, &NewElement)))
|
||||||
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 =
|
FsRtlpExpandLockElement(&NewElement, Entry);
|
||||||
Conflict->Exclusive.FileLock.StartingByte;
|
RemovedOld = RtlDeleteElementGenericTable
|
||||||
|
(&LockInfo->RangeTable,
|
||||||
|
Entry);
|
||||||
|
ASSERT(RemovedOld);
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
Conflict = RtlInsertElementGenericTable
|
Conflict = RtlInsertElementGenericTable
|
||||||
(&LockInfo->RangeTable,
|
(&LockInfo->RangeTable,
|
||||||
ToInsert,
|
&NewElement,
|
||||||
sizeof(*ToInsert),
|
sizeof(NewElement),
|
||||||
&InsertedNew);
|
&InsertedNew);
|
||||||
ASSERT(InsertedNew && Conflict);
|
ASSERT(InsertedNew);
|
||||||
return Conflict;
|
return Conflict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,20 +338,27 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
||||||
COMBINED_LOCK_ELEMENT ToInsert;
|
COMBINED_LOCK_ELEMENT ToInsert;
|
||||||
PCOMBINED_LOCK_ELEMENT Conflict;
|
PCOMBINED_LOCK_ELEMENT Conflict;
|
||||||
PLOCK_INFORMATION LockInfo;
|
PLOCK_INFORMATION LockInfo;
|
||||||
|
PLOCK_SHARED_RANGE NewSharedRange;
|
||||||
BOOLEAN InsertedNew;
|
BOOLEAN InsertedNew;
|
||||||
|
ULARGE_INTEGER UnsignedStart;
|
||||||
|
ULARGE_INTEGER UnsignedEnd;
|
||||||
|
|
||||||
DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x, Length %08x%08x, Key %x, FailImmediately %d, Exclusive %d)\n",
|
DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x, FailImmediately %d, Exclusive %d)\n",
|
||||||
&FileObject->FileName,
|
&FileObject->FileName,
|
||||||
FileOffset->HighPart,
|
FileOffset->HighPart,
|
||||||
FileOffset->LowPart,
|
FileOffset->LowPart,
|
||||||
|
(int)FileOffset->QuadPart,
|
||||||
Length->HighPart,
|
Length->HighPart,
|
||||||
Length->LowPart,
|
Length->LowPart,
|
||||||
|
(int)Length->QuadPart,
|
||||||
Key,
|
Key,
|
||||||
FailImmediately,
|
FailImmediately,
|
||||||
ExclusiveLock);
|
ExclusiveLock);
|
||||||
|
|
||||||
if (FileOffset->QuadPart < 0ll ||
|
UnsignedStart.QuadPart = FileOffset->QuadPart;
|
||||||
FileOffset->QuadPart + Length->QuadPart < FileOffset->QuadPart)
|
UnsignedEnd.QuadPart = FileOffset->QuadPart + Length->QuadPart;
|
||||||
|
|
||||||
|
if (UnsignedEnd.QuadPart < UnsignedStart.QuadPart)
|
||||||
{
|
{
|
||||||
DPRINT("File offset out of range\n");
|
DPRINT("File offset out of range\n");
|
||||||
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
||||||
|
@ -416,11 +427,20 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
||||||
{
|
{
|
||||||
if (Conflict->Exclusive.FileLock.ExclusiveLock || ExclusiveLock)
|
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)
|
if (FailImmediately)
|
||||||
{
|
{
|
||||||
|
DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
|
||||||
IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
|
IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
|
||||||
if (Irp)
|
if (Irp)
|
||||||
{
|
{
|
||||||
|
DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
|
||||||
FsRtlCompleteLockIrpReal
|
FsRtlCompleteLockIrpReal
|
||||||
(FileLock->CompleteLockIrpRoutine,
|
(FileLock->CompleteLockIrpRoutine,
|
||||||
Context,
|
Context,
|
||||||
|
@ -436,6 +456,7 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
||||||
IoStatus->Status = STATUS_PENDING;
|
IoStatus->Status = STATUS_PENDING;
|
||||||
if (Irp)
|
if (Irp)
|
||||||
{
|
{
|
||||||
|
Irp->IoStatus.Information = LockInfo->Generation;
|
||||||
IoMarkIrpPending(Irp);
|
IoMarkIrpPending(Irp);
|
||||||
IoCsqInsertIrpEx
|
IoCsqInsertIrpEx
|
||||||
(&LockInfo->Csq,
|
(&LockInfo->Csq,
|
||||||
|
@ -463,8 +484,10 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
||||||
if (FailImmediately)
|
if (FailImmediately)
|
||||||
{
|
{
|
||||||
IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
|
IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
|
||||||
|
DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
|
||||||
if (Irp)
|
if (Irp)
|
||||||
{
|
{
|
||||||
|
DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
|
||||||
FsRtlCompleteLockIrpReal
|
FsRtlCompleteLockIrpReal
|
||||||
(FileLock->CompleteLockIrpRoutine,
|
(FileLock->CompleteLockIrpRoutine,
|
||||||
Context,
|
Context,
|
||||||
|
@ -491,16 +514,14 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
||||||
}
|
}
|
||||||
else
|
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",
|
DPRINT("Overlapping shared lock %wZ %08x%08x %08x%08x\n",
|
||||||
&FileObject->FileName,
|
&FileObject->FileName,
|
||||||
Conflict->Exclusive.FileLock.StartingByte.HighPart,
|
Conflict->Exclusive.FileLock.StartingByte.HighPart,
|
||||||
Conflict->Exclusive.FileLock.StartingByte.LowPart,
|
Conflict->Exclusive.FileLock.StartingByte.LowPart,
|
||||||
Conflict->Exclusive.FileLock.EndingByte.HighPart,
|
Conflict->Exclusive.FileLock.EndingByte.HighPart,
|
||||||
Conflict->Exclusive.FileLock.EndingByte.LowPart);
|
Conflict->Exclusive.FileLock.EndingByte.LowPart);
|
||||||
Conflict = FsRtlpSubsumeSharedLock
|
Conflict = FsRtlpRebuildSharedLockRange
|
||||||
(FileLock, LockInfo, &ToInsert, Conflict);
|
(FileLock, LockInfo, &ToInsert);
|
||||||
if (!Conflict)
|
if (!Conflict)
|
||||||
{
|
{
|
||||||
IoStatus->Status = STATUS_NO_MEMORY;
|
IoStatus->Status = STATUS_NO_MEMORY;
|
||||||
|
@ -514,20 +535,20 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
||||||
&Status,
|
&Status,
|
||||||
FileObject);
|
FileObject);
|
||||||
}
|
}
|
||||||
return FALSE;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We got here because there were only overlapping shared locks */
|
/* We got here because there were only overlapping shared locks */
|
||||||
DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n",
|
/* A shared lock is both a range *and* a list entry. Insert the
|
||||||
&FileObject->FileName,
|
entry here. */
|
||||||
Conflict->Exclusive.FileLock.StartingByte.HighPart,
|
|
||||||
Conflict->Exclusive.FileLock.StartingByte.LowPart,
|
DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
|
||||||
Conflict->Exclusive.FileLock.EndingByte.HighPart,
|
NewSharedRange =
|
||||||
Conflict->Exclusive.FileLock.EndingByte.LowPart);
|
ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), 'FSRA');
|
||||||
if (!FsRtlpSubsumeSharedLock(FileLock, LockInfo, &ToInsert, Conflict))
|
if (!NewSharedRange)
|
||||||
{
|
{
|
||||||
IoStatus->Status = STATUS_NO_MEMORY;
|
IoStatus->Status = STATUS_NO_MEMORY;
|
||||||
if (Irp)
|
if (Irp)
|
||||||
|
@ -542,6 +563,19 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
||||||
}
|
}
|
||||||
return FALSE;
|
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);
|
||||||
|
|
||||||
|
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;
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
if (Irp)
|
if (Irp)
|
||||||
{
|
{
|
||||||
|
@ -584,7 +618,6 @@ FsRtlPrivateLock(IN PFILE_LOCK FileLock,
|
||||||
Conflict->Exclusive.FileLock.ExclusiveLock);
|
Conflict->Exclusive.FileLock.ExclusiveLock);
|
||||||
if (!ExclusiveLock)
|
if (!ExclusiveLock)
|
||||||
{
|
{
|
||||||
PLOCK_SHARED_RANGE NewSharedRange;
|
|
||||||
NewSharedRange =
|
NewSharedRange =
|
||||||
ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), 'FSRA');
|
ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), 'FSRA');
|
||||||
if (!NewSharedRange)
|
if (!NewSharedRange)
|
||||||
|
@ -805,12 +838,14 @@ FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock,
|
||||||
PCOMBINED_LOCK_ELEMENT Entry;
|
PCOMBINED_LOCK_ELEMENT Entry;
|
||||||
PIRP NextMatchingLockIrp;
|
PIRP NextMatchingLockIrp;
|
||||||
PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
|
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,
|
&FileObject->FileName,
|
||||||
FileOffset->HighPart,
|
FileOffset->HighPart,
|
||||||
FileOffset->LowPart,
|
FileOffset->LowPart,
|
||||||
|
(int)FileOffset->QuadPart,
|
||||||
Length->HighPart,
|
Length->HighPart,
|
||||||
Length->LowPart,
|
Length->LowPart,
|
||||||
|
(int)Length->QuadPart,
|
||||||
Key);
|
Key);
|
||||||
// The region to unlock must correspond exactly to a previously locked region
|
// The region to unlock must correspond exactly to a previously locked region
|
||||||
// -- msdn
|
// -- msdn
|
||||||
|
@ -819,6 +854,7 @@ FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock,
|
||||||
Find.Exclusive.FileLock.StartingByte = *FileOffset;
|
Find.Exclusive.FileLock.StartingByte = *FileOffset;
|
||||||
Find.Exclusive.FileLock.EndingByte.QuadPart =
|
Find.Exclusive.FileLock.EndingByte.QuadPart =
|
||||||
FileOffset->QuadPart + Length->QuadPart;
|
FileOffset->QuadPart + Length->QuadPart;
|
||||||
|
ASSERT(InternalInfo);
|
||||||
Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
|
Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
|
||||||
if (!Entry) {
|
if (!Entry) {
|
||||||
DPRINT("Range not locked %wZ\n", &FileObject->FileName);
|
DPRINT("Range not locked %wZ\n", &FileObject->FileName);
|
||||||
|
@ -879,11 +915,55 @@ FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock,
|
||||||
}
|
}
|
||||||
if (FoundShared)
|
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.StartingByte = SharedRange->Start;
|
||||||
Find.Exclusive.FileLock.EndingByte = SharedRange->End;
|
Find.Exclusive.FileLock.EndingByte = SharedRange->End;
|
||||||
SharedEntry = SharedRange->Entry.Flink;
|
SharedEntry = SharedRange->Entry.Flink;
|
||||||
RemoveEntryList(&SharedRange->Entry);
|
RemoveEntryList(&SharedRange->Entry);
|
||||||
ExFreePool(SharedRange);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -891,35 +971,36 @@ FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsListEmpty(&InternalInfo->SharedLocks)) {
|
DPRINT("Lock still has:\n");
|
||||||
DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n",
|
for (SharedEntry = InternalInfo->SharedLocks.Flink;
|
||||||
&FileObject->FileName,
|
SharedEntry != &InternalInfo->SharedLocks;
|
||||||
Entry->Exclusive.FileLock.StartingByte.HighPart,
|
SharedEntry = SharedEntry->Flink)
|
||||||
Entry->Exclusive.FileLock.StartingByte.LowPart,
|
{
|
||||||
Entry->Exclusive.FileLock.EndingByte.HighPart,
|
SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
|
||||||
Entry->Exclusive.FileLock.EndingByte.LowPart);
|
DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n",
|
||||||
RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
|
&FileObject->FileName,
|
||||||
} else {
|
SharedRange->Start.HighPart,
|
||||||
DPRINT("Lock still has:\n");
|
SharedRange->Start.LowPart,
|
||||||
for (SharedEntry = InternalInfo->SharedLocks.Flink;
|
SharedRange->End.HighPart,
|
||||||
SharedEntry != &InternalInfo->SharedLocks;
|
SharedRange->End.LowPart,
|
||||||
SharedEntry = SharedEntry->Flink)
|
SharedRange->Key);
|
||||||
{
|
|
||||||
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
|
// this is definitely the thing we want
|
||||||
NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find);
|
InternalInfo->Generation++;
|
||||||
while (NextMatchingLockIrp)
|
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
|
// Got a new lock irp... try to do the new lock operation
|
||||||
// Note that we pick an operation that would succeed at the time
|
// 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
|
// we looked, but can't guarantee that it won't just be re-queued
|
||||||
|
@ -943,17 +1024,37 @@ FsRtlFastUnlockAll(IN PFILE_LOCK FileLock,
|
||||||
IN PEPROCESS Process,
|
IN PEPROCESS Process,
|
||||||
IN PVOID Context OPTIONAL)
|
IN PVOID Context OPTIONAL)
|
||||||
{
|
{
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
PCOMBINED_LOCK_ELEMENT Entry;
|
PCOMBINED_LOCK_ELEMENT Entry;
|
||||||
PRTL_GENERIC_TABLE InternalInfo = FileLock->LockInformation;
|
PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
|
||||||
DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
|
DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
|
||||||
// XXX Synchronize somehow
|
// XXX Synchronize somehow
|
||||||
if (!FileLock->LockInformation) {
|
if (!FileLock->LockInformation) {
|
||||||
DPRINT("Not locked %wZ\n", &FileObject->FileName);
|
DPRINT("Not locked %wZ\n", &FileObject->FileName);
|
||||||
return STATUS_RANGE_NOT_LOCKED; // no locks
|
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;
|
||||||
Entry = RtlEnumerateGenericTable(InternalInfo, FALSE))
|
Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
|
||||||
{
|
{
|
||||||
LARGE_INTEGER Length;
|
LARGE_INTEGER Length;
|
||||||
// We'll take the first one to be the list head, and free the others first...
|
// We'll take the first one to be the list head, and free the others first...
|
||||||
|
@ -985,6 +1086,7 @@ FsRtlFastUnlockAllByKey(IN PFILE_LOCK FileLock,
|
||||||
IN ULONG Key,
|
IN ULONG Key,
|
||||||
IN PVOID Context OPTIONAL)
|
IN PVOID Context OPTIONAL)
|
||||||
{
|
{
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
PCOMBINED_LOCK_ELEMENT Entry;
|
PCOMBINED_LOCK_ELEMENT Entry;
|
||||||
PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
|
PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
|
||||||
|
|
||||||
|
@ -992,6 +1094,26 @@ FsRtlFastUnlockAllByKey(IN PFILE_LOCK FileLock,
|
||||||
|
|
||||||
// XXX Synchronize somehow
|
// XXX Synchronize somehow
|
||||||
if (!FileLock->LockInformation) return STATUS_RANGE_NOT_LOCKED; // no locks
|
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);
|
for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
|
||||||
Entry;
|
Entry;
|
||||||
Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
|
Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue