Author: fireball
Date: Thu Aug 12 21:59:22 2010
New Revision: 48525
URL:
http://svn.reactos.org/svn/reactos?rev=48525&view=rev
Log:
[FASTFAT_NEW]
- Implement asynchronous and delayed close operations.
- Fix a logical bug in FatiClose code, which led to always closing the file object (and
freeing respective FCB/VCB/CCB), and then checking flags and queuing a delayed close.
Instead, it should only try to close if it's not marked as a delayed close.
- Support stuff added (queues, mutex for closing lists, etc).
- Misc cleanup, debug silencing.
Modified:
trunk/reactos/drivers/filesystems/fastfat_new/close.c
trunk/reactos/drivers/filesystems/fastfat_new/dir.c
trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c
trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h
trunk/reactos/drivers/filesystems/fastfat_new/fat.c
trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h
trunk/reactos/drivers/filesystems/fastfat_new/fsctl.c
Modified: trunk/reactos/drivers/filesystems/fastfat_new/close.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/close.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/close.c [iso-8859-1] Thu Aug 12 21:59:22
2010
@@ -10,6 +10,16 @@
#define NDEBUG
#include "fastfat.h"
+
+VOID NTAPI
+FatQueueClose(IN PCLOSE_CONTEXT CloseContext,
+ IN BOOLEAN DelayClose);
+
+PCLOSE_CONTEXT NTAPI
+FatRemoveClose(PVCB Vcb OPTIONAL,
+ PVCB LastVcbHint OPTIONAL);
+
+const ULONG FatMaxDelayedCloseCount = 16;
/* FUNCTIONS ****************************************************************/
@@ -246,8 +256,8 @@
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
- BOOLEAN TopLevel, Wait, VcbDeleted = FALSE;
- NTSTATUS Status;
+ BOOLEAN TopLevel, Wait, VcbDeleted = FALSE, DelayedClose = FALSE;
+ NTSTATUS Status = STATUS_SUCCESS;
PCLOSE_CONTEXT CloseContext = NULL;
TopLevel = FatIsTopLevelIrp(Irp);
@@ -265,16 +275,57 @@
/* It's possible to wait only if we are top level or not a system process */
Wait = TopLevel && (PsGetCurrentProcess() != FatGlobalData.SystemProcess);
- /* Call the common handler */
- Status = FatiCommonClose(Vcb, Fcb, Ccb, TypeOfOpen, Wait, &VcbDeleted);
-
- if (((TypeOfOpen == UserFileOpen ||
- TypeOfOpen == UserDirectoryOpen) &&
+ /* Determine if it's a delayed close, by flags first */
+ if ((TypeOfOpen == UserFileOpen || TypeOfOpen == UserDirectoryOpen) &&
(Fcb->State & FCB_STATE_DELAY_CLOSE) &&
- !FatGlobalData.ShutdownStarted) ||
- Status == STATUS_PENDING)
- {
- DPRINT1("TODO: Queue a pending close request\n");
+ !FatGlobalData.ShutdownStarted)
+ {
+ DelayedClose = TRUE;
+ }
+
+ /* If close is not delayed, try to perform the close operation */
+ if (!DelayedClose)
+ Status = FatiCommonClose(Vcb, Fcb, Ccb, TypeOfOpen, Wait, &VcbDeleted);
+
+ /* We have to delay close if either it's defined by a flag or it was not
possible
+ to perform it synchronously */
+ if (DelayedClose || Status == STATUS_PENDING)
+ {
+ DPRINT1("Queuing a pending close, Vcb %p, Fcb %p, Ccb %p\n", Vcb, Fcb,
Ccb);
+
+ /* Check if a close context should be allocated */
+ if (TypeOfOpen == VirtualVolumeFile)
+ {
+ ASSERT(Vcb->CloseContext != NULL);
+ CloseContext = Vcb->CloseContext;
+ Vcb->CloseContext = NULL;
+ CloseContext->Free = TRUE;
+ }
+ else if (TypeOfOpen == DirectoryFile ||
+ TypeOfOpen == EaFile)
+ {
+ UNIMPLEMENTED;
+ //CloseContext = FatAllocateCloseContext(Vcb);
+ //ASSERT(CloseContext != NULL);
+ CloseContext->Free = TRUE;
+ }
+ else
+ {
+ //TODO: FatDeallocateCcbStrings( Ccb );
+
+ /* Set CloseContext to a buffer inside Ccb */
+ CloseContext = &Ccb->CloseContext;
+ CloseContext->Free = FALSE;
+ SetFlag(Ccb->Flags, CCB_CLOSE_CONTEXT);
+ }
+
+ /* Save all info in the close context */
+ CloseContext->Vcb = Vcb;
+ CloseContext->Fcb = Fcb;
+ CloseContext->TypeOfOpen = TypeOfOpen;
+
+ /* Queue the close */
+ FatQueueClose(CloseContext, (BOOLEAN)(Fcb && FlagOn(Fcb->State,
FCB_STATE_DELAY_CLOSE)));
}
else
{
@@ -351,4 +402,250 @@
return Status;
}
+VOID
+NTAPI
+FatPendingClose(IN PVCB Vcb OPTIONAL)
+{
+ PCLOSE_CONTEXT CloseContext;
+ PVCB CurrentVcb = NULL;
+ PVCB LastVcb = NULL;
+ BOOLEAN FreeContext;
+ ULONG Loops = 0;
+
+ /* Do the top-level IRP trick */
+ if (!Vcb) IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
+
+ while ((CloseContext = FatRemoveClose(Vcb, LastVcb)))
+ {
+ if (!Vcb)
+ {
+ if (!FatGlobalData.ShutdownStarted)
+ {
+ if (CloseContext->Vcb != CurrentVcb)
+ {
+ Loops = 0;
+
+ /* Release previous VCB */
+ if (CurrentVcb)
+ ExReleaseResourceLite(&CurrentVcb->Resource);
+
+ /* Lock the new VCB */
+ CurrentVcb = CloseContext->Vcb;
+ (VOID)ExAcquireResourceExclusiveLite(&CurrentVcb->Resource,
TRUE);
+ }
+ else
+ {
+ /* Try to lock */
+ if (++Loops >= 20)
+ {
+ if (ExGetSharedWaiterCount(&CurrentVcb->Resource) +
+ ExGetExclusiveWaiterCount(&CurrentVcb->Resource))
+ {
+ ExReleaseResourceLite(&CurrentVcb->Resource);
+
(VOID)ExAcquireResourceExclusiveLite(&CurrentVcb->Resource, TRUE);
+ }
+
+ Loops = 0;
+ }
+ }
+
+ /* Check open count */
+ if (CurrentVcb->OpenFileCount <= 1)
+ {
+ ExReleaseResourceLite(&CurrentVcb->Resource);
+ CurrentVcb = NULL;
+ }
+ }
+ else if (CurrentVcb)
+ {
+ ExReleaseResourceLite(&CurrentVcb->Resource);
+ CurrentVcb = NULL;
+ }
+ }
+
+ LastVcb = CurrentVcb;
+
+ /* Remember if we should free the context */
+ FreeContext = CloseContext->Free;
+
+ FatiCommonClose(CloseContext->Vcb,
+ CloseContext->Fcb,
+ (FreeContext ? NULL : CONTAINING_RECORD(CloseContext, CCB,
CloseContext)),
+ CloseContext->TypeOfOpen,
+ TRUE,
+ NULL);
+
+ /* Free context if necessary */
+ if (FreeContext) ExFreePool(CloseContext);
+ }
+
+ /* Release VCB if necessary */
+ if (CurrentVcb) ExReleaseResourceLite(&CurrentVcb->Resource);
+
+ /* Reset top level IRP */
+ if (!Vcb) IoSetTopLevelIrp( NULL );
+}
+
+VOID
+NTAPI
+FatCloseWorker(IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
+{
+ FsRtlEnterFileSystem();
+
+ FatPendingClose((PVCB)Context);
+
+ FsRtlExitFileSystem();
+}
+
+VOID
+NTAPI
+FatQueueClose(IN PCLOSE_CONTEXT CloseContext,
+ IN BOOLEAN DelayClose)
+{
+ BOOLEAN RunWorker = FALSE;
+
+ /* Acquire the close lists mutex */
+ ExAcquireFastMutexUnsafe(&FatCloseQueueMutex);
+
+ /* Add it to the desired list */
+ if (DelayClose)
+ {
+ InsertTailList(&FatGlobalData.DelayedCloseList,
+ &CloseContext->GlobalLinks);
+ InsertTailList(&CloseContext->Vcb->DelayedCloseList,
+ &CloseContext->VcbLinks);
+
+ FatGlobalData.DelayedCloseCount++;
+
+ if (FatGlobalData.DelayedCloseCount > FatMaxDelayedCloseCount &&
+ !FatGlobalData.AsyncCloseActive)
+ {
+ FatGlobalData.AsyncCloseActive = TRUE;
+ RunWorker = TRUE;
+ }
+ }
+ else
+ {
+ InsertTailList(&FatGlobalData.AsyncCloseList,
+ &CloseContext->GlobalLinks);
+ InsertTailList(&CloseContext->Vcb->AsyncCloseList,
+ &CloseContext->VcbLinks);
+
+ FatGlobalData.AsyncCloseCount++;
+
+ if (!FatGlobalData.AsyncCloseActive)
+ {
+ FatGlobalData.AsyncCloseActive = TRUE;
+ RunWorker = TRUE;
+ }
+ }
+
+ /* Release the close lists mutex */
+ ExReleaseFastMutexUnsafe(&FatCloseQueueMutex);
+
+ if (RunWorker)
+ IoQueueWorkItem(FatGlobalData.FatCloseItem, FatCloseWorker, CriticalWorkQueue,
NULL);
+}
+
+PCLOSE_CONTEXT
+NTAPI
+FatRemoveClose(PVCB Vcb OPTIONAL,
+ PVCB LastVcbHint OPTIONAL)
+{
+ PLIST_ENTRY Entry;
+ PCLOSE_CONTEXT CloseContext;
+ BOOLEAN IsWorker = FALSE;
+
+ /* Acquire the close lists mutex */
+ ExAcquireFastMutexUnsafe(&FatCloseQueueMutex);
+
+ if (!Vcb) IsWorker = TRUE;
+
+ if (Vcb == NULL && LastVcbHint != NULL)
+ {
+ // TODO: A very special case of overflowing the queue
+ UNIMPLEMENTED;
+ }
+
+ /* Usual processing from a worker thread */
+ if (!Vcb)
+ {
+TryToCloseAgain:
+
+ /* Is there anything in the async close list */
+ if (!IsListEmpty(&FatGlobalData.AsyncCloseList))
+ {
+ Entry = RemoveHeadList(&FatGlobalData.AsyncCloseList);
+ FatGlobalData.AsyncCloseCount--;
+
+ CloseContext = CONTAINING_RECORD(Entry,
+ CLOSE_CONTEXT,
+ GlobalLinks);
+
+ RemoveEntryList(&CloseContext->VcbLinks);
+ } else if (!IsListEmpty(&FatGlobalData.DelayedCloseList) &&
+ (FatGlobalData.DelayedCloseCount > FatMaxDelayedCloseCount/2 ||
+ FatGlobalData.ShutdownStarted))
+ {
+ /* In case of a shutdown or when delayed queue is filled at half - perform
closing */
+ Entry = RemoveHeadList(&FatGlobalData.DelayedCloseList);
+ FatGlobalData.DelayedCloseCount--;
+
+ CloseContext = CONTAINING_RECORD(Entry,
+ CLOSE_CONTEXT,
+ GlobalLinks);
+ RemoveEntryList(&CloseContext->VcbLinks);
+ }
+ else
+ {
+ /* Nothing to close */
+ CloseContext = NULL;
+ if (IsWorker) FatGlobalData.AsyncCloseActive = FALSE;
+ }
+ }
+ else
+ {
+ if (!IsListEmpty(&Vcb->AsyncCloseList))
+ {
+ /* Is there anything in the async close list */
+ Entry = RemoveHeadList(&Vcb->AsyncCloseList);
+ FatGlobalData.AsyncCloseCount--;
+
+ CloseContext = CONTAINING_RECORD(Entry,
+ CLOSE_CONTEXT,
+ VcbLinks);
+
+ RemoveEntryList(&CloseContext->GlobalLinks);
+ }
+ else if (!IsListEmpty(&Vcb->DelayedCloseList))
+ {
+ /* Process delayed close list */
+ Entry = RemoveHeadList(&Vcb->DelayedCloseList);
+ FatGlobalData.DelayedCloseCount--;
+
+ CloseContext = CONTAINING_RECORD(Entry,
+ CLOSE_CONTEXT,
+ VcbLinks);
+
+ RemoveEntryList(&CloseContext->GlobalLinks);
+ }
+ else if (LastVcbHint)
+ {
+ /* Try again */
+ goto TryToCloseAgain;
+ }
+ else
+ {
+ /* Nothing to close */
+ CloseContext = NULL;
+ }
+ }
+
+ /* Release the close lists mutex */
+ ExReleaseFastMutexUnsafe(&FatCloseQueueMutex);
+
+ return CloseContext;
+}
+
/* EOF */
Modified: trunk/reactos/drivers/filesystems/fastfat_new/dir.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/dir.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/dir.c [iso-8859-1] Thu Aug 12 21:59:22
2010
@@ -111,13 +111,6 @@
#endif
UNIMPLEMENTED;
}
-
- /* Initialize free dirent bitmap */
- RtlInitializeBitMap(&Dcb->Dcb.FreeBitmap, NULL, 0);
-
- /* Fill the dirent bitmap */
- DPRINT1("Filling the free dirent bitmap is missing\n");
- //FatCheckFreeDirentBitmap( IrpContext, Dcb );
}
PFCB
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c [iso-8859-1] Thu Aug 12
21:59:22 2010
@@ -14,6 +14,7 @@
/* GLOBALS ******************************************************************/
FAT_GLOBAL_DATA FatGlobalData;
+FAST_MUTEX FatCloseQueueMutex;
/* FUNCTIONS ****************************************************************/
@@ -109,6 +110,12 @@
/* Initialize synchronization resource for the global data */
ExInitializeResourceLite(&FatGlobalData.Resource);
+ /* Initialize queued close stuff */
+ InitializeListHead(&FatGlobalData.AsyncCloseList);
+ InitializeListHead(&FatGlobalData.DelayedCloseList);
+ FatGlobalData.FatCloseItem = IoAllocateWorkItem(DeviceObject);
+ ExInitializeFastMutex(&FatCloseQueueMutex);
+
/* Initialize global VCB list */
InitializeListHead(&FatGlobalData.VcbListHead);
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h [iso-8859-1] Thu Aug 12
21:59:22 2010
@@ -16,6 +16,7 @@
#define TAG_FCB 'BCFV'
#define TAG_IRP 'PRIV'
#define TAG_VFAT 'TAFV'
+#define TAG_FSD_CLOSE_CONTEXT 'CLCV'
/* Global resource acquire/release */
@@ -182,6 +183,8 @@
FatNoopRelease(IN PVOID Context);
/* --------------------------------------------------------- fastfat.c */
+
+extern FAST_MUTEX FatCloseQueueMutex;
PFAT_IRP_CONTEXT NTAPI
FatBuildIrpContext(PIRP Irp, BOOLEAN CanWait);
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fat.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fat.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fat.c [iso-8859-1] Thu Aug 12 21:59:22
2010
@@ -163,6 +163,10 @@
/* Initialize VCB's resource */
ExInitializeResourceLite(&Vcb->Resource);
+ /* Initialize close queue lists */
+ InitializeListHead(&Vcb->AsyncCloseList);
+ InitializeListHead(&Vcb->DelayedCloseList);
+
/* Initialize CC */
CcInitializeCacheMap(Vcb->StreamFileObject,
(PCC_FILE_SIZES)&Vcb->Header.AllocationSize,
@@ -243,6 +247,9 @@
Vcb->StreamFileObject = NULL;
}
+ /* Free ContextClose if it's not freed up already */
+ if (Vcb->CloseContext) ExFreePool(Vcb->CloseContext);
+
/* Free notifications stuff */
FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h [iso-8859-1] Thu Aug 12
21:59:22 2010
@@ -39,6 +39,16 @@
/* Jan 1, 1980 System Time */
LARGE_INTEGER DefaultFileTime;
+ /* Queued close */
+ ULONG AsyncCloseCount;
+ ULONG DelayedCloseCount;
+ LIST_ENTRY AsyncCloseList;
+ LIST_ENTRY DelayedCloseList;
+ PIO_WORKITEM FatCloseItem;
+
+ /* Various flags */
+ BOOLEAN AsyncCloseActive;
+
/* FullFAT integration */
FF_IOMAN *Ioman;
FF_ERROR FF_Error;
@@ -171,6 +181,8 @@
VCB_CONDITION Condition;
ERESOURCE Resource;
struct _CLOSE_CONTEXT *CloseContext;
+ LIST_ENTRY AsyncCloseList;
+ LIST_ENTRY DelayedCloseList;
/* Direct volume access */
SHARE_ACCESS ShareAccess;
@@ -239,6 +251,18 @@
VCB Vcb; /* Must be the last entry! */
};
} VOLUME_DEVICE_OBJECT, *PVOLUME_DEVICE_OBJECT;
+
+typedef enum _TYPE_OF_OPEN
+{
+ UnopenedFileObject,
+ UserFileOpen,
+ UserDirectoryOpen,
+ UserVolumeOpen,
+ VirtualVolumeFile,
+ DirectoryFile,
+ EaFile
+} TYPE_OF_OPEN;
+
//
// Short name always exists in FAT
//
@@ -342,8 +366,6 @@
PFILE_OBJECT DirectoryFile;
/* Directory data stream (just handy to have it). */
//PFILE_OBJECT StreamFileObject;
- /* Bitmap to search for free dirents. */
- RTL_BITMAP FreeBitmap;
/* Names */
PRTL_SPLAY_LINKS SplayLinksAnsi;
PRTL_SPLAY_LINKS SplayLinksUnicode;
@@ -388,28 +410,6 @@
BOOLEAN Valid8dot3Name;
} FAT_FIND_DIRENT_CONTEXT, *PFAT_FIND_DIRENT_CONTEXT;
-typedef struct _CCB
-{
- CSHORT NodeTypeCode;
- CSHORT NodeByteSize;
-
- LARGE_INTEGER CurrentByteOffset;
- ULONG Entry;
- UNICODE_STRING SearchPattern;
- UCHAR Flags;
-} CCB, *PCCB;
-
-typedef enum _TYPE_OF_OPEN
-{
- UnopenedFileObject,
- UserFileOpen,
- UserDirectoryOpen,
- UserVolumeOpen,
- VirtualVolumeFile,
- DirectoryFile,
- EaFile
-} TYPE_OF_OPEN;
-
typedef struct _CLOSE_CONTEXT
{
LIST_ENTRY GlobalLinks;
@@ -421,6 +421,18 @@
BOOLEAN Free;
} CLOSE_CONTEXT, *PCLOSE_CONTEXT;
+typedef struct _CCB
+{
+ CSHORT NodeTypeCode;
+ CSHORT NodeByteSize;
+
+ LARGE_INTEGER CurrentByteOffset;
+ ULONG Entry;
+ UNICODE_STRING SearchPattern;
+ UCHAR Flags;
+ CLOSE_CONTEXT CloseContext;
+} CCB, *PCCB;
+
typedef enum _FILE_TIME_INDEX
{
FileCreationTime = 0,
@@ -432,9 +444,10 @@
#define CCB_SEARCH_RETURN_SINGLE_ENTRY 0x01
#define CCB_SEARCH_PATTERN_LEGAL_8DOT3 0x02
#define CCB_SEARCH_PATTERN_HAS_WILD_CARD 0x04
-#define CCB_DASD_IO 0x10
-#define CCB_READ_ONLY 0x20
-#define CCB_DELETE_ON_CLOSE 0x40
-#define CCB_COMPLETE_DISMOUNT 0x80
+#define CCB_DASD_IO 0x08
+#define CCB_READ_ONLY 0x10
+#define CCB_DELETE_ON_CLOSE 0x20
+#define CCB_COMPLETE_DISMOUNT 0x40
+#define CCB_CLOSE_CONTEXT 0x80
extern FAT_GLOBAL_DATA FatGlobalData;
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fsctl.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fsctl.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fsctl.c [iso-8859-1] Thu Aug 12 21:59:22
2010
@@ -171,7 +171,7 @@
break;
default:
- DPRINT1("FatUserFsCtrl(), unhandled fs control code 0x%x\n", Code);
+ DPRINT("FatUserFsCtrl(), unhandled fs control code 0x%x\n", Code);
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
}