filelock.c:

-general cleanup
-fix signed -> unsigned comparsion
-allow zero length unlocks to complete with success
-makes some more wine reg. tests pass
ntdef.h: add macros LIST_FOR_EACH and LIST_FOR_EACH_SAFE

svn path=/trunk/; revision=12391
This commit is contained in:
Gunnar Dalsnes 2004-12-30 02:30:40 +00:00
parent f5e28a77d1
commit c97559f3c5
5 changed files with 258 additions and 233 deletions

View file

@ -113,12 +113,5 @@
#endif /* !__USE_W32API */
typedef struct _FILE_LOCK_TOC {
KSPIN_LOCK SpinLock;
LIST_ENTRY GrantedListHead;
LIST_ENTRY PendingListHead;
LIST_ENTRY CompletedListHead;
LIST_ENTRY UnlockedListHead;
} FILE_LOCK_TOC, *PFILE_LOCK_TOC;
#endif /* __INCLUDE_FILE_H */

View file

@ -27,9 +27,15 @@ typedef struct _MCB {
typedef struct _FILE_LOCK_GRANTED {
LIST_ENTRY ListEntry;
FILE_LOCK_INFO Lock;
FILE_LOCK_INFO Lock;
PVOID UnlockContext;
} FILE_LOCK_GRANTED, *PFILE_LOCK_GRANTED;
typedef struct _FILE_LOCK_TOC {
KSPIN_LOCK SpinLock;
LIST_ENTRY GrantedListHead;
LIST_ENTRY PendingListHead;
} FILE_LOCK_TOC, *PFILE_LOCK_TOC;
#endif /* __INCLUDE_DDK_FSTYPES_H */

View file

@ -39,6 +39,20 @@
#define SECONDS_TO_100NS(seconds) (((LONGLONG)(seconds)) * MILLIS_TO_100NS(1000L))
/* Helpers for enumarating lists */
#define LIST_FOR_EACH(entry, head) \
for(entry = (head)->Flink; entry != (head); entry = entry->Flink)
/*
Safe version which saves pointer to the next entry so the current ptr->field entry
can be unlinked without corrupting the list. NOTE: Never unlink tmp_entry!!!!!!!!!
*/
#define LIST_FOR_EACH_SAFE(tmp_entry, head, ptr, type, field) \
for ((tmp_entry)=(head)->Flink; (tmp_entry)!=(head) && \
((ptr) = CONTAINING_RECORD(tmp_entry,type,field)) && \
((tmp_entry) = (tmp_entry)->Flink); )
#ifndef __USE_W32API
#define ANYSIZE_ARRAY (1)

View file

@ -1,4 +1,4 @@
/* $Id: filelock.c,v 1.16 2004/12/23 12:30:48 ekohl Exp $
/* $Id: filelock.c,v 1.17 2004/12/30 02:30:40 gdalsnes Exp $
*
* reactos/ntoskrnl/fs/filelock.c
*
@ -13,18 +13,54 @@ NOTE:
I'm not using resource syncronization here, since FsRtlFastCheckLockForRead/Write
are allowed to be called at DISPATCH_LEVEL. Must therefore use nonpaged memory for
the lists.
UPDATE: I'm not sure about this! -Gunnar
*/
#define LOCK_START_OFF(Lock) ((Lock).StartingByte.QuadPart)
#define LOCK_END_OFF(Lock) (((Lock).StartingByte.QuadPart) + ((Lock).Length.QuadPart) - 1)
#define REQUEST_START_OFF (FileOffset->QuadPart)
#define REQUEST_END_OFF ((FileOffset->QuadPart) + (Length->QuadPart) - 1)
FAST_MUTEX LockTocMutex;
NPAGED_LOOKASIDE_LIST GrantedLookaside;
NPAGED_LOOKASIDE_LIST LockTocLookaside;
PAGED_LOOKASIDE_LIST LockLookaside;
inline BOOLEAN
IsOverlappingLock(
PFILE_LOCK_INFO Lock,
PLARGE_INTEGER StartOffset,
PLARGE_INTEGER EndOffset
)
{
if ((ULONGLONG)StartOffset->QuadPart > (ULONGLONG)Lock->EndingByte.QuadPart)
{
return FALSE;
}
if ((ULONGLONG)EndOffset->QuadPart < (ULONGLONG)Lock->StartingByte.QuadPart)
{
return FALSE;
}
return TRUE;
}
inline BOOLEAN
IsSurroundingLock(
PFILE_LOCK_INFO Lock,
PLARGE_INTEGER StartOffset,
PLARGE_INTEGER EndOffset
)
{
if ((ULONGLONG)StartOffset->QuadPart >= (ULONGLONG)Lock->StartingByte.QuadPart &&
(ULONGLONG)EndOffset->QuadPart <= (ULONGLONG)Lock->EndingByte.QuadPart)
{
return TRUE;
}
return FALSE;
}
/**********************************************************************
* NAME PRIVATE
* FsRtlpInitFileLockingImplementation
@ -62,6 +98,7 @@ FsRtlpInitFileLockingImplementation(VOID)
);
ExInitializeFastMutex(&LockTocMutex);
}
/**********************************************************************
@ -78,28 +115,22 @@ FsRtlpFileLockCancelRoutine(
{
KIRQL oldIrql;
PKSPIN_LOCK SpinLock;
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine;
//don't need this since we have our own sync. protecting irp cancellation
IoReleaseCancelSpinLock(Irp->CancelIrql);
SpinLock = &((PFILE_LOCK_TOC)Irp->Tail.Overlay.DriverContext[1])->SpinLock;
SpinLock = Irp->Tail.Overlay.DriverContext[3];
KeAcquireSpinLock(SpinLock, &oldIrql);
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(SpinLock, oldIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
CompleteLockIrpRoutine = ((PFILE_LOCK)Irp->Tail.Overlay.DriverContext[0])->CompleteLockIrpRoutine;
if (CompleteLockIrpRoutine)
{
CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
}
else
{
IofCompleteRequest(Irp, IO_NO_INCREMENT);
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
@ -107,6 +138,9 @@ FsRtlpFileLockCancelRoutine(
* NAME PRIVATE
* FsRtlpCheckLockForReadOrWriteAccess
*
* Return:
* TRUE: can read/write
* FALSE: can't read/write
*/
BOOLEAN
FASTCALL
@ -124,8 +158,10 @@ FsRtlpCheckLockForReadOrWriteAccess(
PFILE_LOCK_TOC LockToc;
PFILE_LOCK_GRANTED Granted;
PLIST_ENTRY EnumEntry;
LARGE_INTEGER EndOffset;
ASSERT(FileLock);
LockToc = FileLock->LockInformation;
if (LockToc == NULL || Length->QuadPart == 0)
@ -133,15 +169,16 @@ FsRtlpCheckLockForReadOrWriteAccess(
return TRUE;
}
EndOffset.QuadPart = FileOffset->QuadPart + Length->QuadPart - 1;
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
EnumEntry = LockToc->GrantedListHead.Flink;
while ( EnumEntry != &LockToc->GrantedListHead)
LIST_FOR_EACH(EnumEntry, &LockToc->GrantedListHead)
{
Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED , ListEntry );
Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED, ListEntry);
//if overlapping
if(!(REQUEST_START_OFF > LOCK_END_OFF(Granted->Lock) ||
REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock)))
if(IsOverlappingLock(&Granted->Lock, FileOffset, &EndOffset))
{
//No read conflict if (shared lock) OR (exclusive + our lock)
//No write conflict if exclusive lock AND our lock
@ -152,30 +189,26 @@ FsRtlpCheckLockForReadOrWriteAccess(
Granted->Lock.Key == Key ) )
{
//AND if lock surround request region, stop searching and grant
if (REQUEST_START_OFF >= LOCK_START_OFF(Granted->Lock) &&
REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock))
if (IsSurroundingLock(&Granted->Lock, FileOffset, &EndOffset) )
{
EnumEntry = &LockToc->GrantedListHead;//indicate no conflict
break;
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
return TRUE;
}
//else continue searching for conflicts
continue;
}
else //conflict
{
break;
}
//found conflict
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
return FALSE;
}
EnumEntry = EnumEntry->Flink;
}
//no conflict
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
if (EnumEntry == &LockToc->GrantedListHead)
{ //no conflict
return TRUE;
}
return FALSE;
return TRUE;
}
@ -206,7 +239,7 @@ FsRtlCheckLockForReadAccess (
Stack->Parameters.Read.Key,
Stack->FileObject,
IoGetRequestorProcess(Irp),
TRUE//Read?
TRUE /* Read */
);
}
@ -238,7 +271,7 @@ FsRtlCheckLockForWriteAccess (
Stack->Parameters.Write.Key,
Stack->FileObject,
IoGetRequestorProcess(Irp),
FALSE//Read?
FALSE /* Read */
);
}
@ -269,7 +302,7 @@ FsRtlFastCheckLockForRead (
Key,
FileObject,
Process,
TRUE//Read?
TRUE /* Read */
);
}
@ -297,7 +330,7 @@ FsRtlFastCheckLockForWrite (
Key,
FileObject,
Process,
FALSE//Read?
FALSE /* Read */
);
}
@ -314,8 +347,8 @@ FsRtlpFastUnlockAllByKey(
IN PFILE_LOCK FileLock,
IN PFILE_OBJECT FileObject,
IN PEPROCESS Process,
IN DWORD Key, /* FIXME: guess */
IN BOOLEAN UseKey, /* FIXME: guess */
IN DWORD Key,
IN BOOLEAN UseKey,
IN PVOID Context OPTIONAL
)
{
@ -325,7 +358,8 @@ FsRtlpFastUnlockAllByKey(
PFILE_LOCK_GRANTED Granted;
BOOLEAN Unlock = FALSE;
//must make local copy since FILE_LOCK struct is allowed to be paged
PUNLOCK_ROUTINE GotUnlockRoutine;
BOOLEAN GotUnlockRoutine;
LIST_ENTRY UnlockedListHead;
ASSERT(FileLock);
LockToc = FileLock->LockInformation;
@ -335,15 +369,13 @@ FsRtlpFastUnlockAllByKey(
return STATUS_RANGE_NOT_LOCKED;
}
GotUnlockRoutine = FileLock->UnlockRoutine;
InitializeListHead(&UnlockedListHead);
GotUnlockRoutine = FileLock->UnlockRoutine != NULL;
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
EnumEntry = LockToc->GrantedListHead.Flink;
while (EnumEntry != &LockToc->GrantedListHead )
LIST_FOR_EACH_SAFE(EnumEntry, &LockToc->GrantedListHead, Granted, FILE_LOCK_GRANTED, ListEntry)
{
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
EnumEntry = EnumEntry->Flink;
if (Granted->Lock.Process == Process &&
Granted->Lock.FileObject == FileObject &&
(!UseKey || (UseKey && Granted->Lock.Key == Key)) )
@ -357,7 +389,7 @@ FsRtlpFastUnlockAllByKey(
Put on unlocked list and call unlock routine for them afterwards.
This way we don't have to restart enum after each call
*/
InsertHeadList(&LockToc->UnlockedListHead,&Granted->ListEntry);
InsertHeadList(&UnlockedListHead,&Granted->ListEntry);
}
else
{
@ -366,21 +398,23 @@ FsRtlpFastUnlockAllByKey(
}
}
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
if (Unlock)
{
//call unlock routine for each unlocked lock (if any)
while (!IsListEmpty(&LockToc->UnlockedListHead))
while (!IsListEmpty(&UnlockedListHead))
{
EnumEntry = RemoveTailList(&LockToc->UnlockedListHead);
EnumEntry = RemoveTailList(&UnlockedListHead);
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
FileLock->UnlockRoutine(Context,&Granted->Lock);
FileLock->UnlockRoutine(Granted->UnlockContext, &Granted->Lock);
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
}
//NOTE: holding spinlock while calling this
FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql);
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
if (IsListEmpty(&LockToc->GrantedListHead))
{
@ -391,10 +425,10 @@ FsRtlpFastUnlockAllByKey(
{
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
}
return STATUS_SUCCESS;
}
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
return STATUS_RANGE_NOT_LOCKED;
}
@ -416,9 +450,9 @@ FsRtlFastUnlockAll /*ByProcess*/ (
return FsRtlpFastUnlockAllByKey( FileLock,
FileObject,
Process,
0, /* Key */
0, /* Key is ignored */
FALSE, /* Do NOT use Key */
Context
Context
);
}
@ -443,7 +477,7 @@ FsRtlFastUnlockAllByKey (
Process,
Key,
TRUE, /* Use Key */
Context
Context
);
}
@ -455,7 +489,7 @@ FsRtlFastUnlockAllByKey (
* NOTE
* Spinlock held at entry !!
*/
NTSTATUS
BOOLEAN
FASTCALL
FsRtlpAddLock(
IN PFILE_LOCK_TOC LockToc,
@ -464,58 +498,60 @@ FsRtlpAddLock(
IN PLARGE_INTEGER Length,
IN PEPROCESS Process,
IN ULONG Key,
IN BOOLEAN ExclusiveLock
IN BOOLEAN ExclusiveLock,
IN PVOID Context
)
{
PLIST_ENTRY EnumEntry;
PFILE_LOCK_GRANTED Granted;
LARGE_INTEGER EndOffset;
EndOffset.QuadPart = FileOffset->QuadPart + Length->QuadPart - 1;
EnumEntry = LockToc->GrantedListHead.Flink;
while (EnumEntry != &LockToc->GrantedListHead)
//loop and try to find conflicking locks
LIST_FOR_EACH(EnumEntry, &LockToc->GrantedListHead)
{
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
//if overlapping
if(!(REQUEST_START_OFF > LOCK_END_OFF(Granted->Lock) ||
REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock)))
if (IsOverlappingLock(&Granted->Lock, FileOffset, &EndOffset))
{
//never conflict if shared lock and we want to add a shared lock
//we found a locks that overlap with the new lock
//if both locks are shared, we might have a fast path outa here...
if (!Granted->Lock.ExclusiveLock && !ExclusiveLock)
{
//AND if lock surround region, stop searching and insert lock
if (REQUEST_START_OFF >= LOCK_START_OFF(Granted->Lock) &&
REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock))
//if existing lock surround new lock, we know that no other exclusive lock
//may overlap with our new lock;-D
if (IsSurroundingLock(&Granted->Lock, FileOffset, &EndOffset))
{
EnumEntry = &LockToc->GrantedListHead;
break;
}
//else keep locking for conflicts
continue;
}
else
{//conflict if we want share access to excl. lock OR exlc. access to shared lock
break;//FAIL
}
//we found a conflict:
//we want shared access to an excl. lock OR exlc. access to a shared lock
return FALSE;
}
EnumEntry = EnumEntry->Flink;
}
if (EnumEntry == &LockToc->GrantedListHead)
{//no conflict
Granted = ExAllocateFromNPagedLookasideList(&GrantedLookaside);
Granted = ExAllocateFromNPagedLookasideList(&GrantedLookaside);
Granted->Lock.StartingByte = *FileOffset;
Granted->Lock.Length = *Length;
Granted->Lock.ExclusiveLock = ExclusiveLock;
Granted->Lock.Key = Key;
Granted->Lock.FileObject = FileObject;
Granted->Lock.Process = Process;
Granted->Lock.EndingByte.QuadPart = REQUEST_END_OFF;
InsertHeadList(&LockToc->GrantedListHead,&Granted->ListEntry);
return TRUE;
}
return FALSE;
//starting offset
Granted->Lock.StartingByte = *FileOffset;
Granted->Lock.Length = *Length;
Granted->Lock.ExclusiveLock = ExclusiveLock;
Granted->Lock.Key = Key;
Granted->Lock.FileObject = FileObject;
Granted->Lock.Process = Process;
//ending offset
Granted->Lock.EndingByte = EndOffset;
Granted->UnlockContext = Context;
InsertHeadList(&LockToc->GrantedListHead,&Granted->ListEntry);
return TRUE;
}
@ -532,19 +568,20 @@ FASTCALL
FsRtlpCompletePendingLocks(
IN PFILE_LOCK FileLock,
IN PFILE_LOCK_TOC LockToc,
IN OUT PKIRQL oldirql
IN OUT PKIRQL oldirql,
IN PVOID Context
)
{
//walk pending list, FIFO order, try 2 complete locks
PLIST_ENTRY EnumEntry;
PIRP Irp;
PIO_STACK_LOCATION Stack;
EnumEntry = LockToc->PendingListHead.Blink;
while (EnumEntry != &LockToc->PendingListHead)
LIST_ENTRY CompletedListHead;
InitializeListHead(&CompletedListHead);
LIST_FOR_EACH_SAFE(EnumEntry, &LockToc->PendingListHead, Irp, IRP, Tail.Overlay.ListEntry)
{
Irp = CONTAINING_RECORD(EnumEntry,IRP, Tail.Overlay.ListEntry);
Stack = IoGetCurrentIrpStackLocation(Irp);
if (FsRtlpAddLock(LockToc,
Stack->FileObject,
@ -552,55 +589,65 @@ FsRtlpCompletePendingLocks(
Stack->Parameters.LockControl.Length,
IoGetRequestorProcess(Irp),
Stack->Parameters.LockControl.Key,
Stack->Flags & SL_EXCLUSIVE_LOCK
Stack->Flags & SL_EXCLUSIVE_LOCK,
Irp->Tail.Overlay.DriverContext[2] //Context
) )
{
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
if (!IoSetCancelRoutine(Irp, NULL))
{
/*
Cancel routine WILL be called after we release the spinlock. It will try to remove
the irp from the list and cancel/complete this irp. Since we allready removed it,
make its ListEntry point to itself.
*/
//irp is canceled and cancelroutine will run when we release the lock
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
continue;
}
else
{
/*
Cancel routine will NOT be called, canceled or not.
Put on completed list and complete them all afterwards.
This way we don't have to restart enum after each completion.
*/
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
InsertHeadList(&LockToc->CompletedListHead,&Irp->Tail.Overlay.ListEntry);
}
/*
Put on completed list and complete them all afterwards.
This way we don't have to restart enum after each completion.
*/
InsertHeadList(&CompletedListHead, &Irp->Tail.Overlay.ListEntry);
}
EnumEntry = EnumEntry->Blink;
}
KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);
//complete irp's (if any)
while (!IsListEmpty(&LockToc->CompletedListHead))
while (!IsListEmpty(&CompletedListHead))
{
EnumEntry = RemoveTailList(&LockToc->CompletedListHead);
KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);//fires cancel routine
EnumEntry = RemoveTailList(&CompletedListHead);
Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
if (FileLock->CompleteLockIrpRoutine)
{
FileLock->CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
if (FileLock->CompleteLockIrpRoutine(Context, Irp)!=STATUS_SUCCESS)
{
Stack = IoGetCurrentIrpStackLocation(Irp);
//revert
FsRtlpUnlockSingle ( FileLock,
Stack->FileObject,
&Stack->Parameters.LockControl.ByteOffset,
Stack->Parameters.LockControl.Length,
IoGetRequestorProcess(Irp),
Stack->Parameters.LockControl.Key,
NULL, /* unused context */
FALSE /* don't call unlock copletion rout.*/
);
}
}
else
{
IofCompleteRequest(Irp, IO_NO_INCREMENT);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
}
KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
}
@ -620,7 +667,6 @@ FsRtlpUnlockSingle(
IN PEPROCESS Process,
IN ULONG Key,
IN PVOID Context OPTIONAL,
IN BOOLEAN AlreadySynchronized,
IN BOOLEAN CallUnlockRoutine
)
{
@ -632,18 +678,16 @@ FsRtlpUnlockSingle(
ASSERT(FileLock);
LockToc = FileLock->LockInformation;
if (LockToc == NULL || Length->QuadPart == 0)
if (LockToc == NULL)
{
return STATUS_RANGE_NOT_LOCKED;
}
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql );
EnumEntry = LockToc->GrantedListHead.Flink;
while (EnumEntry != &LockToc->GrantedListHead)
LIST_FOR_EACH_SAFE(EnumEntry, &LockToc->GrantedListHead, Granted,FILE_LOCK_GRANTED,ListEntry)
{
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
//must be exact match
if (FileOffset->QuadPart == Granted->Lock.StartingByte.QuadPart &&
Length->QuadPart == Granted->Lock.Length.QuadPart &&
@ -652,12 +696,13 @@ FsRtlpUnlockSingle(
Granted->Lock.Key == Key)
{
RemoveEntryList(&Granted->ListEntry);
FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql);
FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
if (IsListEmpty(&LockToc->GrantedListHead))
{
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
FsRtlAreThereCurrentFileLocks(FileLock) = FALSE; //paged data
}
else
{
@ -666,14 +711,13 @@ FsRtlpUnlockSingle(
if (FileLock->UnlockRoutine && CallUnlockRoutine)
{
FileLock->UnlockRoutine(Context,&Granted->Lock);
FileLock->UnlockRoutine(Granted->UnlockContext, &Granted->Lock);
}
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
ExFreeToNPagedLookasideList(&GrantedLookaside, Granted);
return STATUS_SUCCESS;
}
EnumEntry = EnumEntry->Flink;
}
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
@ -710,8 +754,7 @@ FsRtlFastUnlockSingle (
Process,
Key,
Context,
AlreadySynchronized,
TRUE//CallUnlockRoutine
TRUE /* call unlock copletion routine */
);
}
@ -747,11 +790,10 @@ FsRtlpDumpFileLocks(
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
EnumEntry = LockToc->GrantedListHead.Blink;
while ( EnumEntry != &LockToc->GrantedListHead)
LIST_FOR_EACH(EnumEntry, &LockToc->GrantedListHead)
{
Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED , ListEntry );
Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED , ListEntry);
DPRINT1("%s, start: %i, len: %i, end: %i, key: %i, proc: 0x%X, fob: 0x%X\n",
Granted->Lock.ExclusiveLock ? "EXCL" : "SHRD",
Granted->Lock.StartingByte.QuadPart,
@ -762,16 +804,13 @@ FsRtlpDumpFileLocks(
Granted->Lock.FileObject
);
EnumEntry = EnumEntry->Blink;
}
DPRINT1("Dumping pending file locks, FIFO order\n");
EnumEntry = LockToc->PendingListHead.Blink;
while ( EnumEntry != &LockToc->PendingListHead)
LIST_FOR_EACH(EnumEntry, &LockToc->PendingListHead)
{
Irp = CONTAINING_RECORD(EnumEntry, IRP , Tail.Overlay.ListEntry );
Irp = CONTAINING_RECORD(EnumEntry, IRP , Tail.Overlay.ListEntry);
Stack = IoGetCurrentIrpStackLocation(Irp);
DPRINT1("%s, start: %i, len: %i, end: %i, key: %i, proc: 0x%X, fob: 0x%X\n",
@ -784,7 +823,6 @@ FsRtlpDumpFileLocks(
Stack->FileObject
);
EnumEntry = EnumEntry->Blink;
}
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
@ -939,7 +977,7 @@ FsRtlPrivateLock (
IN BOOLEAN ExclusiveLock,
OUT PIO_STATUS_BLOCK IoStatus,
IN PIRP Irp OPTIONAL,
IN PVOID Context,
IN PVOID Context OPTIONAL,
IN BOOLEAN AlreadySynchronized
)
{
@ -958,8 +996,6 @@ FsRtlPrivateLock (
KeInitializeSpinLock(&LockToc->SpinLock);
InitializeListHead(&LockToc->GrantedListHead);
InitializeListHead(&LockToc->PendingListHead);
InitializeListHead(&LockToc->CompletedListHead);
InitializeListHead(&LockToc->UnlockedListHead);
}
ExReleaseFastMutex(&LockTocMutex);
}
@ -974,43 +1010,36 @@ FsRtlPrivateLock (
Length,
Process,
Key,
ExclusiveLock
ExclusiveLock,
Context
) )
{
IoStatus->Status = STATUS_SUCCESS;
}
else if (Irp && !FailImmediately)
{ //failed + irp + no fail = mk. pending
//for our cancel routine
Irp->Tail.Overlay.DriverContext[0] = (PVOID)FileLock;
Irp->Tail.Overlay.DriverContext[1] = (PVOID)LockToc;
{
//failed + irp + no fail = make. pending
Irp->Tail.Overlay.DriverContext[3] = &LockToc->SpinLock;
Irp->Tail.Overlay.DriverContext[2] = Context;
IoSetCancelRoutine(Irp, FsRtlpFileLockCancelRoutine);
if (Irp->Cancel)
{
//irp canceled even before we got to queue it
if (IoSetCancelRoutine(Irp, NULL))
{ //Cancel routine will NOT be called: cancel it here
IoStatus->Status = STATUS_CANCELLED;
}
else
{ //Cancel routine WILL be called. When we release the lock it will complete the irp
//Return pending since we are not completing the irp here
Irp->IoStatus.Status = IoStatus->Status = STATUS_PENDING;
Irp->IoStatus.Information = 0;
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
}
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
{
//irp was canceled
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return TRUE;
}
else
{ //not cancelled: queue irp
IoMarkIrpPending(Irp);
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = IoStatus->Status = STATUS_PENDING;
Irp->IoStatus.Information = 0;
InsertHeadList(&LockToc->PendingListHead,&Irp->Tail.Overlay.ListEntry);
}
InsertHeadList(&LockToc->PendingListHead,&Irp->Tail.Overlay.ListEntry);
}
else
@ -1034,11 +1063,9 @@ FsRtlPrivateLock (
{
Irp->IoStatus.Status = IoStatus->Status;
Irp->IoStatus.Information = 0;
if (FileLock->CompleteLockIrpRoutine)
{ //complete irp routine
if (!NT_SUCCESS(FileLock->CompleteLockIrpRoutine(Context,Irp)))
{
if (FileLock->CompleteLockIrpRoutine(Context,Irp)!=STATUS_SUCCESS)
{
//CompleteLockIrpRoutine complain: revert changes
FsRtlpUnlockSingle( FileLock,
@ -1047,15 +1074,14 @@ FsRtlPrivateLock (
Length,
Process,
Key,
Context,
AlreadySynchronized,
FALSE//CallUnlockRoutine
NULL, /* context */
FALSE /* don't call unlock copletion routine */
);
}
}
else
{//std irp completion
IofCompleteRequest(Irp, IO_NO_INCREMENT);
{
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
}
@ -1115,7 +1141,7 @@ FsRtlProcessFileLock (
Stack->Parameters.LockControl.Length,
IoGetRequestorProcess(Irp),
Stack->Parameters.LockControl.Key,
Context,
Context,
FALSE);
break;
@ -1123,7 +1149,7 @@ FsRtlProcessFileLock (
Status = FsRtlFastUnlockAll( FileLock,
Stack->FileObject,
IoGetRequestorProcess(Irp),
Context);
Context );
break;
case IRP_MN_UNLOCK_ALL_BY_KEY:
@ -1131,26 +1157,21 @@ FsRtlProcessFileLock (
Stack->FileObject,
IoGetRequestorProcess(Irp),
Stack->Parameters.LockControl.Key,
Context);
Context );
break;
default:
Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST;
IofCompleteRequest(Irp, IO_NO_INCREMENT);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
Irp->IoStatus.Status = Status;
if (FileLock->CompleteLockIrpRoutine )
{
FileLock->CompleteLockIrpRoutine(Context,Irp);
}
else
{
IofCompleteRequest(Irp,IO_NO_INCREMENT);
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
@ -1202,28 +1223,17 @@ FsRtlUninitializeFileLock (
{
//The cancel routine will be called. When we release the lock it will complete the irp.
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
continue;
}
else
{
/*
Cancel routine will NOT be called, even though the irp might have been canceled.
Don't care since we'l complete it faster than the cancel routine would have.
*/
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);//fires cancel routine
Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
if (FileLock->CompleteLockIrpRoutine)
{
FileLock->CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
}
else
{
IofCompleteRequest(Irp, IO_NO_INCREMENT);
}
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
}
}
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
@ -1311,4 +1321,5 @@ FsRtlReleaseFile(
UNIMPLEMENTED;
}
/* EOF */

View file

@ -1,6 +1,6 @@
#ifndef __INCLUDE_INTERNAL_IFS_H
#define __INCLUDE_INTERNAL_IFS_H
/* $Id: ifs.h,v 1.6 2003/08/14 18:30:28 silverblade Exp $ */
/* $Id: ifs.h,v 1.7 2004/12/30 02:30:40 gdalsnes Exp $ */
#include <ddk/ntifs.h>
#include <ntos.h>
@ -38,7 +38,7 @@ FsRtlpFastUnlockAllByKey(
IN PVOID Context OPTIONAL
);
NTSTATUS FASTCALL
BOOLEAN FASTCALL
FsRtlpAddLock(
IN PFILE_LOCK_TOC LockToc,
IN PFILE_OBJECT FileObject,
@ -46,14 +46,16 @@ FsRtlpAddLock(
IN PLARGE_INTEGER Length,
IN PEPROCESS Process,
IN ULONG Key,
IN BOOLEAN ExclusiveLock
IN BOOLEAN ExclusiveLock,
IN PVOID UnlockContext
);
VOID FASTCALL
FsRtlpCompletePendingLocks(
IN PFILE_LOCK FileLock,
IN PFILE_LOCK_TOC LockToc,
IN OUT PKIRQL oldirql
IN OUT PKIRQL oldirql,
IN PVOID Context
);
NTSTATUS FASTCALL
@ -65,7 +67,6 @@ FsRtlpUnlockSingle(
IN PEPROCESS Process,
IN ULONG Key,
IN PVOID Context OPTIONAL,
IN BOOLEAN AlreadySynchronized,
IN BOOLEAN CallUnlockRoutine
);