[BTRFS] Fix booting with runtime checks
[reactos.git] / drivers / filesystems / fastfat / cleanup.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/vfat/cleanup.c
5 * PURPOSE: VFAT Filesystem
6 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
7 * Pierre Schweitzer (pierre@reactos.org)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "vfat.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS ****************************************************************/
18
19 /*
20 * FUNCTION: Cleans up after a file has been closed.
21 */
22 static
23 NTSTATUS
24 VfatCleanupFile(
25 PVFAT_IRP_CONTEXT IrpContext)
26 {
27 PVFATFCB pFcb;
28 PVFATCCB pCcb;
29 BOOLEAN IsVolume;
30 PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt;
31 PFILE_OBJECT FileObject = IrpContext->FileObject;
32
33 DPRINT("VfatCleanupFile(DeviceExt %p, FileObject %p)\n",
34 IrpContext->DeviceExt, FileObject);
35
36 /* FIXME: handle file/directory deletion here */
37 pFcb = (PVFATFCB)FileObject->FsContext;
38 if (!pFcb)
39 return STATUS_SUCCESS;
40
41 IsVolume = BooleanFlagOn(pFcb->Flags, FCB_IS_VOLUME);
42 if (IsVolume)
43 {
44 pFcb->OpenHandleCount--;
45 DeviceExt->OpenHandleCount--;
46
47 if (pFcb->OpenHandleCount != 0)
48 {
49 IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess);
50 }
51 }
52 else
53 {
54 ExAcquireResourceExclusiveLite(&pFcb->MainResource, TRUE);
55 ExAcquireResourceExclusiveLite(&pFcb->PagingIoResource, TRUE);
56
57 pCcb = FileObject->FsContext2;
58 if (BooleanFlagOn(pCcb->Flags, CCB_DELETE_ON_CLOSE))
59 {
60 pFcb->Flags |= FCB_DELETE_PENDING;
61 }
62
63 /* Notify about the cleanup */
64 FsRtlNotifyCleanup(IrpContext->DeviceExt->NotifySync,
65 &(IrpContext->DeviceExt->NotifyList),
66 FileObject->FsContext2);
67
68 pFcb->OpenHandleCount--;
69 DeviceExt->OpenHandleCount--;
70
71 if (!vfatFCBIsDirectory(pFcb) &&
72 FsRtlAreThereCurrentFileLocks(&pFcb->FileLock))
73 {
74 /* remove all locks this process have on this file */
75 FsRtlFastUnlockAll(&pFcb->FileLock,
76 FileObject,
77 IoGetRequestorProcess(IrpContext->Irp),
78 NULL);
79 }
80
81 if (BooleanFlagOn(pFcb->Flags, FCB_IS_DIRTY))
82 {
83 VfatUpdateEntry (DeviceExt, pFcb);
84 }
85
86 if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) &&
87 pFcb->OpenHandleCount == 0)
88 {
89 if (vfatFCBIsDirectory(pFcb) &&
90 !VfatIsDirectoryEmpty(DeviceExt, pFcb))
91 {
92 pFcb->Flags &= ~FCB_DELETE_PENDING;
93 }
94 else
95 {
96 PFILE_OBJECT tmpFileObject;
97 tmpFileObject = pFcb->FileObject;
98 if (tmpFileObject != NULL)
99 {
100 pFcb->FileObject = NULL;
101 CcUninitializeCacheMap(tmpFileObject, NULL, NULL);
102 ClearFlag(pFcb->Flags, FCB_CACHE_INITIALIZED);
103 ObDereferenceObject(tmpFileObject);
104 }
105
106 pFcb->RFCB.ValidDataLength.QuadPart = 0;
107 pFcb->RFCB.FileSize.QuadPart = 0;
108 pFcb->RFCB.AllocationSize.QuadPart = 0;
109 }
110 }
111
112 /* Uninitialize the cache (should be done even if caching was never initialized) */
113 CcUninitializeCacheMap(FileObject, &pFcb->RFCB.FileSize, NULL);
114
115 if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) &&
116 pFcb->OpenHandleCount == 0)
117 {
118 VfatDelEntry(DeviceExt, pFcb, NULL);
119
120 vfatReportChange(DeviceExt,
121 pFcb,
122 (vfatFCBIsDirectory(pFcb) ?
123 FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
124 FILE_ACTION_REMOVED);
125 }
126
127 if (pFcb->OpenHandleCount != 0)
128 {
129 IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess);
130 }
131 /* FIXME: causes FS corruption and breaks selfhosting/testbots and so on */
132 #if 0
133 /* If that's the last open handle we just closed, try to see whether
134 * we can delay close operation
135 */
136 else if (!BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) && !BooleanFlagOn(pFcb->Flags, FCB_IS_PAGE_FILE) &&
137 !BooleanFlagOn(pFcb->Flags, FCB_IS_FAT) && !BooleanFlagOn(pFcb->Flags, FCB_IS_VOLUME))
138 {
139 /* This is only allowed if that's a directory with no open files
140 * OR if it's a file with no section opened
141 */
142 if ((vfatFCBIsDirectory(pFcb) && IsListEmpty(&pFcb->ParentListHead)) ||
143 (!vfatFCBIsDirectory(pFcb) && FileObject->SectionObjectPointer->DataSectionObject == NULL &&
144 FileObject->SectionObjectPointer->ImageSectionObject == NULL))
145 {
146 DPRINT("Delaying close of: %wZ\n", &pFcb->PathNameU);
147 SetFlag(pFcb->Flags, FCB_DELAYED_CLOSE);
148 }
149 }
150 #endif
151
152 FileObject->Flags |= FO_CLEANUP_COMPLETE;
153 #ifdef KDBG
154 pFcb->Flags |= FCB_CLEANED_UP;
155 #endif
156
157 ExReleaseResourceLite(&pFcb->PagingIoResource);
158 ExReleaseResourceLite(&pFcb->MainResource);
159 }
160
161 #ifdef ENABLE_SWAPOUT
162 if (IsVolume && BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING))
163 {
164 VfatCheckForDismount(DeviceExt, FALSE);
165 }
166 #endif
167
168 return STATUS_SUCCESS;
169 }
170
171 /*
172 * FUNCTION: Cleans up after a file has been closed.
173 */
174 NTSTATUS
175 VfatCleanup(
176 PVFAT_IRP_CONTEXT IrpContext)
177 {
178 NTSTATUS Status;
179
180 DPRINT("VfatCleanup(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp);
181
182 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
183 {
184 IrpContext->Irp->IoStatus.Information = 0;
185 return STATUS_SUCCESS;
186 }
187
188 ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
189 Status = VfatCleanupFile(IrpContext);
190 ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
191
192 IrpContext->Irp->IoStatus.Information = 0;
193 return Status;
194 }
195
196 /* EOF */