mirror of
https://github.com/reactos/reactos.git
synced 2024-11-18 21:13:52 +00:00
[NTOS:IO] Implement IopAcquireFileObjectLock and use it to fix IopLockFileObject
This commit is contained in:
parent
c6142174af
commit
8fbc488050
4 changed files with 167 additions and 25 deletions
|
@ -1238,6 +1238,15 @@ IopCloseFile(
|
|||
IN ULONG SystemHandleCount
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopAcquireFileObjectLock(
|
||||
_In_ PFILE_OBJECT FileObject,
|
||||
_In_ KPROCESSOR_MODE AccessMode,
|
||||
_In_ BOOLEAN Alertable,
|
||||
_Out_ PBOOLEAN LockFailed
|
||||
);
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
IoGetFileObjectFilterContext(
|
||||
|
|
|
@ -8,16 +8,26 @@
|
|||
|
||||
static
|
||||
__inline
|
||||
VOID
|
||||
IopLockFileObject(IN PFILE_OBJECT FileObject)
|
||||
NTSTATUS
|
||||
IopLockFileObject(
|
||||
_In_ PFILE_OBJECT FileObject,
|
||||
_In_ KPROCESSOR_MODE WaitMode)
|
||||
{
|
||||
BOOLEAN LockFailed;
|
||||
|
||||
/* Lock the FO and check for contention */
|
||||
InterlockedIncrement((PLONG)&FileObject->Waiters);
|
||||
while (InterlockedCompareExchange((PLONG)&FileObject->Busy, TRUE, FALSE) != FALSE)
|
||||
if (InterlockedExchange((PLONG)&FileObject->Busy, TRUE) == FALSE)
|
||||
{
|
||||
/* FIXME - pause for a little while? */
|
||||
ObReferenceObject(FileObject);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IopAcquireFileObjectLock(FileObject,
|
||||
WaitMode,
|
||||
BooleanFlagOn(FileObject->Flags, FO_ALERTABLE_IO),
|
||||
&LockFailed);
|
||||
}
|
||||
InterlockedDecrement((PLONG)&FileObject->Waiters);
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -26,8 +36,12 @@ VOID
|
|||
IopUnlockFileObject(IN PFILE_OBJECT FileObject)
|
||||
{
|
||||
/* Unlock the FO and wake any waiters up */
|
||||
InterlockedExchange((PLONG)&FileObject->Busy, FALSE);
|
||||
if (FileObject->Waiters) KeSetEvent(&FileObject->Lock, 0, FALSE);
|
||||
NT_VERIFY(InterlockedExchange((PLONG)&FileObject->Busy, FALSE) == TRUE);
|
||||
if (FileObject->Waiters)
|
||||
{
|
||||
KeSetEvent(&FileObject->Lock, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
ObDereferenceObject(FileObject);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
|
|
|
@ -1729,7 +1729,12 @@ IopGetSetSecurityObject(IN PVOID ObjectBody,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock the file object */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, ExGetPreviousMode());
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2026,7 +2031,7 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
|
|||
/* Check if this is a sync FO and lock it */
|
||||
if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
|
||||
{
|
||||
IopLockFileObject(FileObject);
|
||||
(VOID)IopLockFileObject(FileObject, KernelMode);
|
||||
}
|
||||
|
||||
/* Go the FastIO path if possible, otherwise fall back to IRP */
|
||||
|
@ -2100,7 +2105,7 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
|
|||
if (Process != NULL &&
|
||||
BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
|
||||
{
|
||||
IopLockFileObject(FileObject);
|
||||
(VOID)IopLockFileObject(FileObject, KernelMode);
|
||||
}
|
||||
|
||||
/* Clear and set up Events */
|
||||
|
@ -2259,6 +2264,52 @@ IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopAcquireFileObjectLock(
|
||||
_In_ PFILE_OBJECT FileObject,
|
||||
_In_ KPROCESSOR_MODE WaitMode,
|
||||
_In_ BOOLEAN Alertable,
|
||||
_Out_ PBOOLEAN LockFailed)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
InterlockedIncrement((PLONG)&FileObject->Waiters);
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
do
|
||||
{
|
||||
if (!InterlockedExchange((PLONG)&FileObject->Busy, TRUE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
Status = KeWaitForSingleObject(&FileObject->Lock,
|
||||
Executive,
|
||||
WaitMode,
|
||||
Alertable,
|
||||
NULL);
|
||||
} while (Status == STATUS_SUCCESS);
|
||||
|
||||
InterlockedDecrement((PLONG)&FileObject->Waiters);
|
||||
if (Status == STATUS_SUCCESS)
|
||||
{
|
||||
ObReferenceObject(FileObject);
|
||||
*LockFailed = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!FileObject->Busy && FileObject->Waiters)
|
||||
{
|
||||
KeSetEvent(&FileObject->Lock, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
*LockFailed = TRUE;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject)
|
||||
|
|
|
@ -334,7 +334,13 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
if (EventObject) ObDereferenceObject(EventObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Remember to unlock later */
|
||||
LockedForSynch = TRUE;
|
||||
|
@ -666,7 +672,7 @@ IopQueryDeviceInformation(IN PFILE_OBJECT FileObject,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
(void)IopLockFileObject(FileObject, KernelMode);
|
||||
|
||||
/* Use File Object event */
|
||||
KeClearEvent(&FileObject->Event);
|
||||
|
@ -1221,7 +1227,7 @@ IoSetInformation(IN PFILE_OBJECT FileObject,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
(void)IopLockFileObject(FileObject, KernelMode);
|
||||
|
||||
/* Use File Object event */
|
||||
KeClearEvent(&FileObject->Event);
|
||||
|
@ -1431,7 +1437,12 @@ NtFlushBuffersFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1579,7 +1590,13 @@ NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
if (Event) ObDereferenceObject(Event);
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
LockedForSync = TRUE;
|
||||
}
|
||||
|
||||
|
@ -1779,7 +1796,13 @@ NtLockFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
if (Event) ObDereferenceObject(Event);
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
LockedForSync = TRUE;
|
||||
}
|
||||
|
||||
|
@ -1972,7 +1995,14 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
if (Event) ObDereferenceObject(Event);
|
||||
ObDereferenceObject(FileObject);
|
||||
if (AuxBuffer) ExFreePoolWithTag(AuxBuffer, TAG_SYSB);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Remember to unlock later */
|
||||
LockedForSynch = TRUE;
|
||||
|
@ -2207,7 +2237,12 @@ NtQueryInformationFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if the caller just wants the position */
|
||||
if (FileInformationClass == FilePositionInformation)
|
||||
|
@ -2619,7 +2654,13 @@ NtReadFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock the file object */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
if (EventObject) ObDereferenceObject(EventObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if we don't have a byte offset available */
|
||||
if (!(ByteOffset) ||
|
||||
|
@ -2961,7 +3002,12 @@ NtSetInformationFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if the caller just wants the position */
|
||||
if (FileInformationClass == FilePositionInformation)
|
||||
|
@ -3411,7 +3457,12 @@ NtUnlockFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3616,7 +3667,13 @@ NtWriteFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock the file object */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
if (EventObject) ObDereferenceObject(EventObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if we don't have a byte offset available */
|
||||
if (!(ByteOffset) ||
|
||||
|
@ -3897,7 +3954,12 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4068,7 +4130,13 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle,
|
|||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
Status = IopLockFileObject(FileObject, PreviousMode);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
if (TargetDeviceObject) ObDereferenceObject(TargetDeviceObject);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue