summaryrefslogtreecommitdiffstats
path: root/private/nw/rdr/fspdisp.c
blob: bd21d7d2db9000c143a36d398e36cdf2b19e0732 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    FspDisp.c

Abstract:

    This module implements the main dispatch procedure/thread for the NetWare
    Fsp

Author:

    Colin Watson     [ColinW]    15-Dec-1992

Revision History:

--*/

#include "Procs.h"

//
//  Define our local debug trace level
//

#define Dbg                              (DEBUG_TRACE_FSP_DISPATCHER)

#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, NwFspDispatch )
#endif

#if 0  //  Not pageable
NwPostToFsp
#endif


VOID
NwFspDispatch (
    IN PVOID Context
    )

/*++

Routine Description:

    This is the main FSP thread routine that is executed to receive
    and dispatch IRP requests.  Each FSP thread begins its execution here.
    There is one thread created at system initialization time and subsequent
    threads created as needed.

Arguments:


    Context - Supplies the thread id.

Return Value:

    None - This routine never exits

--*/

{
    PIRP Irp;
    PIRP_CONTEXT IrpContext;
    PIO_STACK_LOCATION IrpSp;
    NTSTATUS Status;
    PPOST_PROCESSOR PostProcessRoutine;
    BOOLEAN TopLevel;

    IrpContext = (PIRP_CONTEXT)Context;

    Irp = IrpContext->pOriginalIrp;
    ClearFlag( IrpContext->Flags, IRP_FLAG_IN_FSD );

    //
    //  Now case on the function code.  For each major function code,
    //  either call the appropriate FSP routine or case on the minor
    //  function and then call the FSP routine.  The FSP routine that
    //  we call is responsible for completing the IRP, and not us.
    //  That way the routine can complete the IRP and then continue
    //  post processing as required.  For example, a read can be
    //  satisfied right away and then read can be done.
    //
    //  We'll do all of the work within an exception handler that
    //  will be invoked if ever some underlying operation gets into
    //  trouble (e.g., if NwReadSectorsSync has trouble).
    //


    DebugTrace(0, Dbg, "NwFspDispatch: Irp = 0x%08lx\n", Irp);

    FsRtlEnterFileSystem();
    TopLevel = NwIsIrpTopLevel( Irp );

    try {

        //
        //  If we have a run routine for this IRP context, then run it,
        //  if not fall through to the IRP handler.
        //

        if ( IrpContext->PostProcessRoutine != NULL ) {

            PostProcessRoutine = IrpContext->PostProcessRoutine;

            //
            //  Clear the run routine so that we don't run it again.
            //

            IrpContext->PostProcessRoutine = NULL;

            Status = PostProcessRoutine( IrpContext );

        } else {

            IrpSp = IoGetCurrentIrpStackLocation( Irp );

            switch ( IrpSp->MajorFunction ) {

            //
            //  For File System Control operations,
            //

            case IRP_MJ_FILE_SYSTEM_CONTROL:

                Status = NwCommonFileSystemControl( IrpContext );
                break;

            //
            //  For any other major operations, return an invalid
            //  request.
            //

            default:

                Status = STATUS_INVALID_DEVICE_REQUEST;
                break;

            }

        }

        //
        //  We're done with this request.  Dequeue the IRP context from
        //  SCB and complete the request.
        //

        if ( Status != STATUS_PENDING ) {
            NwDequeueIrpContext( IrpContext, FALSE );
        }

        NwCompleteRequest( IrpContext, Status );

    } except(NwExceptionFilter( Irp, GetExceptionInformation() )) {

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code.
        //

        (VOID) NwProcessException( IrpContext, GetExceptionCode() );
    }

    if ( TopLevel ) {
        NwSetTopLevelIrp( NULL );
    }
    FsRtlExitFileSystem();

    return;
}


NTSTATUS
NwPostToFsp (
    IN PIRP_CONTEXT IrpContext,
    IN BOOLEAN MarkIrpPending
    )

/*++

Routine Description:

    This routine post an IRP context to an executive worker thread
    for FSP level processing.

    *** WARNING:  After calling this routine, the caller may no
                  longer access IrpContext.   This routine passes
                  the IrpContext to the FSP which may run and free
                  the IrpContext before this routine returns to the
                  caller.

Arguments:

    IrpContext - Supplies the Irp being processed.

    MarkIrpPending - If true, mark the IRP pending.

Return Value:

    STATUS_PENDING.

--*/

{
    PIRP Irp = IrpContext->pOriginalIrp;

    DebugTrace(0, Dbg, "NwPostToFsp: IrpContext = %X\n", IrpContext );
    DebugTrace(0, Dbg, "PostProcessRoutine = %X\n", IrpContext->PostProcessRoutine );

    if ( MarkIrpPending ) {

        //
        //  Mark this I/O request as being pending.
        //

        IoMarkIrpPending( Irp );
    }

    //
    //  Queue to IRP context to an ex worker thread.
    //

    ExInitializeWorkItem( &IrpContext->WorkQueueItem, NwFspDispatch, IrpContext );
    ExQueueWorkItem( &IrpContext->WorkQueueItem, DelayedWorkQueue );

    return( STATUS_PENDING );
}