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 * Returns whether the device was deleted 22 */ 23 static 24 BOOLEAN 25 VfatCleanupFile( 26 PVFAT_IRP_CONTEXT IrpContext) 27 { 28 PVFATFCB pFcb; 29 PVFATCCB pCcb; 30 BOOLEAN IsVolume; 31 PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt; 32 PFILE_OBJECT FileObject = IrpContext->FileObject; 33 BOOLEAN Deleted = FALSE; 34 35 DPRINT("VfatCleanupFile(DeviceExt %p, FileObject %p)\n", 36 IrpContext->DeviceExt, FileObject); 37 38 /* FIXME: handle file/directory deletion here */ 39 pFcb = (PVFATFCB)FileObject->FsContext; 40 if (!pFcb) 41 return FALSE; 42 43 IsVolume = BooleanFlagOn(pFcb->Flags, FCB_IS_VOLUME); 44 if (IsVolume) 45 { 46 pFcb->OpenHandleCount--; 47 DeviceExt->OpenHandleCount--; 48 49 if (pFcb->OpenHandleCount != 0) 50 { 51 IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess); 52 } 53 } 54 else 55 { 56 ExAcquireResourceExclusiveLite(&pFcb->MainResource, TRUE); 57 ExAcquireResourceExclusiveLite(&pFcb->PagingIoResource, TRUE); 58 59 pCcb = FileObject->FsContext2; 60 if (BooleanFlagOn(pCcb->Flags, CCB_DELETE_ON_CLOSE)) 61 { 62 pFcb->Flags |= FCB_DELETE_PENDING; 63 } 64 65 /* Notify about the cleanup */ 66 FsRtlNotifyCleanup(IrpContext->DeviceExt->NotifySync, 67 &(IrpContext->DeviceExt->NotifyList), 68 FileObject->FsContext2); 69 70 pFcb->OpenHandleCount--; 71 DeviceExt->OpenHandleCount--; 72 73 if (!vfatFCBIsDirectory(pFcb) && 74 FsRtlAreThereCurrentFileLocks(&pFcb->FileLock)) 75 { 76 /* remove all locks this process have on this file */ 77 FsRtlFastUnlockAll(&pFcb->FileLock, 78 FileObject, 79 IoGetRequestorProcess(IrpContext->Irp), 80 NULL); 81 } 82 83 if (BooleanFlagOn(pFcb->Flags, FCB_IS_DIRTY)) 84 { 85 VfatUpdateEntry (DeviceExt, pFcb); 86 } 87 88 if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) && 89 pFcb->OpenHandleCount == 0) 90 { 91 if (vfatFCBIsDirectory(pFcb) && 92 !VfatIsDirectoryEmpty(DeviceExt, pFcb)) 93 { 94 pFcb->Flags &= ~FCB_DELETE_PENDING; 95 } 96 else 97 { 98 PFILE_OBJECT tmpFileObject; 99 tmpFileObject = pFcb->FileObject; 100 if (tmpFileObject != NULL) 101 { 102 pFcb->FileObject = NULL; 103 CcUninitializeCacheMap(tmpFileObject, NULL, NULL); 104 ClearFlag(pFcb->Flags, FCB_CACHE_INITIALIZED); 105 ObDereferenceObject(tmpFileObject); 106 } 107 108 pFcb->RFCB.ValidDataLength.QuadPart = 0; 109 pFcb->RFCB.FileSize.QuadPart = 0; 110 pFcb->RFCB.AllocationSize.QuadPart = 0; 111 } 112 } 113 114 /* Uninitialize the cache (should be done even if caching was never initialized) */ 115 CcUninitializeCacheMap(FileObject, &pFcb->RFCB.FileSize, NULL); 116 117 if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) && 118 pFcb->OpenHandleCount == 0) 119 { 120 VfatDelEntry(DeviceExt, pFcb, NULL); 121 122 vfatReportChange(DeviceExt, 123 pFcb, 124 (vfatFCBIsDirectory(pFcb) ? 125 FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME), 126 FILE_ACTION_REMOVED); 127 } 128 129 if (pFcb->OpenHandleCount != 0) 130 { 131 IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess); 132 } 133 /* FIXME: causes FS corruption and breaks selfhosting/testbots and so on */ 134 #if 0 135 /* If that's the last open handle we just closed, try to see whether 136 * we can delay close operation 137 */ 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)) 140 { 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 143 */ 144 if ((vfatFCBIsDirectory(pFcb) && IsListEmpty(&pFcb->ParentListHead)) || 145 (!vfatFCBIsDirectory(pFcb) && FileObject->SectionObjectPointer->DataSectionObject == NULL && 146 FileObject->SectionObjectPointer->ImageSectionObject == NULL)) 147 { 148 DPRINT("Delaying close of: %wZ\n", &pFcb->PathNameU); 149 SetFlag(pFcb->Flags, FCB_DELAYED_CLOSE); 150 } 151 } 152 #endif 153 154 FileObject->Flags |= FO_CLEANUP_COMPLETE; 155 #ifdef KDBG 156 pFcb->Flags |= FCB_CLEANED_UP; 157 #endif 158 159 ExReleaseResourceLite(&pFcb->PagingIoResource); 160 ExReleaseResourceLite(&pFcb->MainResource); 161 } 162 163 #ifdef ENABLE_SWAPOUT 164 if (IsVolume && BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING)) 165 { 166 Deleted = VfatCheckForDismount(DeviceExt, TRUE); 167 } 168 #endif 169 170 return Deleted; 171 } 172 173 /* 174 * FUNCTION: Cleans up after a file has been closed. 175 */ 176 NTSTATUS 177 VfatCleanup( 178 PVFAT_IRP_CONTEXT IrpContext) 179 { 180 BOOLEAN Deleted; 181 182 DPRINT("VfatCleanup(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp); 183 184 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) 185 { 186 IrpContext->Irp->IoStatus.Information = 0; 187 return STATUS_SUCCESS; 188 } 189 190 ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE); 191 Deleted = VfatCleanupFile(IrpContext); 192 if (!Deleted) ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource); 193 194 IrpContext->Irp->IoStatus.Information = 0; 195 return STATUS_SUCCESS; 196 } 197 198 /* EOF */ 199