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)
10 /* INCLUDES *****************************************************************/
17 /* FUNCTIONS ****************************************************************/
20 * FUNCTION: Cleans up after a file has been closed.
21 * Returns whether the device was deleted
26 PVFAT_IRP_CONTEXT IrpContext
)
31 PDEVICE_EXTENSION DeviceExt
= IrpContext
->DeviceExt
;
32 PFILE_OBJECT FileObject
= IrpContext
->FileObject
;
33 BOOLEAN Deleted
= FALSE
;
35 DPRINT("VfatCleanupFile(DeviceExt %p, FileObject %p)\n",
36 IrpContext
->DeviceExt
, FileObject
);
38 /* FIXME: handle file/directory deletion here */
39 pFcb
= (PVFATFCB
)FileObject
->FsContext
;
43 IsVolume
= BooleanFlagOn(pFcb
->Flags
, FCB_IS_VOLUME
);
46 pFcb
->OpenHandleCount
--;
47 DeviceExt
->OpenHandleCount
--;
49 if (pFcb
->OpenHandleCount
!= 0)
51 IoRemoveShareAccess(FileObject
, &pFcb
->FCBShareAccess
);
56 ExAcquireResourceExclusiveLite(&pFcb
->MainResource
, TRUE
);
57 ExAcquireResourceExclusiveLite(&pFcb
->PagingIoResource
, TRUE
);
59 pCcb
= FileObject
->FsContext2
;
60 if (BooleanFlagOn(pCcb
->Flags
, CCB_DELETE_ON_CLOSE
))
62 pFcb
->Flags
|= FCB_DELETE_PENDING
;
65 /* Notify about the cleanup */
66 FsRtlNotifyCleanup(IrpContext
->DeviceExt
->NotifySync
,
67 &(IrpContext
->DeviceExt
->NotifyList
),
68 FileObject
->FsContext2
);
70 pFcb
->OpenHandleCount
--;
71 DeviceExt
->OpenHandleCount
--;
73 if (!vfatFCBIsDirectory(pFcb
) &&
74 FsRtlAreThereCurrentFileLocks(&pFcb
->FileLock
))
76 /* remove all locks this process have on this file */
77 FsRtlFastUnlockAll(&pFcb
->FileLock
,
79 IoGetRequestorProcess(IrpContext
->Irp
),
83 if (BooleanFlagOn(pFcb
->Flags
, FCB_IS_DIRTY
))
85 VfatUpdateEntry (DeviceExt
, pFcb
);
88 if (BooleanFlagOn(pFcb
->Flags
, FCB_DELETE_PENDING
) &&
89 pFcb
->OpenHandleCount
== 0)
91 if (vfatFCBIsDirectory(pFcb
) &&
92 !VfatIsDirectoryEmpty(DeviceExt
, pFcb
))
94 pFcb
->Flags
&= ~FCB_DELETE_PENDING
;
98 PFILE_OBJECT tmpFileObject
;
99 tmpFileObject
= pFcb
->FileObject
;
100 if (tmpFileObject
!= NULL
)
102 pFcb
->FileObject
= NULL
;
103 CcUninitializeCacheMap(tmpFileObject
, NULL
, NULL
);
104 ClearFlag(pFcb
->Flags
, FCB_CACHE_INITIALIZED
);
105 ObDereferenceObject(tmpFileObject
);
108 pFcb
->RFCB
.ValidDataLength
.QuadPart
= 0;
109 pFcb
->RFCB
.FileSize
.QuadPart
= 0;
110 pFcb
->RFCB
.AllocationSize
.QuadPart
= 0;
114 /* Uninitialize the cache (should be done even if caching was never initialized) */
115 CcUninitializeCacheMap(FileObject
, &pFcb
->RFCB
.FileSize
, NULL
);
117 if (BooleanFlagOn(pFcb
->Flags
, FCB_DELETE_PENDING
) &&
118 pFcb
->OpenHandleCount
== 0)
120 VfatDelEntry(DeviceExt
, pFcb
, NULL
);
122 vfatReportChange(DeviceExt
,
124 (vfatFCBIsDirectory(pFcb
) ?
125 FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME
),
126 FILE_ACTION_REMOVED
);
129 if (pFcb
->OpenHandleCount
!= 0)
131 IoRemoveShareAccess(FileObject
, &pFcb
->FCBShareAccess
);
133 /* FIXME: causes FS corruption and breaks selfhosting/testbots and so on */
135 /* If that's the last open handle we just closed, try to see whether
136 * we can delay close operation
138 else if (!BooleanFlagOn(pFcb
->Flags
, FCB_DELETE_PENDING
) && !BooleanFlagOn(pFcb
->Flags
, FCB_IS_PAGE_FILE
) &&
139 !BooleanFlagOn(pFcb
->Flags
, FCB_IS_FAT
) && !BooleanFlagOn(pFcb
->Flags
, FCB_IS_VOLUME
))
141 /* This is only allowed if that's a directory with no open files
142 * OR if it's a file with no section opened
144 if ((vfatFCBIsDirectory(pFcb
) && IsListEmpty(&pFcb
->ParentListHead
)) ||
145 (!vfatFCBIsDirectory(pFcb
) && FileObject
->SectionObjectPointer
->DataSectionObject
== NULL
&&
146 FileObject
->SectionObjectPointer
->ImageSectionObject
== NULL
))
148 DPRINT("Delaying close of: %wZ\n", &pFcb
->PathNameU
);
149 SetFlag(pFcb
->Flags
, FCB_DELAYED_CLOSE
);
154 FileObject
->Flags
|= FO_CLEANUP_COMPLETE
;
156 pFcb
->Flags
|= FCB_CLEANED_UP
;
159 ExReleaseResourceLite(&pFcb
->PagingIoResource
);
160 ExReleaseResourceLite(&pFcb
->MainResource
);
163 #ifdef ENABLE_SWAPOUT
164 if (IsVolume
&& BooleanFlagOn(DeviceExt
->Flags
, VCB_DISMOUNT_PENDING
))
166 Deleted
= VfatCheckForDismount(DeviceExt
, TRUE
);
174 * FUNCTION: Cleans up after a file has been closed.
178 PVFAT_IRP_CONTEXT IrpContext
)
182 DPRINT("VfatCleanup(DeviceObject %p, Irp %p)\n", IrpContext
->DeviceObject
, IrpContext
->Irp
);
184 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
186 IrpContext
->Irp
->IoStatus
.Information
= 0;
187 return STATUS_SUCCESS
;
190 ExAcquireResourceExclusiveLite(&IrpContext
->DeviceExt
->DirResource
, TRUE
);
191 Deleted
= VfatCleanupFile(IrpContext
);
192 if (!Deleted
) ExReleaseResourceLite(&IrpContext
->DeviceExt
->DirResource
);
194 IrpContext
->Irp
->IoStatus
.Information
= 0;
195 return STATUS_SUCCESS
;