Revert "[CDFS_NEW] Use CdAcquireForCreateSection from the old driver in place of...
[reactos.git] / drivers / filesystems / cdfs_new / workque.c
1 /*++
2
3 Copyright (c) 1989-2000 Microsoft Corporation
4
5 Module Name:
6
7 WorkQue.c
8
9 Abstract:
10
11 This module implements the Work queue routines for the Cdfs File
12 system.
13
14
15 --*/
16
17 #include "cdprocs.h"
18
19 //
20 // The Bug check file id for this module
21 //
22
23 #define BugCheckFileId (CDFS_BUG_CHECK_WORKQUE)
24
25 //
26 // The following constant is the maximum number of ExWorkerThreads that we
27 // will allow to be servicing a particular target device at any one time.
28 //
29
30 #define FSP_PER_DEVICE_THRESHOLD (2)
31
32 //
33 // Local support routines
34 //
35
36 VOID
37 CdAddToWorkque (
38 _Inout_ PIRP_CONTEXT IrpContext,
39 _Inout_ PIRP Irp
40 );
41
42 #ifdef ALLOC_PRAGMA
43 #pragma alloc_text(PAGE, CdFsdPostRequest)
44 #pragma alloc_text(PAGE, CdOplockComplete)
45 #pragma alloc_text(PAGE, CdPrePostIrp)
46 #endif
47
48 \f
49 _Requires_lock_held_(_Global_critical_region_)
50 NTSTATUS
51 CdFsdPostRequest (
52 _Inout_ PIRP_CONTEXT IrpContext,
53 _Inout_ PIRP Irp
54 )
55
56 /*++
57
58 Routine Description:
59
60 This routine enqueues the request packet specified by IrpContext to the
61 work queue associated with the FileSystemDeviceObject. This is a FSD
62 routine.
63
64 Arguments:
65
66 IrpContext - Pointer to the IrpContext to be queued to the Fsp.
67
68 Irp - I/O Request Packet.
69
70 Return Value:
71
72 STATUS_PENDING
73
74 --*/
75
76 {
77 PAGED_CODE();
78
79 ASSERT_IRP_CONTEXT( IrpContext );
80 ASSERT_IRP( Irp );
81
82 //
83 // Posting is a three step operation. First lock down any buffers
84 // in the Irp. Next cleanup the IrpContext for the post and finally
85 // add this to a workque.
86 //
87
88 CdPrePostIrp( IrpContext, Irp );
89
90 CdAddToWorkque( IrpContext, Irp );
91
92 //
93 // And return to our caller
94 //
95
96 return STATUS_PENDING;
97 }
98
99 \f
100
101 _Requires_lock_held_(_Global_critical_region_)
102 VOID
103 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
104 CdPrePostIrp (
105 _Inout_ PIRP_CONTEXT IrpContext,
106 _Inout_ PIRP Irp
107 )
108
109 /*++
110
111 Routine Description:
112
113 This routine performs any neccessary work before STATUS_PENDING is
114 returned with the Fsd thread. This routine is called within the
115 filesystem and by the oplock package.
116
117 Arguments:
118
119 Context - Pointer to the IrpContext to be queued to the Fsp
120
121 Irp - I/O Request Packet.
122
123 Return Value:
124
125 None.
126
127 --*/
128
129 {
130 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
131 BOOLEAN RemovedFcb;
132
133 PAGED_CODE();
134
135 ASSERT_IRP_CONTEXT( IrpContext );
136 ASSERT_IRP( Irp );
137
138 //
139 // Case on the type of the operation.
140 //
141
142 switch (IrpContext->MajorFunction) {
143
144 case IRP_MJ_CREATE :
145
146 //
147 // If called from the oplock package then there is an
148 // Fcb to possibly teardown. We will call the teardown
149 // routine and release the Fcb if still present. The cleanup
150 // code in create will know not to release this Fcb because
151 // we will clear the pointer.
152 //
153
154 if ((IrpContext->TeardownFcb != NULL) &&
155 *(IrpContext->TeardownFcb) != NULL) {
156
157 CdTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), &RemovedFcb );
158
159 if (!RemovedFcb) {
160
161 _Analysis_assume_lock_held_((*IrpContext->TeardownFcb)->FcbNonpaged->FcbResource);
162 CdReleaseFcb( IrpContext, *(IrpContext->TeardownFcb) );
163 }
164
165 *(IrpContext->TeardownFcb) = NULL;
166 IrpContext->TeardownFcb = NULL;
167 }
168
169 break;
170
171 //
172 // We need to lock the user's buffer, unless this is an MDL read/write,
173 // in which case there is no user buffer.
174 //
175
176 case IRP_MJ_READ :
177
178 if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {
179
180 CdLockUserBuffer( IrpContext, IrpSp->Parameters.Read.Length, IoWriteAccess );
181 }
182
183 break;
184
185 case IRP_MJ_WRITE :
186
187 if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {
188
189 CdLockUserBuffer( IrpContext, IrpSp->Parameters.Read.Length, IoReadAccess );
190 }
191
192 break;
193
194 //
195 // We also need to check whether this is a query file operation.
196 //
197
198 case IRP_MJ_DIRECTORY_CONTROL :
199
200 if (IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
201
202 CdLockUserBuffer( IrpContext, IrpSp->Parameters.QueryDirectory.Length, IoWriteAccess );
203 }
204
205 break;
206 }
207
208 //
209 // Cleanup the IrpContext for the post.
210 //
211
212 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
213 CdCleanupIrpContext( IrpContext, TRUE );
214
215 //
216 // Mark the Irp to show that we've already returned pending to the user.
217 //
218
219 IoMarkIrpPending( Irp );
220
221 return;
222 }
223
224 \f
225
226 _Requires_lock_held_(_Global_critical_region_)
227 VOID
228 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
229 CdOplockComplete (
230 _Inout_ PIRP_CONTEXT IrpContext,
231 _Inout_ PIRP Irp
232 )
233
234 /*++
235
236 Routine Description:
237
238 This routine is called by the oplock package when an oplock break has
239 completed, allowing an Irp to resume execution. If the status in
240 the Irp is STATUS_SUCCESS, then we queue the Irp to the Fsp queue.
241 Otherwise we complete the Irp with the status in the Irp.
242
243 If we are completing due to an error then check if there is any
244 cleanup to do.
245
246 Arguments:
247
248 Irp - I/O Request Packet.
249
250 Return Value:
251
252 None.
253
254 --*/
255
256 {
257 BOOLEAN RemovedFcb;
258
259 PAGED_CODE();
260
261 //
262 // Check on the return value in the Irp. If success then we
263 // are to post this request.
264 //
265
266 if (Irp->IoStatus.Status == STATUS_SUCCESS) {
267
268 //
269 // Check if there is any cleanup work to do.
270 //
271
272 switch (IrpContext->MajorFunction) {
273
274 case IRP_MJ_CREATE :
275
276 //
277 // If called from the oplock package then there is an
278 // Fcb to possibly teardown. We will call the teardown
279 // routine and release the Fcb if still present. The cleanup
280 // code in create will know not to release this Fcb because
281 // we will clear the pointer.
282 //
283
284 if (IrpContext->TeardownFcb != NULL) {
285
286 CdTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), &RemovedFcb );
287
288 if (!RemovedFcb) {
289
290 _Analysis_assume_lock_held_((*IrpContext->TeardownFcb)->FcbNonpaged->FcbResource);
291 CdReleaseFcb( IrpContext, *(IrpContext->TeardownFcb) );
292 }
293
294 *(IrpContext->TeardownFcb) = NULL;
295 IrpContext->TeardownFcb = NULL;
296 }
297
298 break;
299 }
300
301 //
302 // Insert the Irp context in the workqueue.
303 //
304
305 CdAddToWorkque( IrpContext, Irp );
306
307 //
308 // Otherwise complete the request.
309 //
310
311 } else {
312
313 CdCompleteRequest( IrpContext, Irp, Irp->IoStatus.Status );
314 }
315
316 return;
317 }
318
319 \f
320 //
321 // Local support routine
322 //
323
324 VOID
325 CdAddToWorkque (
326 _Inout_ PIRP_CONTEXT IrpContext,
327 _Inout_ PIRP Irp
328 )
329
330 /*++
331
332 Routine Description:
333
334 This routine is called to acually store the posted Irp to the Fsp
335 workque.
336
337 Arguments:
338
339 IrpContext - Pointer to the IrpContext to be queued to the Fsp
340
341 Irp - I/O Request Packet.
342
343 Return Value:
344
345 None.
346
347 --*/
348
349 {
350 PVOLUME_DEVICE_OBJECT Vdo;
351 KIRQL SavedIrql;
352 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
353
354 //
355 // Check if this request has an associated file object, and thus volume
356 // device object.
357 //
358
359 if (IrpSp->FileObject != NULL) {
360
361
362 Vdo = CONTAINING_RECORD( IrpSp->DeviceObject,
363 VOLUME_DEVICE_OBJECT,
364 DeviceObject );
365
366 //
367 // Check to see if this request should be sent to the overflow
368 // queue. If not, then send it off to an exworker thread.
369 //
370
371 KeAcquireSpinLock( &Vdo->OverflowQueueSpinLock, &SavedIrql );
372
373 if (Vdo->PostedRequestCount > FSP_PER_DEVICE_THRESHOLD) {
374
375 //
376 // We cannot currently respond to this IRP so we'll just enqueue it
377 // to the overflow queue on the volume.
378 //
379
380 InsertTailList( &Vdo->OverflowQueue,
381 &IrpContext->WorkQueueItem.List );
382
383 Vdo->OverflowQueueCount += 1;
384
385 KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql );
386
387 return;
388
389 } else {
390
391 //
392 // We are going to send this Irp to an ex worker thread so up
393 // the count.
394 //
395
396 Vdo->PostedRequestCount += 1;
397
398 KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql );
399 }
400 }
401
402 //
403 // Send it off.....
404 //
405
406 #ifdef _MSC_VER
407 #pragma prefast(suppress:28155, "the function prototype is correct")
408 #endif
409 ExInitializeWorkItem( &IrpContext->WorkQueueItem,
410 (PVOID)CdFspDispatch,/* ReactOS Change: GCC "assignment from incompatible pointer type" */
411 IrpContext );
412
413 #ifdef _MSC_VER
414 #pragma prefast(suppress: 28159, "prefast believes this routine is obsolete, but it is ok for CDFS to continue using it")
415 #endif
416 ExQueueWorkItem( &IrpContext->WorkQueueItem, CriticalWorkQueue );
417
418 return;
419 }
420
421
422