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
Ext2Close(IN PEXT2_IRP_CONTEXT IrpContext)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
Ext2QueueCloseRequest(IN PEXT2_IRP_CONTEXT IrpContext)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
Ext2DeQueueCloseRequest(IN PVOID Context)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