ReactOS  0.4.13-dev-544-gede3fdd
workque.c
Go to the documentation of this file.
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
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_)
51 CdFsdPostRequest (
52  _Inout_ PIRP_CONTEXT IrpContext,
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 
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,
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 {
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_)
227 VOID
228 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
229 CdOplockComplete (
230  _Inout_ PIRP_CONTEXT IrpContext,
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 
320 //
321 // Local support routine
322 //
323 
324 VOID
326  _Inout_ PIRP_CONTEXT IrpContext,
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 {
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 
WORKER_THREAD_ROUTINE CdFspDispatch
Definition: cdprocs.h:2050
#define TRUE
Definition: types.h:120
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:717
_In_ PIRP Irp
Definition: csq.h:116
#define IRP_CONTEXT_FLAG_MORE_PROCESSING
Definition: cdstruc.h:1220
LONG NTSTATUS
Definition: precomp.h:26
#define CdReleaseFcb(IC, F)
Definition: cdprocs.h:1017
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
#define InsertTailList(ListHead, Entry)
#define PAGED_CODE()
Definition: video.h:57
ULONG OverflowQueueCount
Definition: cdstruc.h:752
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define _Analysis_assume_lock_held_(lock)
Definition: no_sal2.h:682
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:249
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
#define STATUS_PENDING
Definition: ntstatus.h:82
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2866
#define _Inout_
Definition: no_sal2.h:244
_Requires_lock_held_(_Global_critical_region_)
Definition: workque.c:49
#define IRP_MN_MDL
Definition: iotypes.h:4062
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define ASSERT_IRP(I)
Definition: cddata.h:251
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
__volatile LONG PostedRequestCount
Definition: cdstruc.h:745
VOID CdCleanupIrpContext(_In_ PIRP_CONTEXT IrpContext, _In_ BOOLEAN Post)
Definition: strucsup.c:1733
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define CdLockUserBuffer(IC, BL, OP)
Definition: cdprocs.h:398
KSPIN_LOCK OverflowQueueSpinLock
Definition: cdstruc.h:766
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
return STATUS_SUCCESS
Definition: btrfs.c:2777
IoMarkIrpPending(Irp)
LIST_ENTRY OverflowQueue
Definition: cdstruc.h:760
VOID CdAddToWorkque(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: workque.c:325
#define FSP_PER_DEVICE_THRESHOLD
Definition: workque.c:30