ReactOS  0.4.15-dev-2979-gfd8baca
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
277 #ifdef __REACTOS__
278 NTAPI
279 #endif
281  IN PIRP_CONTEXT IrpContext,
282  IN PIRP Irp
283  )
284 
285 /*++
286 
287 Routine Description:
288 
289  This routine is called to acually store the posted Irp to the Fsp
290  workque.
291 
292 Arguments:
293 
294  IrpContext - Pointer to the IrpContext to be queued to the Fsp
295 
296  Irp - I/O Request Packet.
297 
298 Return Value:
299 
300  None.
301 
302 --*/
303 
304 {
305  KIRQL SavedIrql;
307 
309 
310  //
311  // Check if this request has an associated file object, and thus volume
312  // device object.
313  //
314 
315  if ( IrpSp->FileObject != NULL ) {
316 
318 
321  DeviceObject );
322 
323  //
324  // Check to see if this request should be sent to the overflow
325  // queue. If not, then send it off to an exworker thread.
326  //
327 
328  KeAcquireSpinLock( &Vdo->OverflowQueueSpinLock, &SavedIrql );
329 
331 
332  //
333  // We cannot currently respond to this IRP so we'll just enqueue it
334  // to the overflow queue on the volume.
335  //
336 
338  &IrpContext->WorkQueueItem.List );
339 
340  Vdo->OverflowQueueCount += 1;
341 
342  KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql );
343 
344  return;
345 
346  } else {
347 
348  //
349  // We are going to send this Irp to an ex worker thread so up
350  // the count.
351  //
352 
353  Vdo->PostedRequestCount += 1;
354 
355  KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql );
356  }
357  }
358 
359  //
360  // Send it off.....
361  //
362 
363  ExInitializeWorkItem( &IrpContext->WorkQueueItem,
365  IrpContext );
366 
367 #ifdef _MSC_VER
368 #pragma prefast( suppress:28159, "prefast indicates this is an obsolete API but it is ok for fastfat to keep using it." )
369 #endif
370  ExQueueWorkItem( &IrpContext->WorkQueueItem, CriticalWorkQueue );
371 
372  return;
373 }
374 
375 
#define IN
Definition: typedefs.h:39
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
IRP_CONTEXT * PIRP_CONTEXT
Definition: cdstruc.h:1211
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2633
#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:3276
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
ULONG OverflowQueueCount
Definition: cdstruc.h:746
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ PIRP Irp
Definition: csq.h:116
#define IRP_MJ_SET_EA
VOID NTAPI FatOplockComplete(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:35
#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:4403
#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:3223
#define FSCTL_GET_RETRIEVAL_POINTERS
Definition: winioctl.h:95
#define IRP_MN_MDL
Definition: iotypes.h:4419
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
#define FSCTL_GET_VOLUME_BITMAP
Definition: winioctl.h:94
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
__volatile LONG PostedRequestCount
Definition: cdstruc.h:739
WORKER_THREAD_ROUTINE FatFspDispatch
Definition: fatprocs.h:2380
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define IRP_MJ_READ
Definition: rdpdr.c:46
KSPIN_LOCK OverflowQueueSpinLock
Definition: cdstruc.h:760
VOID FatAddToWorkque(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:280
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
IoMarkIrpPending(Irp)
LIST_ENTRY OverflowQueue
Definition: cdstruc.h:754
VOID NTAPI FatPrePostIrp(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:91
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3310