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, TRUE); 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 */ 197