* FILE: drivers/fs/vfat/cleanup.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
+ * Pierre Schweitzer (pierre@reactos.org)
*/
/* INCLUDES *****************************************************************/
/*
* FUNCTION: Cleans up after a file has been closed.
+ * Returns whether the device was deleted
*/
static
-NTSTATUS
+BOOLEAN
VfatCleanupFile(
PVFAT_IRP_CONTEXT IrpContext)
{
PVFATFCB pFcb;
+ PVFATCCB pCcb;
+ BOOLEAN IsVolume;
PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt;
PFILE_OBJECT FileObject = IrpContext->FileObject;
+ BOOLEAN Deleted = FALSE;
DPRINT("VfatCleanupFile(DeviceExt %p, FileObject %p)\n",
IrpContext->DeviceExt, FileObject);
/* FIXME: handle file/directory deletion here */
pFcb = (PVFATFCB)FileObject->FsContext;
if (!pFcb)
- return STATUS_SUCCESS;
+ return FALSE;
- if (pFcb->Flags & FCB_IS_VOLUME)
+ IsVolume = BooleanFlagOn(pFcb->Flags, FCB_IS_VOLUME);
+ if (IsVolume)
{
pFcb->OpenHandleCount--;
+ DeviceExt->OpenHandleCount--;
if (pFcb->OpenHandleCount != 0)
{
}
else
{
- if(!ExAcquireResourceExclusiveLite(&pFcb->MainResource,
- BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
- {
- return STATUS_PENDING;
- }
- if(!ExAcquireResourceExclusiveLite(&pFcb->PagingIoResource,
- BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
+ ExAcquireResourceExclusiveLite(&pFcb->MainResource, TRUE);
+ ExAcquireResourceExclusiveLite(&pFcb->PagingIoResource, TRUE);
+
+ pCcb = FileObject->FsContext2;
+ if (BooleanFlagOn(pCcb->Flags, CCB_DELETE_ON_CLOSE))
{
- ExReleaseResourceLite(&pFcb->MainResource);
- return STATUS_PENDING;
+ pFcb->Flags |= FCB_DELETE_PENDING;
}
/* Notify about the cleanup */
pFcb->OpenHandleCount--;
DeviceExt->OpenHandleCount--;
- if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) &&
+ if (!vfatFCBIsDirectory(pFcb) &&
FsRtlAreThereCurrentFileLocks(&pFcb->FileLock))
{
/* remove all locks this process have on this file */
NULL);
}
- if (pFcb->Flags & FCB_IS_DIRTY)
+ if (BooleanFlagOn(pFcb->Flags, FCB_IS_DIRTY))
{
- VfatUpdateEntry (pFcb);
+ VfatUpdateEntry (DeviceExt, pFcb);
}
- if (pFcb->Flags & FCB_DELETE_PENDING &&
+ if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) &&
pFcb->OpenHandleCount == 0)
{
- PFILE_OBJECT tmpFileObject;
- tmpFileObject = pFcb->FileObject;
- if (tmpFileObject != NULL)
+ if (vfatFCBIsDirectory(pFcb) &&
+ !VfatIsDirectoryEmpty(DeviceExt, pFcb))
{
- pFcb->FileObject = NULL;
- CcUninitializeCacheMap(tmpFileObject, NULL, NULL);
- ObDereferenceObject(tmpFileObject);
+ pFcb->Flags &= ~FCB_DELETE_PENDING;
+ }
+ else
+ {
+ PFILE_OBJECT tmpFileObject;
+ tmpFileObject = pFcb->FileObject;
+ if (tmpFileObject != NULL)
+ {
+ pFcb->FileObject = NULL;
+ CcUninitializeCacheMap(tmpFileObject, NULL, NULL);
+ ClearFlag(pFcb->Flags, FCB_CACHE_INITIALIZED);
+ ObDereferenceObject(tmpFileObject);
+ }
+
+ pFcb->RFCB.ValidDataLength.QuadPart = 0;
+ pFcb->RFCB.FileSize.QuadPart = 0;
+ pFcb->RFCB.AllocationSize.QuadPart = 0;
}
-
- pFcb->RFCB.ValidDataLength.QuadPart = 0;
- pFcb->RFCB.FileSize.QuadPart = 0;
- pFcb->RFCB.AllocationSize.QuadPart = 0;
}
/* Uninitialize the cache (should be done even if caching was never initialized) */
CcUninitializeCacheMap(FileObject, &pFcb->RFCB.FileSize, NULL);
- if (pFcb->Flags & FCB_DELETE_PENDING &&
+ if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) &&
pFcb->OpenHandleCount == 0)
{
VfatDelEntry(DeviceExt, pFcb, NULL);
- FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
- &(DeviceExt->NotifyList),
- (PSTRING)&pFcb->PathNameU,
- pFcb->PathNameU.Length - pFcb->LongNameU.Length,
- NULL,
- NULL,
- ((*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
- FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
- FILE_ACTION_REMOVED,
- NULL);
+ vfatReportChange(DeviceExt,
+ pFcb,
+ (vfatFCBIsDirectory(pFcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
+ FILE_ACTION_REMOVED);
}
if (pFcb->OpenHandleCount != 0)
{
IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess);
}
+/* FIXME: causes FS corruption and breaks selfhosting/testbots and so on */
+#if 0
+ /* If that's the last open handle we just closed, try to see whether
+ * we can delay close operation
+ */
+ else if (!BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) && !BooleanFlagOn(pFcb->Flags, FCB_IS_PAGE_FILE) &&
+ !BooleanFlagOn(pFcb->Flags, FCB_IS_FAT) && !BooleanFlagOn(pFcb->Flags, FCB_IS_VOLUME))
+ {
+ /* This is only allowed if that's a directory with no open files
+ * OR if it's a file with no section opened
+ */
+ if ((vfatFCBIsDirectory(pFcb) && IsListEmpty(&pFcb->ParentListHead)) ||
+ (!vfatFCBIsDirectory(pFcb) && FileObject->SectionObjectPointer->DataSectionObject == NULL &&
+ FileObject->SectionObjectPointer->ImageSectionObject == NULL))
+ {
+ DPRINT("Delaying close of: %wZ\n", &pFcb->PathNameU);
+ SetFlag(pFcb->Flags, FCB_DELAYED_CLOSE);
+ }
+ }
+#endif
FileObject->Flags |= FO_CLEANUP_COMPLETE;
+#ifdef KDBG
+ pFcb->Flags |= FCB_CLEANED_UP;
+#endif
ExReleaseResourceLite(&pFcb->PagingIoResource);
ExReleaseResourceLite(&pFcb->MainResource);
}
#ifdef ENABLE_SWAPOUT
- if (DeviceExt->Flags & VCB_DISMOUNT_PENDING)
+ if (IsVolume && BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING))
{
- VfatCheckForDismount(DeviceExt, FALSE);
+ Deleted = VfatCheckForDismount(DeviceExt, TRUE);
}
#endif
- return STATUS_SUCCESS;
+ return Deleted;
}
/*
VfatCleanup(
PVFAT_IRP_CONTEXT IrpContext)
{
- NTSTATUS Status;
+ BOOLEAN Deleted;
DPRINT("VfatCleanup(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp);
return STATUS_SUCCESS;
}
- if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource,
- BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
- {
- return VfatMarkIrpContextForQueue(IrpContext);
- }
-
- Status = VfatCleanupFile(IrpContext);
-
- ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
-
- if (Status == STATUS_PENDING)
- {
- return VfatMarkIrpContextForQueue(IrpContext);
- }
+ ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
+ Deleted = VfatCleanupFile(IrpContext);
+ if (!Deleted) ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
IrpContext->Irp->IoStatus.Information = 0;
- return Status;
+ return STATUS_SUCCESS;
}
/* EOF */