2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/filesystems/fastfat/close.c
5 * PURPOSE: VFAT Filesystem
6 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
7 * Pierre Schweitzer (pierre@reactos.org)
10 /* INCLUDES *****************************************************************/
17 /* FUNCTIONS ****************************************************************/
21 PDEVICE_EXTENSION DeviceExt
,
24 /* Nothing to do for volumes or for the FAT file object */
25 if (BooleanFlagOn(pFcb
->Flags
, FCB_IS_FAT
| FCB_IS_VOLUME
))
30 /* If cache is still initialized, release it
31 * This only affects directories
33 if (pFcb
->OpenHandleCount
== 0 && BooleanFlagOn(pFcb
->Flags
, FCB_CACHE_INITIALIZED
))
35 PFILE_OBJECT tmpFileObject
;
36 tmpFileObject
= pFcb
->FileObject
;
37 if (tmpFileObject
!= NULL
)
39 pFcb
->FileObject
= NULL
;
40 CcUninitializeCacheMap(tmpFileObject
, NULL
, NULL
);
41 ClearFlag(pFcb
->Flags
, FCB_CACHE_INITIALIZED
);
42 ObDereferenceObject(tmpFileObject
);
47 pFcb
->Flags
|= FCB_CLOSED
;
50 /* Release the FCB, we likely cause its deletion */
51 vfatReleaseFCB(DeviceExt
, pFcb
);
57 IN PDEVICE_OBJECT DeviceObject
,
62 PDEVICE_EXTENSION Vcb
;
63 PVFAT_CLOSE_CONTEXT CloseContext
;
64 BOOLEAN ConcurrentDeletion
;
66 /* Start removing work items */
67 ExAcquireFastMutex(&VfatGlobalData
->CloseMutex
);
68 while (!IsListEmpty(&VfatGlobalData
->CloseListHead
))
70 Entry
= RemoveHeadList(&VfatGlobalData
->CloseListHead
);
71 CloseContext
= CONTAINING_RECORD(Entry
, VFAT_CLOSE_CONTEXT
, CloseListEntry
);
74 --VfatGlobalData
->CloseCount
;
75 /* Reset its entry to detect concurrent deletions */
76 InitializeListHead(&CloseContext
->CloseListEntry
);
77 ExReleaseFastMutex(&VfatGlobalData
->CloseMutex
);
79 /* Get the elements */
80 Vcb
= CloseContext
->Vcb
;
81 pFcb
= CloseContext
->Fcb
;
82 ExAcquireResourceExclusiveLite(&Vcb
->DirResource
, TRUE
);
83 /* If it didn't got deleted in between */
84 if (BooleanFlagOn(pFcb
->Flags
, FCB_DELAYED_CLOSE
))
87 DPRINT("Late closing: %wZ\n", &pFcb
->PathNameU
);
88 ClearFlag(pFcb
->Flags
, FCB_DELAYED_CLOSE
);
89 pFcb
->CloseContext
= NULL
;
90 VfatCommonCloseFile(Vcb
, pFcb
);
91 ConcurrentDeletion
= FALSE
;
95 /* Otherwise, mark not to delete it */
96 ConcurrentDeletion
= TRUE
;
98 ExReleaseResourceLite(&Vcb
->DirResource
);
100 /* If we were the fastest, delete the context */
101 if (!ConcurrentDeletion
)
103 ExFreeToPagedLookasideList(&VfatGlobalData
->CloseContextLookasideList
, CloseContext
);
106 /* Lock again the list */
107 ExAcquireFastMutex(&VfatGlobalData
->CloseMutex
);
110 /* We're done, bye! */
111 VfatGlobalData
->CloseWorkerRunning
= FALSE
;
112 ExReleaseFastMutex(&VfatGlobalData
->CloseMutex
);
117 PDEVICE_EXTENSION DeviceExt
,
118 PFILE_OBJECT FileObject
)
120 PVFAT_CLOSE_CONTEXT CloseContext
;
122 /* Allocate a work item */
123 CloseContext
= ExAllocateFromPagedLookasideList(&VfatGlobalData
->CloseContextLookasideList
);
124 if (CloseContext
== NULL
)
126 return STATUS_INSUFFICIENT_RESOURCES
;
129 /* Set relevant fields */
130 CloseContext
->Vcb
= DeviceExt
;
131 CloseContext
->Fcb
= FileObject
->FsContext
;
132 CloseContext
->Fcb
->CloseContext
= CloseContext
;
134 /* Acquire the lock to insert in list */
135 ExAcquireFastMutex(&VfatGlobalData
->CloseMutex
);
137 /* One more element */
138 InsertTailList(&VfatGlobalData
->CloseListHead
, &CloseContext
->CloseListEntry
);
139 ++VfatGlobalData
->CloseCount
;
141 /* If we have more than 16 items in list, and no worker thread
144 if (VfatGlobalData
->CloseCount
> 16 && !VfatGlobalData
->CloseWorkerRunning
)
146 VfatGlobalData
->CloseWorkerRunning
= TRUE
;
147 IoQueueWorkItem(VfatGlobalData
->CloseWorkItem
, VfatCloseWorker
, CriticalWorkQueue
, NULL
);
151 ExReleaseFastMutex(&VfatGlobalData
->CloseMutex
);
153 return STATUS_SUCCESS
;
157 * FUNCTION: Closes a file
161 PDEVICE_EXTENSION DeviceExt
,
162 PFILE_OBJECT FileObject
)
166 NTSTATUS Status
= STATUS_SUCCESS
;
168 DPRINT("VfatCloseFile(DeviceExt %p, FileObject %p)\n",
169 DeviceExt
, FileObject
);
171 /* FIXME : update entry in directory? */
172 pCcb
= (PVFATCCB
) (FileObject
->FsContext2
);
173 pFcb
= (PVFATFCB
) (FileObject
->FsContext
);
177 return STATUS_SUCCESS
;
182 vfatDestroyCCB(pCcb
);
185 /* If we have to close immediately, or if delaying failed, close */
186 if (VfatGlobalData
->ShutdownStarted
|| !BooleanFlagOn(pFcb
->Flags
, FCB_DELAYED_CLOSE
) ||
187 !NT_SUCCESS(VfatPostCloseFile(DeviceExt
, FileObject
)))
189 VfatCommonCloseFile(DeviceExt
, pFcb
);
192 FileObject
->FsContext2
= NULL
;
193 FileObject
->FsContext
= NULL
;
194 FileObject
->SectionObjectPointer
= NULL
;
196 #ifdef ENABLE_SWAPOUT
197 if (BooleanFlagOn(pFcb
->Flags
, FCB_IS_VOLUME
) && DeviceExt
->OpenHandleCount
== 0)
199 VfatCheckForDismount(DeviceExt
, FALSE
);
207 * FUNCTION: Closes a file
211 PVFAT_IRP_CONTEXT IrpContext
)
215 DPRINT("VfatClose(DeviceObject %p, Irp %p)\n", IrpContext
->DeviceObject
, IrpContext
->Irp
);
217 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
219 DPRINT("Closing file system\n");
220 IrpContext
->Irp
->IoStatus
.Information
= 0;
221 return STATUS_SUCCESS
;
223 if (!ExAcquireResourceExclusiveLite(&IrpContext
->DeviceExt
->DirResource
, BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
)))
225 return VfatMarkIrpContextForQueue(IrpContext
);
228 Status
= VfatCloseFile(IrpContext
->DeviceExt
, IrpContext
->FileObject
);
229 ExReleaseResourceLite(&IrpContext
->DeviceExt
->DirResource
);
231 IrpContext
->Irp
->IoStatus
.Information
= 0;