1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7     FspDisp.c
8 
9 Abstract:
10 
11     This module implements the main dispatch procedure/thread for the Fat
12     Fsp
13 
14 
15 --*/
16 
17 #include "fatprocs.h"
18 
19 //
20 //  Internal support routine, spinlock wrapper.
21 //
22 
23 PVOID
24 FatRemoveOverflowEntry (
25     IN PVOLUME_DEVICE_OBJECT VolDo
26     );
27 
28 //
29 //  Define our local debug trace level
30 //
31 
32 #define Dbg                              (DEBUG_TRACE_FSP_DISPATCHER)
33 
34 #ifdef ALLOC_PRAGMA
35 #pragma alloc_text(PAGE, FatFspDispatch)
36 #endif
37 
38 
39 VOID
40 NTAPI
41 FatFspDispatch (
42     _In_ PVOID Context
43     )
44 
45 /*++
46 
47 Routine Description:
48 
49     This is the main FSP thread routine that is executed to receive
50     and dispatch IRP requests.  Each FSP thread begins its execution here.
51     There is one thread created at system initialization time and subsequent
52     threads created as needed.
53 
54 Arguments:
55 
56 
57     Context - Supplies the thread id.
58 
59 Return Value:
60 
61     None - This routine never exits
62 
63 --*/
64 
65 {
66     NTSTATUS Status = STATUS_SUCCESS;
67 
68 
69     PIRP Irp;
70     PIRP_CONTEXT IrpContext;
71     PIO_STACK_LOCATION IrpSp;
72     BOOLEAN VcbDeleted;
73     BOOLEAN  ExceptionCompletedIrp = FALSE;
74 
75     PVOLUME_DEVICE_OBJECT VolDo;
76 
77     UCHAR MajorFunction = 0;
78 
79     PAGED_CODE();
80 
81     IrpContext = (PIRP_CONTEXT)Context;
82 
83     Irp = IrpContext->OriginatingIrp;
84 
85     IrpSp = IoGetCurrentIrpStackLocation( Irp );
86 
87     //
88     //  Now because we are the Fsp we will force the IrpContext to
89     //  indicate true on Wait.
90     //
91 
92     SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP);
93 
94     //
95     //  If this request has an associated volume device object, remember it.
96     //
97 
98     if ( IrpSp->FileObject != NULL ) {
99 
100         VolDo = CONTAINING_RECORD( IrpSp->DeviceObject,
101                                    VOLUME_DEVICE_OBJECT,
102                                    DeviceObject );
103     } else {
104 
105         VolDo = NULL;
106     }
107 
108     //
109     //  Now case on the function code.  For each major function code,
110     //  either call the appropriate FSP routine or case on the minor
111     //  function and then call the FSP routine.  The FSP routine that
112     //  we call is responsible for completing the IRP, and not us.
113     //  That way the routine can complete the IRP and then continue
114     //  post processing as required.  For example, a read can be
115     //  satisfied right away and then read can be done.
116     //
117     //  We'll do all of the work within an exception handler that
118     //  will be invoked if ever some underlying operation gets into
119     //  trouble (e.g., if FatReadSectorsSync has trouble).
120     //
121 
122     while ( TRUE ) {
123 
124         ExceptionCompletedIrp = FALSE;
125 
126         DebugTrace(0, Dbg, "FatFspDispatch: Irp = %p\n", Irp);
127 
128         //
129         //  If this Irp was top level, note it in our thread local storage.
130         //
131 
132         FsRtlEnterFileSystem();
133 
134         if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) ) {
135 
136             IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );
137 
138         } else {
139 
140             IoSetTopLevelIrp( Irp );
141         }
142 
143         MajorFunction = IrpContext->MajorFunction;
144 
145         _SEH2_TRY {
146 
147             switch ( MajorFunction ) {
148 
149                 //
150                 //  For Create Operation,
151                 //
152 
153                 case IRP_MJ_CREATE:
154 
155                     Status = FatCommonCreate( IrpContext, Irp );
156                     break;
157 
158                 //
159                 //  For close operations.  We do a little kludge here in case
160                 //  this close causes a volume to go away.  It will NULL the
161                 //  VolDo local variable so that we will not try to look at
162                 //  the overflow queue.
163                 //
164 
165                 case IRP_MJ_CLOSE:
166 
167                 {
168                     PVCB Vcb;
169                     PFCB Fcb;
170                     PCCB Ccb;
171                     TYPE_OF_OPEN TypeOfOpen;
172 
173                     //
174                     //  Extract and decode the file object
175                     //
176 
177                     TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );
178 
179                     //
180                     //  Do the close.  We have a slightly different format
181                     //  for this call because of the async closes.
182                     //
183 
184                     Status = FatCommonClose( Vcb,
185                                              Fcb,
186                                              Ccb,
187                                              TypeOfOpen,
188                                              TRUE,
189                                              TRUE,
190                                              &VcbDeleted );
191 
192                     //
193                     //  If the VCB was deleted, do not try to access it later.
194                     //
195 
196                     if (VcbDeleted) {
197 
198                         VolDo = NULL;
199                     }
200 
201                     NT_ASSERT(Status == STATUS_SUCCESS);
202 
203                     FatCompleteRequest( IrpContext, Irp, Status );
204 
205                     break;
206                 }
207 
208                 //
209                 //  For read operations
210                 //
211 
212                 case IRP_MJ_READ:
213 
214                     (VOID) FatCommonRead( IrpContext, Irp );
215                     break;
216 
217                 //
218                 //  For write operations,
219                 //
220 
221                 case IRP_MJ_WRITE:
222 
223                     (VOID) FatCommonWrite( IrpContext, Irp );
224                     break;
225 
226                 //
227                 //  For Query Information operations,
228                 //
229 
230                 case IRP_MJ_QUERY_INFORMATION:
231 
232                     (VOID) FatCommonQueryInformation( IrpContext, Irp );
233                     break;
234 
235                 //
236                 //  For Set Information operations,
237                 //
238 
239                 case IRP_MJ_SET_INFORMATION:
240 
241                     (VOID) FatCommonSetInformation( IrpContext, Irp );
242                     break;
243 
244                 //
245                 //  For Query EA operations,
246                 //
247 
248                 case IRP_MJ_QUERY_EA:
249 
250                     (VOID) FatCommonQueryEa( IrpContext, Irp );
251                     break;
252 
253                 //
254                 //  For Set EA operations,
255                 //
256 
257                 case IRP_MJ_SET_EA:
258 
259                     (VOID) FatCommonSetEa( IrpContext, Irp );
260                     break;
261 
262                 //
263                 //  For Flush buffers operations,
264                 //
265 
266                 case IRP_MJ_FLUSH_BUFFERS:
267 
268                     (VOID) FatCommonFlushBuffers( IrpContext, Irp );
269                     break;
270 
271                 //
272                 //  For Query Volume Information operations,
273                 //
274 
275                 case IRP_MJ_QUERY_VOLUME_INFORMATION:
276 
277                     (VOID) FatCommonQueryVolumeInfo( IrpContext, Irp );
278                     break;
279 
280                 //
281                 //  For Set Volume Information operations,
282                 //
283 
284                 case IRP_MJ_SET_VOLUME_INFORMATION:
285 
286                     (VOID) FatCommonSetVolumeInfo( IrpContext, Irp );
287                     break;
288 
289                 //
290                 //  For File Cleanup operations,
291                 //
292 
293                 case IRP_MJ_CLEANUP:
294 
295                     (VOID) FatCommonCleanup( IrpContext, Irp );
296                     break;
297 
298                 //
299                 //  For Directory Control operations,
300                 //
301 
302                 case IRP_MJ_DIRECTORY_CONTROL:
303 
304                     (VOID) FatCommonDirectoryControl( IrpContext, Irp );
305                     break;
306 
307                 //
308                 //  For File System Control operations,
309                 //
310 
311                 case IRP_MJ_FILE_SYSTEM_CONTROL:
312 
313                     (VOID) FatCommonFileSystemControl( IrpContext, Irp );
314                     break;
315 
316                 //
317                 //  For Lock Control operations,
318                 //
319 
320                 case IRP_MJ_LOCK_CONTROL:
321 
322                     (VOID) FatCommonLockControl( IrpContext, Irp );
323                     break;
324 
325                 //
326                 //  For Device Control operations,
327                 //
328 
329                 case IRP_MJ_DEVICE_CONTROL:
330 
331                     (VOID) FatCommonDeviceControl( IrpContext, Irp );
332                     break;
333 
334                 //
335                 //  For the Shutdown operation,
336                 //
337 
338                 case IRP_MJ_SHUTDOWN:
339 
340                     (VOID) FatCommonShutdown( IrpContext, Irp );
341                     break;
342 
343                 //
344                 //  For plug and play operations.
345                 //
346 
347                 case IRP_MJ_PNP:
348 
349                     //
350                     //  I don't believe this should ever occur, but allow for the unexpected.
351                     //
352 
353                     (VOID) FatCommonPnp( IrpContext, Irp );
354                     break;
355 
356                 //
357                 //  For any other major operations, return an invalid
358                 //  request.
359                 //
360 
361                 default:
362 
363                     FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
364                     break;
365 
366             }
367 
368         } _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
369 
370             //
371             //  We had some trouble trying to perform the requested
372             //  operation, so we'll abort the I/O request with
373             //  the error status that we get back from the
374             //  execption code.
375             //
376 
377             (VOID) FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
378             ExceptionCompletedIrp = TRUE;
379         } _SEH2_END;
380 
381         IoSetTopLevelIrp( NULL );
382 
383         FsRtlExitFileSystem();
384 
385 
386         if (MajorFunction == IRP_MJ_CREATE && !ExceptionCompletedIrp && Status != STATUS_PENDING) {
387 
388             //
389             // Creates are completed here. IrpContext is also freed here.
390             //
391 
392             FatCompleteRequest( IrpContext, Irp, Status );
393         }
394 
395         //
396         //  If there are any entries on this volume's overflow queue, service
397         //  them.
398         //
399 
400         if ( VolDo != NULL ) {
401 
402             PVOID Entry;
403 
404             //
405             //  We have a volume device object so see if there is any work
406             //  left to do in its overflow queue.
407             //
408 
409             Entry = FatRemoveOverflowEntry( VolDo );
410 
411             //
412             //  There wasn't an entry, break out of the loop and return to
413             //  the Ex Worker thread.
414             //
415 
416             if ( Entry == NULL ) {
417 
418                 break;
419             }
420 
421             //
422             //  Extract the IrpContext, Irp, and IrpSp, and loop.
423             //
424 
425             IrpContext = CONTAINING_RECORD( Entry,
426                                             IRP_CONTEXT,
427                                             WorkQueueItem.List );
428 
429             SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP);
430 
431             Irp = IrpContext->OriginatingIrp;
432 
433             IrpSp = IoGetCurrentIrpStackLocation( Irp );
434 
435             continue;
436 
437         } else {
438 
439             break;
440         }
441     }
442 
443     return;
444 }
445 
446 
447 //
448 //  Internal support routine, spinlock wrapper.
449 //
450 
451 PVOID
452 FatRemoveOverflowEntry (
453     IN PVOLUME_DEVICE_OBJECT VolDo
454     )
455 {
456     PVOID Entry;
457     KIRQL SavedIrql;
458 
459     KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql );
460 
461     if (VolDo->OverflowQueueCount > 0) {
462 
463         //
464         //  There is overflow work to do in this volume so we'll
465         //  decrement the Overflow count, dequeue the IRP, and release
466         //  the Event
467         //
468 
469         VolDo->OverflowQueueCount -= 1;
470 
471         Entry = RemoveHeadList( &VolDo->OverflowQueue );
472 
473     } else {
474 
475         VolDo->PostedRequestCount -= 1;
476 
477         Entry = NULL;
478     }
479 
480     KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql );
481 
482     return Entry;
483 }
484 
485 
486