1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: close.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "ext2fs.h" 13 14 /* GLOBALS ***************************************************************/ 15 16 extern PEXT2_GLOBAL Ext2Global; 17 18 /* DEFINITIONS *************************************************************/ 19 20 #ifdef ALLOC_PRAGMA 21 #pragma alloc_text(PAGE, Ext2QueueCloseRequest) 22 #pragma alloc_text(PAGE, Ext2DeQueueCloseRequest) 23 #endif 24 25 NTSTATUS 26 Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) 27 { 28 PDEVICE_OBJECT DeviceObject; 29 NTSTATUS Status = STATUS_SUCCESS; 30 PEXT2_VCB Vcb = NULL; 31 PFILE_OBJECT FileObject; 32 PEXT2_FCB Fcb = NULL; 33 PEXT2_CCB Ccb = NULL; 34 35 BOOLEAN VcbResourceAcquired = FALSE; 36 BOOLEAN FcbResourceAcquired = FALSE; 37 BOOLEAN FcbDerefDeferred = FALSE; 38 39 _SEH2_TRY { 40 41 ASSERT(IrpContext != NULL); 42 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 43 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 44 45 DeviceObject = IrpContext->DeviceObject; 46 if (IsExt2FsDevice(DeviceObject)) { 47 Status = STATUS_SUCCESS; 48 Vcb = NULL; 49 _SEH2_LEAVE; 50 } 51 52 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 53 ASSERT(Vcb != NULL); 54 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 55 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 56 57 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) { 58 59 FileObject = NULL; 60 Fcb = IrpContext->Fcb; 61 Ccb = IrpContext->Ccb; 62 63 } else { 64 65 FileObject = IrpContext->FileObject; 66 Fcb = (PEXT2_FCB) FileObject->FsContext; 67 if (!Fcb) { 68 Status = STATUS_SUCCESS; 69 _SEH2_LEAVE; 70 } 71 ASSERT(Fcb != NULL); 72 Ccb = (PEXT2_CCB) FileObject->FsContext2; 73 } 74 75 DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n", 76 Vcb, Vcb->ReferenceCount)); 77 78 /* 79 * WARNING: don't release Vcb resource lock here. 80 * 81 * CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE 82 * which would cause revrese order of lock acquirision: 83 * 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock 84 * 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock 85 */ 86 87 if (Fcb->Identifier.Type == EXT2VCB) { 88 89 if (!ExAcquireResourceExclusiveLite( 90 &Vcb->MainResource, 91 TRUE )) { 92 DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n", 93 Vcb->OpenHandleCount, Vcb->ReferenceCount)); 94 Status = STATUS_PENDING; 95 _SEH2_LEAVE; 96 } 97 VcbResourceAcquired = TRUE; 98 99 if (Ccb) { 100 101 Ext2DerefXcb(&Vcb->ReferenceCount); 102 Ext2FreeCcb(Vcb, Ccb); 103 104 if (FileObject) { 105 FileObject->FsContext2 = Ccb = NULL; 106 } 107 } 108 109 Status = STATUS_SUCCESS; 110 _SEH2_LEAVE; 111 } 112 113 if ( Fcb->Identifier.Type != EXT2FCB || 114 Fcb->Identifier.Size != sizeof(EXT2_FCB)) { 115 _SEH2_LEAVE; 116 } 117 118 if (!ExAcquireResourceExclusiveLite( 119 &Fcb->MainResource, 120 TRUE )) { 121 Status = STATUS_PENDING; 122 _SEH2_LEAVE; 123 } 124 FcbResourceAcquired = TRUE; 125 126 Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; 127 128 if (Ccb == NULL || 129 Ccb->Identifier.Type != EXT2CCB || 130 Ccb->Identifier.Size != sizeof(EXT2_CCB)) { 131 Status = STATUS_SUCCESS; 132 _SEH2_LEAVE; 133 } 134 135 DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n", 136 Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName )); 137 138 Ext2FreeCcb(Vcb, Ccb); 139 if (FileObject) { 140 FileObject->FsContext2 = Ccb = NULL; 141 } 142 143 /* only deref fcb, Ext2ReleaseFcb might lead deadlock */ 144 FcbDerefDeferred = TRUE; 145 if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) || 146 NULL == Fcb->Mcb || 147 IsFileDeleted(Fcb->Mcb)) { 148 Fcb->TsDrop.QuadPart = 0; 149 } else { 150 KeQuerySystemTime(&Fcb->TsDrop); 151 } 152 Ext2DerefXcb(&Vcb->ReferenceCount); 153 154 if (FileObject) { 155 FileObject->FsContext = NULL; 156 } 157 158 Status = STATUS_SUCCESS; 159 160 } _SEH2_FINALLY { 161 162 if (FcbResourceAcquired) { 163 ExReleaseResourceLite(&Fcb->MainResource); 164 } 165 166 if (VcbResourceAcquired) { 167 ExReleaseResourceLite(&Vcb->MainResource); 168 } 169 170 if (!IrpContext->ExceptionInProgress) { 171 172 if (Status == STATUS_PENDING) { 173 174 Ext2QueueCloseRequest(IrpContext); 175 176 } else { 177 178 Ext2CompleteIrpContext(IrpContext, Status); 179 } 180 } 181 182 if (FcbDerefDeferred) 183 Ext2DerefXcb(&Fcb->ReferenceCount); 184 } _SEH2_END; 185 186 return Status; 187 } 188 189 VOID 190 Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext) 191 { 192 ASSERT(IrpContext); 193 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 194 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 195 196 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) { 197 198 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) { 199 Ext2Sleep(500); /* 0.5 sec*/ 200 } else { 201 Ext2Sleep(50); /* 0.05 sec*/ 202 } 203 204 } else { 205 206 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 207 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE); 208 209 IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext; 210 IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2; 211 } 212 213 ExInitializeWorkItem( 214 &IrpContext->WorkQueueItem, 215 Ext2DeQueueCloseRequest, 216 IrpContext); 217 218 ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue); 219 } 220 221 VOID NTAPI 222 Ext2DeQueueCloseRequest (IN PVOID Context) 223 { 224 PEXT2_IRP_CONTEXT IrpContext; 225 226 IrpContext = (PEXT2_IRP_CONTEXT) Context; 227 ASSERT(IrpContext); 228 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 229 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 230 231 _SEH2_TRY { 232 233 _SEH2_TRY { 234 235 FsRtlEnterFileSystem(); 236 Ext2Close(IrpContext); 237 238 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { 239 240 Ext2ExceptionHandler(IrpContext); 241 } _SEH2_END; 242 243 } _SEH2_FINALLY { 244 245 FsRtlExitFileSystem(); 246 } _SEH2_END; 247 } 248