2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ***************************************************************/
16 extern PEXT2_GLOBAL Ext2Global
;
18 /* DEFINITIONS *************************************************************/
21 Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext
)
23 PDEVICE_OBJECT DeviceObject
;
24 NTSTATUS Status
= STATUS_SUCCESS
;
26 PFILE_OBJECT FileObject
;
33 BOOLEAN VcbResourceAcquired
= FALSE
;
34 BOOLEAN FcbResourceAcquired
= FALSE
;
35 BOOLEAN FcbPagingIoResourceAcquired
= FALSE
;
39 ASSERT(IrpContext
!= NULL
);
40 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
41 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
43 DeviceObject
= IrpContext
->DeviceObject
;
44 if (IsExt2FsDevice(DeviceObject
)) {
45 Status
= STATUS_SUCCESS
;
49 Irp
= IrpContext
->Irp
;
50 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
52 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
53 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
55 if (!IsVcbInited(Vcb
)) {
56 Status
= STATUS_SUCCESS
;
60 FileObject
= IrpContext
->FileObject
;
61 Fcb
= (PEXT2_FCB
) FileObject
->FsContext
;
62 if (!Fcb
|| (Fcb
->Identifier
.Type
!= EXT2VCB
&&
63 Fcb
->Identifier
.Type
!= EXT2FCB
)) {
64 Status
= STATUS_SUCCESS
;
68 Ccb
= (PEXT2_CCB
) FileObject
->FsContext2
;
70 if (IsFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
)) {
71 Status
= STATUS_SUCCESS
;
76 ExAcquireResourceExclusiveLite(
78 IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
)
81 if (Fcb
->Identifier
.Type
== EXT2VCB
) {
83 if (FlagOn(Vcb
->Flags
, VCB_VOLUME_LOCKED
) &&
84 Vcb
->LockFile
== FileObject
){
86 ClearFlag(Vcb
->Flags
, VCB_VOLUME_LOCKED
);
88 Ext2ClearVpbFlag(Vcb
->Vpb
, VPB_LOCKED
);
92 Ext2DerefXcb(&Vcb
->OpenHandleCount
);
93 Ext2DerefXcb(&Vcb
->OpenVolumeCount
);
96 IoRemoveShareAccess(FileObject
, &Vcb
->ShareAccess
);
98 Status
= STATUS_SUCCESS
;
102 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
103 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
105 if (IsFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
)) {
106 if (IsFlagOn(FileObject
->Flags
, FO_FILE_MODIFIED
) &&
107 IsFlagOn(Vcb
->Flags
, VCB_FLOPPY_DISK
) &&
108 !IsVcbReadOnly(Vcb
) ) {
109 Status
= Ext2FlushFile(IrpContext
, Fcb
, Ccb
);
115 Status
= STATUS_SUCCESS
;
119 if (IsDirectory(Fcb
)) {
120 if (IsFlagOn(Ccb
->Flags
, CCB_DELETE_ON_CLOSE
)) {
121 SetLongFlag(Fcb
->Flags
, FCB_DELETE_PENDING
);
123 FsRtlNotifyFullChangeDirectory(
136 FsRtlNotifyCleanup(Vcb
->NotifySync
, &Vcb
->NotifyList
, Ccb
);
140 ExReleaseResourceLite(&Vcb
->MainResource
);
141 VcbResourceAcquired
= FALSE
;
143 FcbResourceAcquired
=
144 ExAcquireResourceExclusiveLite(
146 IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
)
149 ASSERT((Ccb
->Identifier
.Type
== EXT2CCB
) &&
150 (Ccb
->Identifier
.Size
== sizeof(EXT2_CCB
)));
152 Ext2DerefXcb(&Vcb
->OpenHandleCount
);
153 Ext2DerefXcb(&Fcb
->OpenHandleCount
);
155 if (IsFlagOn(FileObject
->Flags
, FO_FILE_MODIFIED
)) {
156 Fcb
->Mcb
->FileAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
159 if (IsDirectory(Fcb
)) {
161 ext3_release_dir(Fcb
->Inode
, &Ccb
->filp
);
165 if ( IsFlagOn(FileObject
->Flags
, FO_FILE_MODIFIED
) &&
166 !IsFlagOn(Ccb
->Flags
, CCB_LAST_WRITE_UPDATED
)) {
168 LARGE_INTEGER SysTime
;
169 KeQuerySystemTime(&SysTime
);
171 Fcb
->Inode
->i_atime
=
172 Fcb
->Inode
->i_mtime
= Ext2LinuxTime(SysTime
);
173 Fcb
->Mcb
->LastAccessTime
=
174 Fcb
->Mcb
->LastWriteTime
= Ext2NtTime(Fcb
->Inode
->i_atime
);
176 Ext2SaveInode(IrpContext
, Vcb
, Fcb
->Inode
);
178 Ext2NotifyReportChange(
182 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
183 FILE_NOTIFY_CHANGE_LAST_WRITE
|
184 FILE_NOTIFY_CHANGE_LAST_ACCESS
,
185 FILE_ACTION_MODIFIED
);
188 FsRtlCheckOplock( &Fcb
->Oplock
,
194 Fcb
->Header
.IsFastIoPossible
= Ext2IsFastIoPossible(Fcb
);
196 if (!IsFlagOn(FileObject
->Flags
, FO_CACHE_SUPPORTED
)) {
197 Fcb
->NonCachedOpenCount
--;
200 if (IsFlagOn(Ccb
->Flags
, CCB_DELETE_ON_CLOSE
)) {
201 SetLongFlag(Fcb
->Flags
, FCB_DELETE_PENDING
);
205 // Drop any byte range locks this process may have on the file.
209 &Fcb
->FileLockAnchor
,
211 IoGetRequestorProcess(Irp
),
215 // If there are no byte range locks owned by other processes on the
216 // file the fast I/O read/write functions doesn't have to check for
217 // locks so we set IsFastIoPossible to FastIoIsPossible again.
219 if (!FsRtlGetNextFileLock(&Fcb
->FileLockAnchor
, TRUE
)) {
220 if (Fcb
->Header
.IsFastIoPossible
!= FastIoIsPossible
) {
222 DEBUG(DL_INF
, (": %-16.16s %-31s %wZ\n",
223 Ext2GetCurrentProcessName(),
229 Fcb
->Header
.IsFastIoPossible
= FastIoIsPossible
;
233 if (Fcb
->OpenHandleCount
== 0 && FlagOn(Fcb
->Flags
, FCB_ALLOC_IN_CREATE
|
234 FCB_ALLOC_IN_SETINFO
) ){
236 if (FlagOn(Fcb
->Flags
, FCB_ALLOC_IN_SETINFO
)) {
237 if (Fcb
->Header
.ValidDataLength
.QuadPart
< Fcb
->Header
.FileSize
.QuadPart
) {
238 if (!INODE_HAS_EXTENT(Fcb
->Inode
)) {
239 #if EXT2_PRE_ALLOCATION_SUPPORT
240 CcZeroData(FileObject
, &Fcb
->Header
.ValidDataLength
,
241 &Fcb
->Header
.AllocationSize
, TRUE
);
247 if (FlagOn(Fcb
->Flags
, FCB_ALLOC_IN_CREATE
)) {
251 ExAcquireResourceExclusiveLite(&Fcb
->PagingIoResource
, TRUE
);
252 FcbPagingIoResourceAcquired
= TRUE
;
254 Size
.QuadPart
= CEILING_ALIGNED(ULONGLONG
,
255 (ULONGLONG
)Fcb
->Mcb
->Inode
.i_size
,
256 (ULONGLONG
)BLOCK_SIZE
);
257 if (!IsFlagOn(Fcb
->Flags
, FCB_DELETE_PENDING
)) {
259 Ext2TruncateFile(IrpContext
, Vcb
, Fcb
->Mcb
, &Size
);
260 Fcb
->Header
.AllocationSize
= Size
;
261 Fcb
->Header
.FileSize
.QuadPart
= Mcb
->Inode
.i_size
;
262 if (Fcb
->Header
.ValidDataLength
.QuadPart
> Fcb
->Header
.FileSize
.QuadPart
)
263 Fcb
->Header
.ValidDataLength
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
264 if (CcIsFileCached(FileObject
)) {
265 CcSetFileSizes(FileObject
,
266 (PCC_FILE_SIZES
)(&(Fcb
->Header
.AllocationSize
)));
269 ClearLongFlag(Fcb
->Flags
, FCB_ALLOC_IN_CREATE
|FCB_ALLOC_IN_WRITE
|FCB_ALLOC_IN_SETINFO
);
270 ExReleaseResourceLite(&Fcb
->PagingIoResource
);
271 FcbPagingIoResourceAcquired
= FALSE
;
276 if (IsFlagOn(Fcb
->Flags
, FCB_DELETE_PENDING
)) {
278 if (Fcb
->OpenHandleCount
== 0 || (Mcb
= Ccb
->SymLink
)) {
281 // Ext2DeleteFile will acquire these lock inside
284 if (FcbResourceAcquired
) {
285 ExReleaseResourceLite(&Fcb
->MainResource
);
286 FcbResourceAcquired
= FALSE
;
290 // this file is to be deleted ...
294 FileObject
->DeletePending
= FALSE
;
297 Status
= Ext2DeleteFile(IrpContext
, Vcb
, Fcb
, Mcb
);
299 if (NT_SUCCESS(Status
)) {
300 if (IsMcbDirectory(Mcb
)) {
301 Ext2NotifyReportChange( IrpContext
, Vcb
, Mcb
,
302 FILE_NOTIFY_CHANGE_DIR_NAME
,
303 FILE_ACTION_REMOVED
);
305 Ext2NotifyReportChange( IrpContext
, Vcb
, Mcb
,
306 FILE_NOTIFY_CHANGE_FILE_NAME
,
307 FILE_ACTION_REMOVED
);
312 // re-acquire the main resource lock
315 FcbResourceAcquired
=
316 ExAcquireResourceExclusiveLite(
318 IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
)
321 SetFlag(FileObject
->Flags
, FO_FILE_MODIFIED
);
322 if (CcIsFileCached(FileObject
)) {
323 CcSetFileSizes(FileObject
,
324 (PCC_FILE_SIZES
)(&(Fcb
->Header
.AllocationSize
)));
329 if (!IsDirectory(Fcb
)) {
331 if ( IsFlagOn(FileObject
->Flags
, FO_CACHE_SUPPORTED
) &&
332 (Fcb
->NonCachedOpenCount
+ 1 == Fcb
->ReferenceCount
) &&
333 (Fcb
->SectionObject
.DataSectionObject
!= NULL
)) {
335 if (!IsVcbReadOnly(Vcb
)) {
336 CcFlushCache(&Fcb
->SectionObject
, NULL
, 0, NULL
);
337 ClearLongFlag(Fcb
->Flags
, FCB_FILE_MODIFIED
);
340 if (ExAcquireResourceExclusiveLite(&(Fcb
->PagingIoResource
), TRUE
)) {
341 ExReleaseResourceLite(&(Fcb
->PagingIoResource
));
344 CcPurgeCacheSection( &Fcb
->SectionObject
,
350 CcUninitializeCacheMap(FileObject
, NULL
, NULL
);
353 IoRemoveShareAccess(FileObject
, &Fcb
->ShareAccess
);
355 DEBUG(DL_INF
, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
356 Fcb
->OpenHandleCount
, Fcb
->ReferenceCount
, Fcb
->NonCachedOpenCount
, &Fcb
->Mcb
->FullName
));
358 Status
= STATUS_SUCCESS
;
361 SetFlag(FileObject
->Flags
, FO_CLEANUP_COMPLETE
);
366 if (FcbPagingIoResourceAcquired
) {
367 ExReleaseResourceLite(&Fcb
->PagingIoResource
);
370 if (FcbResourceAcquired
) {
371 ExReleaseResourceLite(&Fcb
->MainResource
);
374 if (VcbResourceAcquired
) {
375 ExReleaseResourceLite(&Vcb
->MainResource
);
378 if (!IrpContext
->ExceptionInProgress
) {
379 if (Status
== STATUS_PENDING
) {
380 Ext2QueueRequest(IrpContext
);
382 IrpContext
->Irp
->IoStatus
.Status
= Status
;
383 Ext2CompleteIrpContext(IrpContext
, Status
);