3 Copyright (c) 1989-2000 Microsoft Corporation
11 This module implements the Work queue routines for the Cdfs File
20 // The Bug check file id for this module
23 #define BugCheckFileId (CDFS_BUG_CHECK_WORKQUE)
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.
30 #define FSP_PER_DEVICE_THRESHOLD (2)
33 // Local support routines
38 IN PIRP_CONTEXT IrpContext
,
43 #pragma alloc_text(PAGE, CdFsdPostRequest)
44 #pragma alloc_text(PAGE, CdOplockComplete)
45 #pragma alloc_text(PAGE, CdPrePostIrp)
51 IN PIRP_CONTEXT IrpContext
,
59 This routine enqueues the request packet specified by IrpContext to the
60 work queue associated with the FileSystemDeviceObject. This is a FSD
65 IrpContext - Pointer to the IrpContext to be queued to the Fsp.
67 Irp - I/O Request Packet.
78 ASSERT_IRP_CONTEXT( IrpContext
);
82 // Posting is a three step operation. First lock down any buffers
83 // in the Irp. Next cleanup the IrpContext for the post and finally
84 // add this to a workque.
87 CdPrePostIrp( IrpContext
, Irp
);
89 CdAddToWorkque( IrpContext
, Irp
);
92 // And return to our caller
95 return STATUS_PENDING
;
100 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
102 IN PIRP_CONTEXT IrpContext
,
110 This routine performs any necessary work before STATUS_PENDING is
111 returned with the Fsd thread. This routine is called within the
112 filesystem and by the oplock package.
116 Context - Pointer to the IrpContext to be queued to the Fsp
118 Irp - I/O Request Packet.
127 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
132 ASSERT_IRP_CONTEXT( IrpContext
);
136 // Case on the type of the operation.
139 switch (IrpContext
->MajorFunction
) {
144 // If called from the oplock package then there is an
145 // Fcb to possibly teardown. We will call the teardown
146 // routine and release the Fcb if still present. The cleanup
147 // code in create will know not to release this Fcb because
148 // we will clear the pointer.
151 if ((IrpContext
->TeardownFcb
!= NULL
) &&
152 *(IrpContext
->TeardownFcb
) != NULL
) {
154 CdTeardownStructures( IrpContext
, *(IrpContext
->TeardownFcb
), &RemovedFcb
);
158 CdReleaseFcb( IrpContext
, *(IrpContext
->TeardownFcb
) );
161 *(IrpContext
->TeardownFcb
) = NULL
;
162 IrpContext
->TeardownFcb
= NULL
;
168 // We need to lock the user's buffer, unless this is an MDL-read,
169 // in which case there is no user buffer.
174 if (!FlagOn( IrpContext
->MinorFunction
, IRP_MN_MDL
)) {
176 CdLockUserBuffer( IrpContext
, IrpSp
->Parameters
.Read
.Length
);
182 // We also need to check whether this is a query file operation.
185 case IRP_MJ_DIRECTORY_CONTROL
:
187 if (IrpContext
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
) {
189 CdLockUserBuffer( IrpContext
, IrpSp
->Parameters
.QueryDirectory
.Length
);
196 // Cleanup the IrpContext for the post.
199 SetFlag( IrpContext
->Flags
, IRP_CONTEXT_FLAG_MORE_PROCESSING
);
200 CdCleanupIrpContext( IrpContext
, TRUE
);
203 // Mark the Irp to show that we've already returned pending to the user.
206 IoMarkIrpPending( Irp
);
213 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
215 IN PIRP_CONTEXT IrpContext
,
223 This routine is called by the oplock package when an oplock break has
224 completed, allowing an Irp to resume execution. If the status in
225 the Irp is STATUS_SUCCESS, then we queue the Irp to the Fsp queue.
226 Otherwise we complete the Irp with the status in the Irp.
228 If we are completing due to an error then check if there is any
233 Irp - I/O Request Packet.
247 // Check on the return value in the Irp. If success then we
248 // are to post this request.
251 if (Irp
->IoStatus
.Status
== STATUS_SUCCESS
) {
254 // Check if there is any cleanup work to do.
257 switch (IrpContext
->MajorFunction
) {
262 // If called from the oplock package then there is an
263 // Fcb to possibly teardown. We will call the teardown
264 // routine and release the Fcb if still present. The cleanup
265 // code in create will know not to release this Fcb because
266 // we will clear the pointer.
269 if (IrpContext
->TeardownFcb
!= NULL
) {
271 CdTeardownStructures( IrpContext
, *(IrpContext
->TeardownFcb
), &RemovedFcb
);
275 CdReleaseFcb( IrpContext
, *(IrpContext
->TeardownFcb
) );
278 *(IrpContext
->TeardownFcb
) = NULL
;
279 IrpContext
->TeardownFcb
= NULL
;
286 // Insert the Irp context in the workqueue.
289 CdAddToWorkque( IrpContext
, Irp
);
292 // Otherwise complete the request.
297 CdCompleteRequest( IrpContext
, Irp
, Irp
->IoStatus
.Status
);
305 // Local support routine
310 IN PIRP_CONTEXT IrpContext
,
318 This routine is called to actually store the posted Irp to the Fsp
323 IrpContext - Pointer to the IrpContext to be queued to the Fsp
325 Irp - I/O Request Packet.
334 PVOLUME_DEVICE_OBJECT Vdo
;
336 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
339 // Check if this request has an associated file object, and thus volume
343 if (IrpSp
->FileObject
!= NULL
) {
346 Vdo
= CONTAINING_RECORD( IrpSp
->DeviceObject
,
347 VOLUME_DEVICE_OBJECT
,
351 // Check to see if this request should be sent to the overflow
352 // queue. If not, then send it off to an exworker thread.
355 KeAcquireSpinLock( &Vdo
->OverflowQueueSpinLock
, &SavedIrql
);
357 if (Vdo
->PostedRequestCount
> FSP_PER_DEVICE_THRESHOLD
) {
360 // We cannot currently respond to this IRP so we'll just enqueue it
361 // to the overflow queue on the volume.
364 InsertTailList( &Vdo
->OverflowQueue
,
365 &IrpContext
->WorkQueueItem
.List
);
367 Vdo
->OverflowQueueCount
+= 1;
369 KeReleaseSpinLock( &Vdo
->OverflowQueueSpinLock
, SavedIrql
);
376 // We are going to send this Irp to an ex worker thread so up
380 Vdo
->PostedRequestCount
+= 1;
382 KeReleaseSpinLock( &Vdo
->OverflowQueueSpinLock
, SavedIrql
);
390 ExInitializeWorkItem( &IrpContext
->WorkQueueItem
,
391 (PVOID
)CdFspDispatch
,/* ReactOS Change: GCC "assignment from incompatible pointer type" */
394 ExQueueWorkItem( &IrpContext
->WorkQueueItem
, CriticalWorkQueue
);