Import code from Pierre Schweitzer's fsrtl branch.
- Large MCB and MCB
- Change notification

svn path=/trunk/; revision=55914
This commit is contained in:
Art Yerkes 2012-02-29 09:18:01 +00:00
parent c131df4a4c
commit 9d75a5ebae
6 changed files with 1230 additions and 261 deletions

View file

@ -119,6 +119,7 @@ list(APPEND SOURCE
fsrtl/fsfilter.c fsrtl/fsfilter.c
fsrtl/fsrtlpc.c fsrtl/fsrtlpc.c
fsrtl/largemcb.c fsrtl/largemcb.c
fsrtl/mcb.c
fsrtl/name.c fsrtl/name.c
fsrtl/notify.c fsrtl/notify.c
fsrtl/oplock.c fsrtl/oplock.c

View file

@ -169,6 +169,8 @@ FsRtlInitSystem(VOID)
IFS_POOL_TAG, IFS_POOL_TAG,
0); 0);
FsRtlInitializeLargeMcbs();
/* Allocate the Resource Buffer */ /* Allocate the Resource Buffer */
FsRtlPagingIoResources = FsRtlAllocatePoolWithTag(NonPagedPool, FsRtlPagingIoResources = FsRtlAllocatePoolWithTag(NonPagedPool,
FSRTL_MAX_RESOURCES * FSRTL_MAX_RESOURCES *

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,190 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/fsrtl/mcb.c
* PURPOSE: Mapped Control Block (MCB) support for File System Drivers
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
BOOLEAN
NTAPI
FsRtlAddMcbEntry(IN PMCB Mcb,
IN VBN Vbn,
IN LBN Lbn,
IN ULONG SectorCount)
{
/* Call the newer function */
return FsRtlAddLargeMcbEntry(&Mcb->
DummyFieldThatSizesThisStructureCorrectly,
(LONGLONG)Vbn,
(LONGLONG)Lbn,
(LONGLONG)SectorCount);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
FsRtlGetNextMcbEntry(IN PMCB Mcb,
IN ULONG RunIndex,
OUT PVBN Vbn,
OUT PLBN Lbn,
OUT PULONG SectorCount)
{
BOOLEAN Return = FALSE;
LONGLONG llVbn;
LONGLONG llLbn;
LONGLONG llSectorCount;
/* Call the Large version */
Return = FsRtlGetNextLargeMcbEntry(
&Mcb->DummyFieldThatSizesThisStructureCorrectly,
RunIndex,
&llVbn,
&llLbn,
&llSectorCount);
/* Return the lower 32 bits */
*Vbn = (ULONG)llVbn;
*Lbn = (ULONG)llLbn;
*SectorCount = (ULONG)llSectorCount;
/* And return the original value */
return Return;
}
/*
* @implemented
*/
VOID
NTAPI
FsRtlInitializeMcb(IN PMCB Mcb,
IN POOL_TYPE PoolType)
{
/* Call the newer function */
FsRtlInitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
PoolType);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
FsRtlLookupLastMcbEntry(IN PMCB Mcb,
OUT PVBN Vbn,
OUT PLBN Lbn)
{
BOOLEAN Return = FALSE;
LONGLONG llVbn = 0;
LONGLONG llLbn = 0;
/* Call the Large version */
Return = FsRtlLookupLastLargeMcbEntry(
&Mcb->DummyFieldThatSizesThisStructureCorrectly,
&llVbn,
&llLbn);
/* Return the lower 32-bits */
*Vbn = (ULONG)llVbn;
*Lbn = (ULONG)llLbn;
/* And return the original value */
return Return;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
FsRtlLookupMcbEntry(IN PMCB Mcb,
IN VBN Vbn,
OUT PLBN Lbn,
OUT PULONG SectorCount OPTIONAL,
OUT PULONG Index)
{
BOOLEAN Return = FALSE;
LONGLONG llLbn;
LONGLONG llSectorCount;
/* Call the Large version */
Return = FsRtlLookupLargeMcbEntry(&Mcb->
DummyFieldThatSizesThisStructureCorrectly,
(LONGLONG)Vbn,
&llLbn,
&llSectorCount,
NULL,
NULL,
Index);
/* Return the lower 32-bits */
*Lbn = (ULONG)llLbn;
if (SectorCount) *SectorCount = (ULONG)llSectorCount;
/* And return the original value */
return Return;
}
/*
* @implemented
*/
ULONG
NTAPI
FsRtlNumberOfRunsInMcb(IN PMCB Mcb)
{
/* Call the newer function */
return FsRtlNumberOfRunsInLargeMcb(
&Mcb->DummyFieldThatSizesThisStructureCorrectly);
}
/*
* @implemented
*/
VOID
NTAPI
FsRtlRemoveMcbEntry(IN PMCB Mcb,
IN VBN Vbn,
IN ULONG SectorCount)
{
/* Call the large function */
FsRtlRemoveLargeMcbEntry(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
(LONGLONG)Vbn,
(LONGLONG)SectorCount);
}
/*
* @implemented
*/
VOID
NTAPI
FsRtlTruncateMcb(IN PMCB Mcb,
IN VBN Vbn)
{
/* Call the newer function */
FsRtlTruncateLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
(LONGLONG)Vbn);
}
/*
* @implemented
*/
VOID
NTAPI
FsRtlUninitializeMcb(IN PMCB Mcb)
{
/* Call the newer function */
FsRtlUninitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly);
}

View file

@ -12,6 +12,68 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
PNOTIFY_CHANGE
FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList,
IN PVOID FsContext)
{
PLIST_ENTRY NextEntry;
PNOTIFY_CHANGE NotifyChange;
if (!IsListEmpty(NotifyList))
{
/* Browse the notifications list to find the matching entry */
for (NextEntry = NotifyList->Flink;
NextEntry != NotifyList;
NextEntry = NextEntry->Flink)
{
NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
/* If the current record matches with the given context, it's the good one */
if (NotifyChange->FsContext == FsContext)
{
return NotifyChange;
}
}
}
return NULL;
}
VOID
FORCEINLINE
FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
{
ULONG_PTR CurrentThread = (ULONG_PTR)KeGetCurrentThread();
/* Only acquire fast mutex if it's not already acquired by the current thread */
if (RealNotifySync->OwningThread != CurrentThread)
{
ExAcquireFastMutexUnsafe(&(RealNotifySync->FastMutex));
RealNotifySync->OwningThread = CurrentThread;
}
/* Whatever the case, keep trace of the attempt to acquire fast mutex */
RealNotifySync->OwnerCount++;
}
VOID
FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
IN NTSTATUS Status)
{
}
VOID
FORCEINLINE
FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
{
RealNotifySync->OwnerCount--;
/* Release the fast mutex only if no other instance needs it */
if (!RealNotifySync->OwnerCount)
{
ExReleaseFastMutexUnsafe(&(RealNotifySync->FastMutex));
RealNotifySync->OwningThread = (ULONG_PTR)0;
}
}
/* PUBLIC FUNCTIONS **********************************************************/ /* PUBLIC FUNCTIONS **********************************************************/
/*++ /*++
@ -44,8 +106,7 @@
* *
* @return None * @return None
* *
* @remarks This function only redirects to FsRtlNotifyFullChangeDirectory. * @remarks This function only redirects to FsRtlNotifyFilterChangeDirectory.
* So, it's better to call the entire function.
* *
*--*/ *--*/
VOID VOID
@ -58,32 +119,33 @@ FsRtlNotifyChangeDirectory(IN PNOTIFY_SYNC NotifySync,
IN ULONG CompletionFilter, IN ULONG CompletionFilter,
IN PIRP NotifyIrp) IN PIRP NotifyIrp)
{ {
FsRtlNotifyFullChangeDirectory(NotifySync, FsRtlNotifyFilterChangeDirectory(NotifySync,
NotifyList, NotifyList,
FsContext, FsContext,
FullDirectoryName, FullDirectoryName,
WatchTree, WatchTree,
TRUE, TRUE,
CompletionFilter, CompletionFilter,
NotifyIrp, NotifyIrp,
NULL, NULL,
NULL); NULL,
NULL);
} }
/*++ /*++
* @name FsRtlNotifyCleanup * @name FsRtlNotifyCleanup
* @unimplemented * @implemented
* *
* Called by FSD when all handles to FileObject (identified by FsContext) are closed * Called by FSD when all handles to FileObject (identified by FsContext) are closed
* *
* @param NotifySync * @param NotifySync
* FILLME * Synchronization object pointer
* *
* @param NotifyList * @param NotifyList
* FILLME * Notify list pointer (to head)
* *
* @param FsContext * @param FsContext
* FILLME * Used to identify the notify structure
* *
* @return None * @return None
* *
@ -96,7 +158,67 @@ FsRtlNotifyCleanup(IN PNOTIFY_SYNC NotifySync,
IN PLIST_ENTRY NotifyList, IN PLIST_ENTRY NotifyList,
IN PVOID FsContext) IN PVOID FsContext)
{ {
KeBugCheck(FILE_SYSTEM); PNOTIFY_CHANGE NotifyChange;
PREAL_NOTIFY_SYNC RealNotifySync;
PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL;
/* Get real structure hidden behind the opaque pointer */
RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
/* Acquire the fast mutex */
FsRtlNotifyAcquireFastMutex(RealNotifySync);
_SEH2_TRY
{
/* Find if there's a matching notification with the FsContext */
NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
if (NotifyChange)
{
/* Mark it as to know that cleanup is in process */
NotifyChange->Flags |= CLEANUP_IN_PROCESS;
/* If there are pending IRPs, complete them using the STATUS_NOTIFY_CLEANUP status */
if (!IsListEmpty(NotifyChange->NotifyIrps))
{
FsRtlNotifyCompleteIrpList(NotifyChange, STATUS_NOTIFY_CLEANUP);
}
/* Remove from the list */
RemoveEntryList(NotifyChange->NotifyList);
/* Downcrease reference number and if 0 is reached, it's time to do complete cleanup */
if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount)))
{
/* In case there was an allocated buffer, free it */
if (NotifyChange->AllocatedBuffer)
{
PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
ExFreePool(NotifyChange->AllocatedBuffer);
}
/* In case there the string was set, get the captured subject security context */
if (NotifyChange->FullDirectoryName)
{
SubjectContext = NotifyChange->SubjectContext;
}
/* Finally, free the notification, as it's not needed anymore */
ExFreePool(NotifyChange);
}
}
}
_SEH2_FINALLY
{
/* Release fast mutex */
FsRtlNotifyReleaseFastMutex(RealNotifySync);
/* If the subject security context was captured, release and free it */
if (SubjectContext)
{
SeReleaseSubjectContext(SubjectContext);
ExFreePool(SubjectContext);
}
}
_SEH2_END;
} }
/*++ /*++
@ -219,43 +341,46 @@ FsRtlNotifyFilterReportChange(IN PNOTIFY_SYNC NotifySync,
/*++ /*++
* @name FsRtlNotifyFullChangeDirectory * @name FsRtlNotifyFullChangeDirectory
* @unimplemented * @implemented
* *
* FILLME * Lets FSD know if changes occures in the specified directory.
* *
* @param NotifySync * @param NotifySync
* FILLME * Synchronization object pointer
* *
* @param NotifyList * @param NotifyList
* FILLME * Notify list pointer (to head)
* *
* @param FsContext * @param FsContext
* FILLME * Used to identify the notify structure
* *
* @param FullDirectoryName * @param FullDirectoryName
* FILLME * String (A or W) containing the full directory name
* *
* @param WatchTree * @param WatchTree
* FILLME * True to notify changes in subdirectories too
* *
* @param IgnoreBuffer * @param IgnoreBuffer
* FILLME * True to reenumerate directory. It's ignored it NotifyIrp is null
* *
* @param CompletionFilter * @param CompletionFilter
* FILLME * Used to define types of changes to notify
* *
* @param Irp * @param NotifyIrp
* FILLME * IRP pointer to complete notify operation. It can be null
* *
* @param TraverseCallback * @param TraverseCallback
* FILLME * Pointer to a callback function. It's called each time a change is
* done in a subdirectory of the main directory. It's ignored it NotifyIrp
* is null
* *
* @param SubjectContext * @param SubjectContext
* FILLME * Pointer to pass to SubjectContext member of TraverseCallback.
* It's freed after use. It's ignored it NotifyIrp is null
* *
* @return None * @return None
* *
* @remarks None * @remarks This function only redirects to FsRtlNotifyFilterChangeDirectory.
* *
*--*/ *--*/
VOID VOID
@ -267,49 +392,60 @@ FsRtlNotifyFullChangeDirectory(IN PNOTIFY_SYNC NotifySync,
IN BOOLEAN WatchTree, IN BOOLEAN WatchTree,
IN BOOLEAN IgnoreBuffer, IN BOOLEAN IgnoreBuffer,
IN ULONG CompletionFilter, IN ULONG CompletionFilter,
IN PIRP Irp, IN PIRP NotifyIrp,
IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL,
IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL) IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
{ {
KeBugCheck(FILE_SYSTEM); FsRtlNotifyFilterChangeDirectory(NotifySync,
NotifyList,
FsContext,
FullDirectoryName,
WatchTree,
IgnoreBuffer,
CompletionFilter,
NotifyIrp,
TraverseCallback,
SubjectContext,
NULL);
} }
/*++ /*++
* @name FsRtlNotifyFullReportChange * @name FsRtlNotifyFullReportChange
* @unimplemented * @implemented
* *
* FILLME * Complets the pending notify IRPs.
* *
* @param NotifySync * @param NotifySync
* FILLME * Synchronization object pointer
* *
* @param NotifyList * @param NotifyList
* FILLME * Notify list pointer (to head)
* *
* @param FullTargetName * @param FullTargetName
* FILLME * String (A or W) containing the full directory name that changed
* *
* @param TargetNameOffset * @param TargetNameOffset
* FILLME * Offset, in FullTargetName, of the final component that is in the changed directory
* *
* @param StreamName * @param StreamName
* FILLME * String (A or W) containing a stream name
* *
* @param NormalizedParentName * @param NormalizedParentName
* FILLME * String (A or W) containing the full directory name that changed with long names
* *
* @param FilterMatch * @param FilterMatch
* FILLME * Flags that will be compared to the completion filter
* *
* @param Action * @param Action
* FILLME * Action code to store in user's buffer
* *
* @param TargetContext * @param TargetContext
* FILLME * Pointer to a callback function. It's called each time a change is
* done in a subdirectory of the main directory.
* *
* @return None * @return None
* *
* @remarks None * @remarks This function only redirects to FsRtlNotifyFilterReportChange.
* *
*--*/ *--*/
VOID VOID
@ -324,54 +460,73 @@ FsRtlNotifyFullReportChange(IN PNOTIFY_SYNC NotifySync,
IN ULONG Action, IN ULONG Action,
IN PVOID TargetContext) IN PVOID TargetContext)
{ {
KeBugCheck(FILE_SYSTEM); FsRtlNotifyFilterReportChange(NotifySync,
NotifyList,
FullTargetName,
TargetNameOffset,
StreamName,
NormalizedParentName,
FilterMatch,
Action,
TargetContext,
NULL);
} }
/*++ /*++
* @name FsRtlNotifyInitializeSync * @name FsRtlNotifyInitializeSync
* @unimplemented * @implemented
* *
* FILLME * Allocates the internal structure associated with notifications.
* *
* @param NotifySync * @param NotifySync
* FILLME * Opaque pointer. It will receive the address of the allocated internal structure.
* *
* @return None * @return None
* *
* @remarks None * @remarks This function raise an exception in case of a failure.
* *
*--*/ *--*/
VOID VOID
NTAPI NTAPI
FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync) FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync)
{ {
KeBugCheck(FILE_SYSTEM); PREAL_NOTIFY_SYNC RealNotifySync;
*NotifySync = NULL;
RealNotifySync = ExAllocatePoolWithTag(NonPagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
sizeof(REAL_NOTIFY_SYNC), TAG('F', 'S', 'N', 'S'));
ExInitializeFastMutex(&(RealNotifySync->FastMutex));
RealNotifySync->OwningThread = 0;
RealNotifySync->OwnerCount = 0;
*NotifySync = RealNotifySync;
} }
/*++ /*++
* @name FsRtlNotifyReportChange * @name FsRtlNotifyReportChange
* @unimplemented * @implemented
* *
* FILLME * Complets the pending notify IRPs.
* *
* @param NotifySync * @param NotifySync
* FILLME * Synchronization object pointer
* *
* @param NotifyList * @param NotifyList
* FILLME * Notify list pointer (to head)
* *
* @param FullTargetName * @param FullTargetName
* FILLME * String (A or W) containing the full directory name that changed
* *
* @param FileNamePartLength * @param FileNamePartLength
* FILLME * Length of the final component that is in the changed directory
* *
* @param FilterMatch * @param FilterMatch
* FILLME * Flags that will be compared to the completion filter
* *
* @return None * @return None
* *
* @remarks None * @remarks This function only redirects to FsRtlNotifyFilterReportChange.
* *
*--*/ *--*/
VOID VOID
@ -382,11 +537,20 @@ FsRtlNotifyReportChange(IN PNOTIFY_SYNC NotifySync,
IN PUSHORT FileNamePartLength, IN PUSHORT FileNamePartLength,
IN ULONG FilterMatch) IN ULONG FilterMatch)
{ {
KeBugCheck(FILE_SYSTEM); FsRtlNotifyFilterReportChange(NotifySync,
NotifyList,
FullTargetName,
FullTargetName->Length - *FileNamePartLength,
NULL,
NULL,
FilterMatch,
0,
NULL,
NULL);
} }
/*++ /*++
* @name FsRtlCurrentBatchOplock * @name FsRtlNotifyUninitializeSync
* @implemented * @implemented
* *
* Uninitialize a NOTIFY_SYNC object * Uninitialize a NOTIFY_SYNC object
@ -404,6 +568,10 @@ VOID
NTAPI NTAPI
FsRtlNotifyUninitializeSync(IN PNOTIFY_SYNC *NotifySync) FsRtlNotifyUninitializeSync(IN PNOTIFY_SYNC *NotifySync)
{ {
KeBugCheck(FILE_SYSTEM); if (*NotifySync)
{
ExFreePoolWithTag(*NotifySync, TAG('F', 'S', 'N', 'S'));
*NotifySync = NULL;
}
} }

View file

@ -6,6 +6,10 @@
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/ */
#ifndef TAG
#define TAG(w,x,y,z) (((w)<<24)|((x)<<16)|((y)<<8)|(z))
#endif
// //
// Define this if you want debugging support // Define this if you want debugging support
// //
@ -36,7 +40,7 @@
if (x & FsRtlpTraceLevel) DbgPrint(__VA_ARGS__) if (x & FsRtlpTraceLevel) DbgPrint(__VA_ARGS__)
#endif #endif
#else #else
#define FSTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #define FSTRACE(x, ...) DPRINT(__VA_ARGS__)
#endif #endif
// //
@ -44,12 +48,68 @@
// //
#define FSRTL_MAX_RESOURCES 16 #define FSRTL_MAX_RESOURCES 16
//
// Number of maximum pair count per MCB
//
#define MAXIMUM_PAIR_COUNT 15
//
// Notifications flags
//
#define CLEANUP_IN_PROCESS 4
//
// Internal structure for NOTIFY_SYNC
//
typedef struct _REAL_NOTIFY_SYNC
{
FAST_MUTEX FastMutex;
ULONG_PTR OwningThread;
ULONG OwnerCount;
} REAL_NOTIFY_SYNC, * PREAL_NOTIFY_SYNC;
//
// Internal structure for notifications
//
typedef struct _NOTIFY_CHANGE
{
PREAL_NOTIFY_SYNC NotifySync;
PVOID FsContext;
PVOID StreamID;
PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback;
PSECURITY_SUBJECT_CONTEXT SubjectContext;
PSTRING FullDirectoryName;
PLIST_ENTRY NotifyList;
PLIST_ENTRY NotifyIrps;
PFILTER_REPORT_CHANGE FilterCallback;
USHORT Flags;
UCHAR CharacterSize;
ULONG CompletionFilter;
PVOID AllocatedBuffer;
PVOID Buffer;
ULONG BufferLength;
ULONG ThisBufferLength;
ULONG DataLength;
ULONG LastEntry;
ULONG ReferenceCount;
PEPROCESS OwningProcess;
} NOTIFY_CHANGE, *PNOTIFY_CHANGE;
//
// Internal structure for MCB Mapping pointer
//
typedef struct _INT_MAPPING
{
VBN Vbn;
LBN Lbn;
} INT_MAPPING, *PINT_MAPPING;
// //
// Initialization Routines // Initialization Routines
// //
BOOLEAN VOID
NTAPI NTAPI
FsRtlInitSystem( FsRtlInitializeLargeMcbs(
VOID VOID
); );
@ -62,6 +122,12 @@ FsRtlPTeardownPerFileObjectContexts(
IN PFILE_OBJECT FileObject IN PFILE_OBJECT FileObject
); );
BOOLEAN
NTAPI
FsRtlInitSystem(
VOID
);
// //
// Global data inside the File System Runtime Library // Global data inside the File System Runtime Library
// //