xref: /reactos/drivers/filesystems/cdfs/fspdisp.c (revision 81db5e1d)
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 Cdfs
12     Fsp
13 
14 
15 --*/
16 
17 #include "cdprocs.h"
18 
19 //
20 //  The Bug check file id for this module
21 //
22 
23 #define BugCheckFileId                   (CDFS_BUG_CHECK_FSPDISP)
24 
25 
26 VOID
27 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
28 CdFspDispatch (
29     _In_ PVOID Context
30     )
31 
32 /*++
33 
34 Routine Description:
35 
36     This is the main FSP thread routine that is executed to receive
37     and dispatch IRP requests.  Each FSP thread begins its execution here.
38     There is one thread created at system initialization time and subsequent
39     threads created as needed.
40 
41 Arguments:
42 
43     IrpContext - IrpContext for a request to process.
44 
45 Return Value:
46 
47     None
48 
49 --*/
50 
51 {
52     THREAD_CONTEXT ThreadContext = {0};
53     PIRP_CONTEXT IrpContext = Context;
54     NTSTATUS Status;
55 
56     PIRP Irp = IrpContext->Irp;
57     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
58 
59     PVOLUME_DEVICE_OBJECT VolDo = NULL;
60 
61     //
62     //  If this request has an associated volume device object, remember it.
63     //
64 
65     if (IrpSp->FileObject != NULL) {
66 
67         VolDo = CONTAINING_RECORD( IrpSp->DeviceObject,
68                                    VOLUME_DEVICE_OBJECT,
69                                    DeviceObject );
70     }
71 
72     //
73     //  Now case on the function code.  For each major function code,
74     //  either call the appropriate worker routine.  This routine that
75     //  we call is responsible for completing the IRP, and not us.
76     //  That way the routine can complete the IRP and then continue
77     //  post processing as required.  For example, a read can be
78     //  satisfied right away and then read can be done.
79     //
80     //  We'll do all of the work within an exception handler that
81     //  will be invoked if ever some underlying operation gets into
82     //  trouble.
83     //
84 
85     while ( TRUE ) {
86 
87         //
88         //  Set all the flags indicating we are in the Fsp.
89         //
90 
91         SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS );
92 
93         FsRtlEnterFileSystem();
94 
95         CdSetThreadContext( IrpContext, &ThreadContext );
96 
97         while (TRUE) {
98 
99             _SEH2_TRY {
100 
101                 //
102                 //  Reinitialize for the next try at completing this
103                 //  request.
104                 //
105 
106                 Status =
107                 IrpContext->ExceptionStatus = STATUS_SUCCESS;
108 
109                 //
110                 //  Initialize the Io status field in the Irp.
111                 //
112 
113                 Irp->IoStatus.Status = STATUS_SUCCESS;
114                 Irp->IoStatus.Information = 0;
115 
116                 //
117                 //  Case on the major irp code.
118                 //
119 
120                 switch (IrpContext->MajorFunction) {
121 
122                 case IRP_MJ_CREATE :
123 
124                     CdCommonCreate( IrpContext, Irp );
125                     break;
126 
127                 case IRP_MJ_CLOSE :
128 
129                     NT_ASSERT( FALSE );
130                     break;
131 
132                 case IRP_MJ_READ :
133 
134                     CdCommonRead( IrpContext, Irp );
135                     break;
136 
137                 case IRP_MJ_QUERY_INFORMATION :
138 
139                     CdCommonQueryInfo( IrpContext, Irp );
140                     break;
141 
142                 case IRP_MJ_SET_INFORMATION :
143 
144                     CdCommonSetInfo( IrpContext, Irp );
145                     break;
146 
147                 case IRP_MJ_QUERY_VOLUME_INFORMATION :
148 
149                     CdCommonQueryVolInfo( IrpContext, Irp );
150                     break;
151 
152                 case IRP_MJ_DIRECTORY_CONTROL :
153 
154                     CdCommonDirControl( IrpContext, Irp );
155                     break;
156 
157                 case IRP_MJ_FILE_SYSTEM_CONTROL :
158 
159                     CdCommonFsControl( IrpContext, Irp );
160                     break;
161 
162                 case IRP_MJ_DEVICE_CONTROL :
163 
164                     CdCommonDevControl( IrpContext, Irp );
165                     break;
166 
167                 case IRP_MJ_LOCK_CONTROL :
168 
169                     CdCommonLockControl( IrpContext, Irp );
170                     break;
171 
172                 case IRP_MJ_CLEANUP :
173 
174                     CdCommonCleanup( IrpContext, Irp );
175                     break;
176 
177                 case IRP_MJ_PNP :
178 
179                     NT_ASSERT( FALSE );
180                     CdCommonPnp( IrpContext, Irp );
181                     break;
182 
183                 default :
184 
185                     Status = STATUS_INVALID_DEVICE_REQUEST;
186                     CdCompleteRequest( IrpContext, Irp, Status );
187                 }
188 
189             } _SEH2_EXCEPT( CdExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
190 
191                 Status = CdProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
192             } _SEH2_END;
193 
194             //
195             //  Break out of the loop if we didn't get CANT_WAIT.
196             //
197 
198             if (Status != STATUS_CANT_WAIT) { break; }
199 
200             //
201             //  We are retrying this request.  Cleanup the IrpContext for the retry.
202             //
203 
204             SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
205             CdCleanupIrpContext( IrpContext, FALSE );
206         }
207 
208         FsRtlExitFileSystem();
209 
210         //
211         //  If there are any entries on this volume's overflow queue, service
212         //  them.
213         //
214 
215         if (VolDo != NULL) {
216 
217             KIRQL SavedIrql;
218             PVOID Entry = NULL;
219 
220             //
221             //  We have a volume device object so see if there is any work
222             //  left to do in its overflow queue.
223             //
224 
225             KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql );
226 
227             if (VolDo->OverflowQueueCount > 0) {
228 
229                 //
230                 //  There is overflow work to do in this volume so we'll
231                 //  decrement the Overflow count, dequeue the IRP, and release
232                 //  the Event
233                 //
234 
235                 VolDo->OverflowQueueCount -= 1;
236 
237                 Entry = RemoveHeadList( &VolDo->OverflowQueue );
238 
239             } else {
240 
241                 VolDo->PostedRequestCount -= 1;
242 
243                 Entry = NULL;
244             }
245 
246             KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql );
247 
248             //
249             //  There wasn't an entry, break out of the loop and return to
250             //  the Ex Worker thread.
251             //
252 
253             if (Entry == NULL) {
254 
255                 break;
256             }
257 
258             //
259             //  Extract the IrpContext , Irp, set wait to TRUE, and loop.
260             //
261 
262             IrpContext = CONTAINING_RECORD( Entry,
263                                             IRP_CONTEXT,
264                                             WorkQueueItem.List );
265 
266             Irp = IrpContext->Irp;
267             IrpSp = IoGetCurrentIrpStackLocation( Irp );
268             __analysis_assert( IrpSp != 0 );
269 
270             continue;
271         }
272 
273         break;
274     }
275 
276     return;
277 }
278 
279 
280 
281 
282