diff --git a/reactos/include/ntos/file.h b/reactos/include/ntos/file.h index 767dbda7376..9349f1d524c 100644 --- a/reactos/include/ntos/file.h +++ b/reactos/include/ntos/file.h @@ -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 */ diff --git a/reactos/include/ntos/fstypes.h b/reactos/include/ntos/fstypes.h index bc0596237fe..3aa21a66770 100644 --- a/reactos/include/ntos/fstypes.h +++ b/reactos/include/ntos/fstypes.h @@ -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 */ diff --git a/reactos/include/ntos/ntdef.h b/reactos/include/ntos/ntdef.h index c3d0e698259..5bdc58054d5 100644 --- a/reactos/include/ntos/ntdef.h +++ b/reactos/include/ntos/ntdef.h @@ -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) diff --git a/reactos/ntoskrnl/fs/filelock.c b/reactos/ntoskrnl/fs/filelock.c index cb485831250..f4e4fd871be 100644 --- a/reactos/ntoskrnl/fs/filelock.c +++ b/reactos/ntoskrnl/fs/filelock.c @@ -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 */ diff --git a/reactos/ntoskrnl/include/internal/ifs.h b/reactos/ntoskrnl/include/internal/ifs.h index 7a1494a5a4c..aeadb5cd628 100644 --- a/reactos/ntoskrnl/include/internal/ifs.h +++ b/reactos/ntoskrnl/include/internal/ifs.h @@ -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 #include @@ -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 );