ReactOS 0.4.15-dev-5666-gc548b97
workque.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 WorkQue.c
8
9Abstract:
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
36VOID
38 _Inout_ PIRP_CONTEXT IrpContext,
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
49_Requires_lock_held_(_Global_critical_region_)
51CdFsdPostRequest (
52 _Inout_ PIRP_CONTEXT IrpContext,
54 )
55
56/*++
57
58Routine 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
64Arguments:
65
66 IrpContext - Pointer to the IrpContext to be queued to the Fsp.
67
68 Irp - I/O Request Packet.
69
70Return 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
100
101_Requires_lock_held_(_Global_critical_region_)
102VOID
103NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
104CdPrePostIrp (
105 _Inout_ PIRP_CONTEXT IrpContext,
107 )
108
109/*++
110
111Routine 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
117Arguments:
118
119 Context - Pointer to the IrpContext to be queued to the Fsp
120
121 Irp - I/O Request Packet.
122
123Return Value:
124
125 None.
126
127--*/
128
129{
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
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
220
221 return;
222}
223
224
225
226_Requires_lock_held_(_Global_critical_region_)
227VOID
228NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
229CdOplockComplete (
230 _Inout_ PIRP_CONTEXT IrpContext,
232 )
233
234/*++
235
236Routine 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
246Arguments:
247
248 Irp - I/O Request Packet.
249
250Return 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
320//
321// Local support routine
322//
323
324VOID
326 _Inout_ PIRP_CONTEXT IrpContext,
328 )
329
330/*++
331
332Routine Description:
333
334 This routine is called to acually store the posted Irp to the Fsp
335 workque.
336
337Arguments:
338
339 IrpContext - Pointer to the IrpContext to be queued to the Fsp
340
341 Irp - I/O Request Packet.
342
343Return Value:
344
345 None.
346
347--*/
348
349{
351 KIRQL SavedIrql;
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
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
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
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
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
#define ASSERT_IRP(I)
Definition: cddata.h:250
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:248
VOID CdAddToWorkque(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: workque.c:325
#define FSP_PER_DEVICE_THRESHOLD
Definition: workque.c:30
VOID CdCleanupIrpContext(_In_ PIRP_CONTEXT IrpContext, _In_ BOOLEAN Post)
Definition: strucsup.c:1733
#define CdReleaseFcb(IC, F)
Definition: cdprocs.h:1012
WORKER_THREAD_ROUTINE CdFspDispatch
Definition: cdprocs.h:2040
#define CdLockUserBuffer(IC, BL, OP)
Definition: cdprocs.h:393
#define IRP_CONTEXT_FLAG_MORE_PROCESSING
Definition: cdstruc.h:1214
#define _Requires_lock_held_(lock)
#define _Analysis_assume_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define InsertTailList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
IoMarkIrpPending(Irp)
#define _Inout_
Definition: ms_sal.h:378
#define STATUS_PENDING
Definition: ntstatus.h:82
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define STATUS_SUCCESS
Definition: shellext.h:65
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
__volatile LONG PostedRequestCount
Definition: cdstruc.h:739
KSPIN_LOCK OverflowQueueSpinLock
Definition: cdstruc.h:760
LIST_ENTRY OverflowQueue
Definition: cdstruc.h:754
ULONG OverflowQueueCount
Definition: cdstruc.h:746
#define NTAPI
Definition: typedefs.h:36
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ CriticalWorkQueue
Definition: extypes.h:189
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define IRP_MN_MDL
Definition: iotypes.h:4419
@ IoReadAccess
Definition: ketypes.h:851
@ IoWriteAccess
Definition: ketypes.h:852