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 _Inout_ PIRP_CONTEXT IrpContext
,
43 #pragma alloc_text(PAGE, CdFsdPostRequest)
44 #pragma alloc_text(PAGE, CdOplockComplete)
45 #pragma alloc_text(PAGE, CdPrePostIrp)
49 _Requires_lock_held_(_Global_critical_region_
)
52 _Inout_ PIRP_CONTEXT IrpContext
,
60 This routine enqueues the request packet specified by IrpContext to the
61 work queue associated with the FileSystemDeviceObject. This is a FSD
66 IrpContext - Pointer to the IrpContext to be queued to the Fsp.
68 Irp - I/O Request Packet.
79 ASSERT_IRP_CONTEXT( IrpContext
);
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.
88 CdPrePostIrp( IrpContext
, Irp
);
90 CdAddToWorkque( IrpContext
, Irp
);
93 // And return to our caller
96 return STATUS_PENDING
;
101 _Requires_lock_held_(_Global_critical_region_
)
103 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
105 _Inout_ PIRP_CONTEXT IrpContext
,
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.
119 Context - Pointer to the IrpContext to be queued to the Fsp
121 Irp - I/O Request Packet.
130 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
135 ASSERT_IRP_CONTEXT( IrpContext
);
139 // Case on the type of the operation.
142 switch (IrpContext
->MajorFunction
) {
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.
154 if ((IrpContext
->TeardownFcb
!= NULL
) &&
155 *(IrpContext
->TeardownFcb
) != NULL
) {
157 CdTeardownStructures( IrpContext
, *(IrpContext
->TeardownFcb
), &RemovedFcb
);
161 _Analysis_assume_lock_held_((*IrpContext
->TeardownFcb
)->FcbNonpaged
->FcbResource
);
162 CdReleaseFcb( IrpContext
, *(IrpContext
->TeardownFcb
) );
165 *(IrpContext
->TeardownFcb
) = NULL
;
166 IrpContext
->TeardownFcb
= NULL
;
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.
178 if (!FlagOn( IrpContext
->MinorFunction
, IRP_MN_MDL
)) {
180 CdLockUserBuffer( IrpContext
, IrpSp
->Parameters
.Read
.Length
, IoWriteAccess
);
187 if (!FlagOn( IrpContext
->MinorFunction
, IRP_MN_MDL
)) {
189 CdLockUserBuffer( IrpContext
, IrpSp
->Parameters
.Read
.Length
, IoReadAccess
);
195 // We also need to check whether this is a query file operation.
198 case IRP_MJ_DIRECTORY_CONTROL
:
200 if (IrpContext
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
) {
202 CdLockUserBuffer( IrpContext
, IrpSp
->Parameters
.QueryDirectory
.Length
, IoWriteAccess
);
209 // Cleanup the IrpContext for the post.
212 SetFlag( IrpContext
->Flags
, IRP_CONTEXT_FLAG_MORE_PROCESSING
);
213 CdCleanupIrpContext( IrpContext
, TRUE
);
216 // Mark the Irp to show that we've already returned pending to the user.
219 IoMarkIrpPending( Irp
);
226 _Requires_lock_held_(_Global_critical_region_
)
228 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
230 _Inout_ PIRP_CONTEXT IrpContext
,
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.
243 If we are completing due to an error then check if there is any
248 Irp - I/O Request Packet.
262 // Check on the return value in the Irp. If success then we
263 // are to post this request.
266 if (Irp
->IoStatus
.Status
== STATUS_SUCCESS
) {
269 // Check if there is any cleanup work to do.
272 switch (IrpContext
->MajorFunction
) {
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.
284 if (IrpContext
->TeardownFcb
!= NULL
) {
286 CdTeardownStructures( IrpContext
, *(IrpContext
->TeardownFcb
), &RemovedFcb
);
290 _Analysis_assume_lock_held_((*IrpContext
->TeardownFcb
)->FcbNonpaged
->FcbResource
);
291 CdReleaseFcb( IrpContext
, *(IrpContext
->TeardownFcb
) );
294 *(IrpContext
->TeardownFcb
) = NULL
;
295 IrpContext
->TeardownFcb
= NULL
;
302 // Insert the Irp context in the workqueue.
305 CdAddToWorkque( IrpContext
, Irp
);
308 // Otherwise complete the request.
313 CdCompleteRequest( IrpContext
, Irp
, Irp
->IoStatus
.Status
);
321 // Local support routine
326 _Inout_ PIRP_CONTEXT IrpContext
,
334 This routine is called to acually store the posted Irp to the Fsp
339 IrpContext - Pointer to the IrpContext to be queued to the Fsp
341 Irp - I/O Request Packet.
350 PVOLUME_DEVICE_OBJECT Vdo
;
352 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
355 // Check if this request has an associated file object, and thus volume
359 if (IrpSp
->FileObject
!= NULL
) {
362 Vdo
= CONTAINING_RECORD( IrpSp
->DeviceObject
,
363 VOLUME_DEVICE_OBJECT
,
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.
371 KeAcquireSpinLock( &Vdo
->OverflowQueueSpinLock
, &SavedIrql
);
373 if (Vdo
->PostedRequestCount
> FSP_PER_DEVICE_THRESHOLD
) {
376 // We cannot currently respond to this IRP so we'll just enqueue it
377 // to the overflow queue on the volume.
380 InsertTailList( &Vdo
->OverflowQueue
,
381 &IrpContext
->WorkQueueItem
.List
);
383 Vdo
->OverflowQueueCount
+= 1;
385 KeReleaseSpinLock( &Vdo
->OverflowQueueSpinLock
, SavedIrql
);
392 // We are going to send this Irp to an ex worker thread so up
396 Vdo
->PostedRequestCount
+= 1;
398 KeReleaseSpinLock( &Vdo
->OverflowQueueSpinLock
, SavedIrql
);
407 #pragma prefast(suppress:28155, "the function prototype is correct")
409 ExInitializeWorkItem( &IrpContext
->WorkQueueItem
,
410 (PVOID
)CdFspDispatch
,/* ReactOS Change: GCC "assignment from incompatible pointer type" */
414 #pragma prefast(suppress: 28159, "prefast believes this routine is obsolete, but it is ok for CDFS to continue using it")
416 ExQueueWorkItem( &IrpContext
->WorkQueueItem
, CriticalWorkQueue
);