ReactOS  0.4.13-dev-73-gcfe54aa
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 Fat File
12  system.
13 
14 
15 --*/
16 
17 #include "fatprocs.h"
18 
19 //
20 // The following constant is the maximum number of ExWorkerThreads that we
21 // will allow to be servicing a particular target device at any one time.
22 //
23 
24 #define FSP_PER_DEVICE_THRESHOLD (2)
25 
26 #ifdef ALLOC_PRAGMA
27 #pragma alloc_text(PAGE, FatOplockComplete)
28 #pragma alloc_text(PAGE, FatPrePostIrp)
29 #pragma alloc_text(PAGE, FatFsdPostRequest)
30 #endif
31 
32 
33 VOID
34 NTAPI
37  IN PIRP Irp
38  )
39 
40 /*++
41 
42 Routine Description:
43 
44  This routine is called by the oplock package when an oplock break has
45  completed, allowing an Irp to resume execution. If the status in
46  the Irp is STATUS_SUCCESS, then we queue the Irp to the Fsp queue.
47  Otherwise we complete the Irp with the status in the Irp.
48 
49 Arguments:
50 
51  Context - Pointer to the IrpContext to be queued to the Fsp
52 
53  Irp - I/O Request Packet.
54 
55 Return Value:
56 
57  None.
58 
59 --*/
60 
61 {
62  PAGED_CODE();
63 
64  //
65  // Check on the return value in the Irp.
66  //
67 
68  if (Irp->IoStatus.Status == STATUS_SUCCESS) {
69 
70  //
71  // Insert the Irp context in the workqueue.
72  //
73 
75 
76  //
77  // Otherwise complete the request.
78  //
79 
80  } else {
81 
82  FatCompleteRequest( (PIRP_CONTEXT) Context, Irp, Irp->IoStatus.Status );
83  }
84 
85  return;
86 }
87 
88 
89 VOID
90 NTAPI
93  IN PIRP Irp
94  )
95 
96 /*++
97 
98 Routine Description:
99 
100  This routine performs any neccessary work before STATUS_PENDING is
101  returned with the Fsd thread. This routine is called within the
102  filesystem and by the oplock package.
103 
104 Arguments:
105 
106  Context - Pointer to the IrpContext to be queued to the Fsp
107 
108  Irp - I/O Request Packet.
109 
110 Return Value:
111 
112  None.
113 
114 --*/
115 
116 {
118  PIRP_CONTEXT IrpContext;
119 
120  PAGED_CODE();
121 
122  //
123  // If there is no Irp, we are done.
124  //
125 
126  if (Irp == NULL) {
127 
128  return;
129  }
130 
132 
133  IrpContext = (PIRP_CONTEXT) Context;
134 
135  //
136  // If there is a STACK FatIoContext pointer, clean and NULL it.
137  //
138 
139  if ((IrpContext->FatIoContext != NULL) &&
140  FlagOn(IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT)) {
141 
142  ClearFlag(IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT);
143  IrpContext->FatIoContext = NULL;
144  }
145 
146  //
147  // We need to lock the user's buffer, unless this is an MDL-read,
148  // in which case there is no user buffer.
149  //
150  // **** we need a better test than non-MDL (read or write)!
151 
152  if (IrpContext->MajorFunction == IRP_MJ_READ ||
153  IrpContext->MajorFunction == IRP_MJ_WRITE) {
154 
155  //
156  // If not an Mdl request, lock the user's buffer.
157  //
158 
159  if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {
160 
161  FatLockUserBuffer( IrpContext,
162  Irp,
163  (IrpContext->MajorFunction == IRP_MJ_READ) ?
165  (IrpContext->MajorFunction == IRP_MJ_READ) ?
166  IrpSp->Parameters.Read.Length : IrpSp->Parameters.Write.Length );
167  }
168 
169  //
170  // We also need to check whether this is a query file operation.
171  //
172 
173  } else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL
174  && IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
175 
176  FatLockUserBuffer( IrpContext,
177  Irp,
179  IrpSp->Parameters.QueryDirectory.Length );
180 
181  //
182  // We also need to check whether this is a query ea operation.
183  //
184 
185  } else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) {
186 
187  FatLockUserBuffer( IrpContext,
188  Irp,
190  IrpSp->Parameters.QueryEa.Length );
191 
192  //
193  // We also need to check whether this is a set ea operation.
194  //
195 
196  } else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) {
197 
198  FatLockUserBuffer( IrpContext,
199  Irp,
200  IoReadAccess,
201  IrpSp->Parameters.SetEa.Length );
202 
203  //
204  // These two FSCTLs use neither I/O, so check for them.
205  //
206 
207  } else if ((IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
208  (IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) &&
209  ((IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) ||
210  (IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS))) {
211 
212  FatLockUserBuffer( IrpContext,
213  Irp,
215  IrpSp->Parameters.FileSystemControl.OutputBufferLength );
216  }
217 
218  //
219  // Mark that we've already returned pending to the user
220  //
221 
223 
224  return;
225 }
226 
227 
228 NTSTATUS
230  IN PIRP_CONTEXT IrpContext,
231  IN PIRP Irp
232  )
233 
234 /*++
235 
236 Routine Description:
237 
238  This routine enqueues the request packet specified by IrpContext to the
239  Ex Worker threads. This is a FSD routine.
240 
241 Arguments:
242 
243  IrpContext - Pointer to the IrpContext to be queued to the Fsp
244 
245  Irp - I/O Request Packet, or NULL if it has already been completed.
246 
247 Return Value:
248 
249  STATUS_PENDING
250 
251 
252 --*/
253 
254 {
255  PAGED_CODE();
256 
258  NT_ASSERT( IrpContext->OriginatingIrp == Irp );
259 
260  FatPrePostIrp( IrpContext, Irp );
261 
262  FatAddToWorkque( IrpContext, Irp );
263 
264  //
265  // And return to our caller
266  //
267 
268  return STATUS_PENDING;
269 }
270 
271 
272 //
273 // Local support routine.
274 //
275 
276 VOID
278  IN PIRP_CONTEXT IrpContext,
279  IN PIRP Irp
280  )
281 
282 /*++
283 
284 Routine Description:
285 
286  This routine is called to acually store the posted Irp to the Fsp
287  workque.
288 
289 Arguments:
290 
291  IrpContext - Pointer to the IrpContext to be queued to the Fsp
292 
293  Irp - I/O Request Packet.
294 
295 Return Value:
296 
297  None.
298 
299 --*/
300 
301 {
302  KIRQL SavedIrql;
304 
306 
307  //
308  // Check if this request has an associated file object, and thus volume
309  // device object.
310  //
311 
312  if ( IrpSp->FileObject != NULL ) {
313 
315 
318  DeviceObject );
319 
320  //
321  // Check to see if this request should be sent to the overflow
322  // queue. If not, then send it off to an exworker thread.
323  //
324 
325  KeAcquireSpinLock( &Vdo->OverflowQueueSpinLock, &SavedIrql );
326 
328 
329  //
330  // We cannot currently respond to this IRP so we'll just enqueue it
331  // to the overflow queue on the volume.
332  //
333 
335  &IrpContext->WorkQueueItem.List );
336 
337  Vdo->OverflowQueueCount += 1;
338 
339  KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql );
340 
341  return;
342 
343  } else {
344 
345  //
346  // We are going to send this Irp to an ex worker thread so up
347  // the count.
348  //
349 
350  Vdo->PostedRequestCount += 1;
351 
352  KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql );
353  }
354  }
355 
356  //
357  // Send it off.....
358  //
359 
360  ExInitializeWorkItem( &IrpContext->WorkQueueItem,
362  IrpContext );
363 
364 #ifdef _MSC_VER
365 #pragma prefast( suppress:28159, "prefast indicates this is an obsolete API but it is ok for fastfat to keep using it." )
366 #endif
367  ExQueueWorkItem( &IrpContext->WorkQueueItem, CriticalWorkQueue );
368 
369  return;
370 }
371 
372 
#define IN
Definition: typedefs.h:38
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:717
IRP_CONTEXT * PIRP_CONTEXT
Definition: cdstruc.h:1217
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2621
_In_ PIRP Irp
Definition: csq.h:116
#define IRP_CONTEXT_STACK_IO_CONTEXT
Definition: ext2fs.h:1084
VOID FatLockUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp, IN LOCK_OPERATION Operation, IN ULONG BufferLength)
Definition: deviosup.c:3288
LONG NTSTATUS
Definition: precomp.h:26
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
#define InsertTailList(ListHead, Entry)
#define FSP_PER_DEVICE_THRESHOLD
Definition: workque.c:24
#define PAGED_CODE()
Definition: video.h:57
ULONG OverflowQueueCount
Definition: cdstruc.h:752
UCHAR KIRQL
Definition: env_spec_w32.h:591
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define IRP_MJ_SET_EA
VOID NTAPI FatOplockComplete(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:35
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 IRP_MJ_QUERY_EA
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4046
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
#define STATUS_PENDING
Definition: ntstatus.h:82
#define ARGUMENT_PRESENT(ArgumentPointer)
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2866
#define FSCTL_GET_RETRIEVAL_POINTERS
Definition: winioctl.h:95
#define IRP_MN_MDL
Definition: iotypes.h:4062
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
#define FSCTL_GET_VOLUME_BITMAP
Definition: winioctl.h:94
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
__volatile LONG PostedRequestCount
Definition: cdstruc.h:745
WORKER_THREAD_ROUTINE FatFspDispatch
Definition: fatprocs.h:2368
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define IRP_MJ_READ
Definition: rdpdr.c:46
KSPIN_LOCK OverflowQueueSpinLock
Definition: cdstruc.h:766
VOID FatAddToWorkque(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:277
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
return STATUS_SUCCESS
Definition: btrfs.c:2725
IoMarkIrpPending(Irp)
LIST_ENTRY OverflowQueue
Definition: cdstruc.h:760
VOID NTAPI FatPrePostIrp(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:91
#define NT_ASSERT
Definition: rtlfuncs.h:3312