[FASTFAT_NEW] Fix build with FASTFATDBG set
[reactos.git] / drivers / filesystems / fastfat_new / workque.c
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 #endif
30
31 \f
32 VOID
33 NTAPI
34 FatOplockComplete (
35 IN PVOID Context,
36 IN PIRP Irp
37 )
38
39 /*++
40
41 Routine Description:
42
43 This routine is called by the oplock package when an oplock break has
44 completed, allowing an Irp to resume execution. If the status in
45 the Irp is STATUS_SUCCESS, then we queue the Irp to the Fsp queue.
46 Otherwise we complete the Irp with the status in the Irp.
47
48 Arguments:
49
50 Context - Pointer to the IrpContext to be queued to the Fsp
51
52 Irp - I/O Request Packet.
53
54 Return Value:
55
56 None.
57
58 --*/
59
60 {
61 //
62 // Check on the return value in the Irp.
63 //
64
65 if (Irp->IoStatus.Status == STATUS_SUCCESS) {
66
67 //
68 // Insert the Irp context in the workqueue.
69 //
70
71 FatAddToWorkque( (PIRP_CONTEXT) Context, Irp );
72
73 //
74 // Otherwise complete the request.
75 //
76
77 } else {
78
79 FatCompleteRequest( (PIRP_CONTEXT) Context, Irp, Irp->IoStatus.Status );
80 }
81
82 return;
83 }
84
85 \f
86 VOID
87 NTAPI
88 FatPrePostIrp (
89 IN PVOID Context,
90 IN PIRP Irp
91 )
92
93 /*++
94
95 Routine Description:
96
97 This routine performs any neccessary work before STATUS_PENDING is
98 returned with the Fsd thread. This routine is called within the
99 filesystem and by the oplock package.
100
101 Arguments:
102
103 Context - Pointer to the IrpContext to be queued to the Fsp
104
105 Irp - I/O Request Packet.
106
107 Return Value:
108
109 None.
110
111 --*/
112
113 {
114 PIO_STACK_LOCATION IrpSp;
115 PIRP_CONTEXT IrpContext;
116
117 //
118 // If there is no Irp, we are done.
119 //
120
121 if (Irp == NULL) {
122
123 return;
124 }
125
126 IrpSp = IoGetCurrentIrpStackLocation( Irp );
127
128 IrpContext = (PIRP_CONTEXT) Context;
129
130 //
131 // If there is a STACK FatIoContext pointer, clean and NULL it.
132 //
133
134 if ((IrpContext->FatIoContext != NULL) &&
135 FlagOn(IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT)) {
136
137 ClearFlag(IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT);
138 IrpContext->FatIoContext = NULL;
139 }
140
141 //
142 // We need to lock the user's buffer, unless this is an MDL-read,
143 // in which case there is no user buffer.
144 //
145 // **** we need a better test than non-MDL (read or write)!
146
147 if (IrpContext->MajorFunction == IRP_MJ_READ ||
148 IrpContext->MajorFunction == IRP_MJ_WRITE) {
149
150 //
151 // If not an Mdl request, lock the user's buffer.
152 //
153
154 if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {
155
156 FatLockUserBuffer( IrpContext,
157 Irp,
158 (IrpContext->MajorFunction == IRP_MJ_READ) ?
159 IoWriteAccess : IoReadAccess,
160 (IrpContext->MajorFunction == IRP_MJ_READ) ?
161 IrpSp->Parameters.Read.Length : IrpSp->Parameters.Write.Length );
162 }
163
164 //
165 // We also need to check whether this is a query file operation.
166 //
167
168 } else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL
169 && IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
170
171 FatLockUserBuffer( IrpContext,
172 Irp,
173 IoWriteAccess,
174 IrpSp->Parameters.QueryDirectory.Length );
175
176 //
177 // We also need to check whether this is a query ea operation.
178 //
179
180 } else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) {
181
182 FatLockUserBuffer( IrpContext,
183 Irp,
184 IoWriteAccess,
185 IrpSp->Parameters.QueryEa.Length );
186
187 //
188 // We also need to check whether this is a set ea operation.
189 //
190
191 } else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) {
192
193 FatLockUserBuffer( IrpContext,
194 Irp,
195 IoReadAccess,
196 IrpSp->Parameters.SetEa.Length );
197
198 //
199 // These two FSCTLs use neither I/O, so check for them.
200 //
201
202 } else if ((IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
203 (IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) &&
204 ((IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) ||
205 (IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS))) {
206
207 FatLockUserBuffer( IrpContext,
208 Irp,
209 IoWriteAccess,
210 IrpSp->Parameters.FileSystemControl.OutputBufferLength );
211 }
212
213 //
214 // Mark that we've already returned pending to the user
215 //
216
217 IoMarkIrpPending( Irp );
218
219 return;
220 }
221
222 \f
223 NTSTATUS
224 FatFsdPostRequest(
225 IN PIRP_CONTEXT IrpContext,
226 IN PIRP Irp
227 )
228
229 /*++
230
231 Routine Description:
232
233 This routine enqueues the request packet specified by IrpContext to the
234 Ex Worker threads. This is a FSD routine.
235
236 Arguments:
237
238 IrpContext - Pointer to the IrpContext to be queued to the Fsp
239
240 Irp - I/O Request Packet, or NULL if it has already been completed.
241
242 Return Value:
243
244 STATUS_PENDING
245
246
247 --*/
248
249 {
250 ASSERT( ARGUMENT_PRESENT(Irp) );
251 ASSERT( IrpContext->OriginatingIrp == Irp );
252
253 FatPrePostIrp( IrpContext, Irp );
254
255 FatAddToWorkque( IrpContext, Irp );
256
257 //
258 // And return to our caller
259 //
260
261 return STATUS_PENDING;
262 }
263
264 \f
265 //
266 // Local support routine.
267 //
268
269 VOID
270 FatAddToWorkque (
271 IN PIRP_CONTEXT IrpContext,
272 IN PIRP Irp
273 )
274
275 /*++
276
277 Routine Description:
278
279 This routine is called to acually store the posted Irp to the Fsp
280 workque.
281
282 Arguments:
283
284 IrpContext - Pointer to the IrpContext to be queued to the Fsp
285
286 Irp - I/O Request Packet.
287
288 Return Value:
289
290 None.
291
292 --*/
293
294 {
295 KIRQL SavedIrql;
296 PIO_STACK_LOCATION IrpSp;
297
298 IrpSp = IoGetCurrentIrpStackLocation( Irp );
299
300 //
301 // Check if this request has an associated file object, and thus volume
302 // device object.
303 //
304
305 if ( IrpSp->FileObject != NULL ) {
306
307 PVOLUME_DEVICE_OBJECT Vdo;
308
309 Vdo = CONTAINING_RECORD( IrpSp->DeviceObject,
310 VOLUME_DEVICE_OBJECT,
311 DeviceObject );
312
313 //
314 // Check to see if this request should be sent to the overflow
315 // queue. If not, then send it off to an exworker thread.
316 //
317
318 KeAcquireSpinLock( &Vdo->OverflowQueueSpinLock, &SavedIrql );
319
320 if ( Vdo->PostedRequestCount > FSP_PER_DEVICE_THRESHOLD) {
321
322 //
323 // We cannot currently respond to this IRP so we'll just enqueue it
324 // to the overflow queue on the volume.
325 //
326
327 InsertTailList( &Vdo->OverflowQueue,
328 &IrpContext->WorkQueueItem.List );
329
330 Vdo->OverflowQueueCount += 1;
331
332 KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql );
333
334 return;
335
336 } else {
337
338 //
339 // We are going to send this Irp to an ex worker thread so up
340 // the count.
341 //
342
343 Vdo->PostedRequestCount += 1;
344
345 KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql );
346 }
347 }
348
349 //
350 // Send it off.....
351 //
352
353 ExInitializeWorkItem( &IrpContext->WorkQueueItem,
354 FatFspDispatch,
355 IrpContext );
356
357 ExQueueWorkItem( &IrpContext->WorkQueueItem, CriticalWorkQueue );
358
359 return;
360 }
361
362