ReactOS 0.4.16-dev-311-g9382aa2
workque.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 WorkQue.c
8
9Abstract:
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
33VOID
37 IN PIRP Irp
38 )
39
40/*++
41
42Routine 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
49Arguments:
50
51 Context - Pointer to the IrpContext to be queued to the Fsp
52
53 Irp - I/O Request Packet.
54
55Return 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
89VOID
93 IN PIRP Irp
94 )
95
96/*++
97
98Routine 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
104Arguments:
105
106 Context - Pointer to the IrpContext to be queued to the Fsp
107
108 Irp - I/O Request Packet.
109
110Return 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,
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,
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) &&
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
230 IN PIRP_CONTEXT IrpContext,
231 IN PIRP Irp
232 )
233
234/*++
235
236Routine Description:
237
238 This routine enqueues the request packet specified by IrpContext to the
239 Ex Worker threads. This is a FSD routine.
240
241Arguments:
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
247Return 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
276VOID
277#ifdef __REACTOS__
278NTAPI
279#endif
281 IN PIRP_CONTEXT IrpContext,
282 IN PIRP Irp
283 )
284
285/*++
286
287Routine Description:
288
289 This routine is called to acually store the posted Irp to the Fsp
290 workque.
291
292Arguments:
293
294 IrpContext - Pointer to the IrpContext to be queued to the Fsp
295
296 Irp - I/O Request Packet.
297
298Return 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
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
LONG NTSTATUS
Definition: precomp.h:26
#define FSP_PER_DEVICE_THRESHOLD
Definition: workque.c:30
IRP_CONTEXT * PIRP_CONTEXT
Definition: cdstruc.h:1211
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define NULL
Definition: types.h:112
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define InsertTailList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define IRP_CONTEXT_STACK_IO_CONTEXT
Definition: ext2fs.h:1093
VOID FatLockUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp, IN LOCK_OPERATION Operation, IN ULONG BufferLength)
Definition: deviosup.c:3276
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
VOID NTAPI FatPrePostIrp(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:91
VOID NTAPI FatOplockComplete(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:35
VOID FatAddToWorkque(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:280
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2634
WORKER_THREAD_ROUTINE FatFspDispatch
Definition: fatprocs.h:2381
IoMarkIrpPending(Irp)
#define ARGUMENT_PRESENT(ArgumentPointer)
#define FSCTL_GET_RETRIEVAL_POINTERS
Definition: winioctl.h:744
#define FSCTL_GET_VOLUME_BITMAP
Definition: winioctl.h:743
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _IO_STACK_LOCATION::@3979::@3984 Write
struct _IO_STACK_LOCATION::@3979::@3990 QueryEa
struct _IO_STACK_LOCATION::@3979::@3983 Read
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
struct _IO_STACK_LOCATION::@3979::@3994 FileSystemControl
union _IO_STACK_LOCATION::@1580 Parameters
struct _IO_STACK_LOCATION::@3979::@3985 QueryDirectory
struct _IO_STACK_LOCATION::@3979::@3991 SetEa
__volatile LONG PostedRequestCount
Definition: cdstruc.h:739
KSPIN_LOCK OverflowQueueSpinLock
Definition: cdstruc.h:760
LIST_ENTRY OverflowQueue
Definition: cdstruc.h:754
ULONG OverflowQueueCount
Definition: cdstruc.h:746
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ CriticalWorkQueue
Definition: extypes.h:189
#define IRP_MJ_QUERY_EA
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4403
#define IRP_MJ_SET_EA
#define IRP_MN_MDL
Definition: iotypes.h:4419
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864
#define NT_ASSERT
Definition: rtlfuncs.h:3327