Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

workque.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 WorkQue.c 00008 00009 Abstract: 00010 00011 This module implements the Work queue routines for the Udfs File 00012 system. 00013 00014 Author: 00015 00016 Dan Lovinger [DanLo] 23-Sep-1996 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "UdfProcs.h" 00023 00024 // 00025 // The Bug check file id for this module 00026 // 00027 00028 #define BugCheckFileId (UDFS_BUG_CHECK_WORKQUE) 00029 00030 // 00031 // The local debug trace level 00032 // 00033 00034 #define Dbg (UDFS_DEBUG_LEVEL_WORKQUE) 00035 00036 // 00037 // The following constant is the maximum number of ExWorkerThreads that we 00038 // will allow to be servicing a particular target device at any one time. 00039 // 00040 00041 #define FSP_PER_DEVICE_THRESHOLD (2) 00042 00043 // 00044 // Local support routines 00045 // 00046 00047 VOID 00048 UdfAddToWorkque ( 00049 IN PIRP_CONTEXT IrpContext, 00050 IN PIRP Irp 00051 ); 00052 00053 #ifdef ALLOC_PRAGMA 00054 #pragma alloc_text(PAGE, UdfFsdPostRequest) 00055 #pragma alloc_text(PAGE, UdfOplockComplete) 00056 #pragma alloc_text(PAGE, UdfPrePostIrp) 00057 #endif 00058 00059 00060 NTSTATUS 00061 UdfFsdPostRequest ( 00062 IN PIRP_CONTEXT IrpContext, 00063 IN PIRP Irp 00064 ) 00065 00066 /*++ 00067 00068 Routine Description: 00069 00070 This routine enqueues the request packet specified by IrpContext to the 00071 work queue associated with the FileSystemDeviceObject. This is a FSD 00072 routine. 00073 00074 Arguments: 00075 00076 IrpContext - Pointer to the IrpContext to be queued to the Fsp. 00077 00078 Irp - I/O Request Packet. 00079 00080 Return Value: 00081 00082 STATUS_PENDING 00083 00084 --*/ 00085 00086 { 00087 PAGED_CODE(); 00088 00089 ASSERT_IRP_CONTEXT( IrpContext ); 00090 ASSERT_IRP( Irp ); 00091 00092 // 00093 // Posting is a three step operation. First lock down any buffers 00094 // in the Irp. Next cleanup the IrpContext for the post and finally 00095 // add this to a workque. 00096 // 00097 00098 UdfPrePostIrp( IrpContext, Irp ); 00099 00100 UdfAddToWorkque( IrpContext, Irp ); 00101 00102 // 00103 // And return to our caller 00104 // 00105 00106 return STATUS_PENDING; 00107 } 00108 00109 00110 VOID 00111 UdfPrePostIrp ( 00112 IN PIRP_CONTEXT IrpContext, 00113 IN PIRP Irp 00114 ) 00115 00116 /*++ 00117 00118 Routine Description: 00119 00120 This routine performs any neccessary work before STATUS_PENDING is 00121 returned with the Fsd thread. This routine is called within the 00122 filesystem and by the oplock package. 00123 00124 Arguments: 00125 00126 Context - Pointer to the IrpContext to be queued to the Fsp 00127 00128 Irp - I/O Request Packet. 00129 00130 Return Value: 00131 00132 None. 00133 00134 --*/ 00135 00136 { 00137 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 00138 BOOLEAN RemovedFcb; 00139 00140 PAGED_CODE(); 00141 00142 ASSERT_IRP_CONTEXT( IrpContext ); 00143 ASSERT_IRP( Irp ); 00144 00145 // 00146 // Case on the type of the operation. 00147 // 00148 00149 switch (IrpContext->MajorFunction) { 00150 00151 case IRP_MJ_CREATE : 00152 00153 // 00154 // If called from the oplock package then there is an 00155 // Fcb to possibly teardown. We will call the teardown 00156 // routine and release the Fcb if still present. The cleanup 00157 // code in create will know not to release this Fcb because 00158 // we will clear the pointer. 00159 // 00160 00161 if ((IrpContext->TeardownFcb != NULL) && 00162 *(IrpContext->TeardownFcb) != NULL) { 00163 00164 UdfTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), FALSE, &RemovedFcb ); 00165 00166 if (!RemovedFcb) { 00167 00168 UdfReleaseFcb( IrpContext, *(IrpContext->TeardownFcb) ); 00169 } 00170 00171 *(IrpContext->TeardownFcb) = NULL; 00172 IrpContext->TeardownFcb = NULL; 00173 } 00174 00175 break; 00176 00177 // 00178 // We need to lock the user's buffer, unless this is an MDL-read, 00179 // in which case there is no user buffer. 00180 // 00181 00182 case IRP_MJ_READ : 00183 00184 if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) { 00185 00186 UdfLockUserBuffer( IrpContext, IrpSp->Parameters.Read.Length ); 00187 } 00188 00189 break; 00190 00191 // 00192 // We also need to check whether this is a query file operation. 00193 // 00194 00195 case IRP_MJ_DIRECTORY_CONTROL : 00196 00197 if (IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) { 00198 00199 UdfLockUserBuffer( IrpContext, IrpSp->Parameters.QueryDirectory.Length ); 00200 } 00201 00202 break; 00203 } 00204 // 00205 // Cleanup the IrpContext for the post. 00206 // 00207 00208 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING ); 00209 UdfCleanupIrpContext( IrpContext, TRUE ); 00210 00211 // 00212 // Mark the Irp to show that we've already returned pending to the user. 00213 // 00214 00215 IoMarkIrpPending( Irp ); 00216 00217 return; 00218 } 00219 00220 00221 VOID 00222 UdfOplockComplete ( 00223 IN PIRP_CONTEXT IrpContext, 00224 IN PIRP Irp 00225 ) 00226 00227 /*++ 00228 00229 Routine Description: 00230 00231 This routine is called by the oplock package when an oplock break has 00232 completed, allowing an Irp to resume execution. If the status in 00233 the Irp is STATUS_SUCCESS, then we queue the Irp to the Fsp queue. 00234 Otherwise we complete the Irp with the status in the Irp. 00235 00236 If we are completing due to an error then check if there is any 00237 cleanup to do. 00238 00239 Arguments: 00240 00241 Irp - I/O Request Packet. 00242 00243 Return Value: 00244 00245 None. 00246 00247 --*/ 00248 00249 { 00250 BOOLEAN RemovedFcb; 00251 00252 PAGED_CODE(); 00253 00254 // 00255 // Check on the return value in the Irp. If success then we 00256 // are to post this request. 00257 // 00258 00259 if (Irp->IoStatus.Status == STATUS_SUCCESS) { 00260 00261 // 00262 // Check if there is any cleanup work to do. 00263 // 00264 00265 switch (IrpContext->MajorFunction) { 00266 00267 case IRP_MJ_CREATE : 00268 00269 // 00270 // If called from the oplock package then there is an 00271 // Fcb to possibly teardown. We will call the teardown 00272 // routine and release the Fcb if still present. The cleanup 00273 // code in create will know not to release this Fcb because 00274 // we will clear the pointer. 00275 // 00276 00277 if (IrpContext->TeardownFcb != NULL) { 00278 00279 UdfTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), FALSE, &RemovedFcb ); 00280 00281 if (!RemovedFcb) { 00282 00283 UdfReleaseFcb( IrpContext, *(IrpContext->TeardownFcb) ); 00284 } 00285 00286 *(IrpContext->TeardownFcb) = NULL; 00287 IrpContext->TeardownFcb = NULL; 00288 } 00289 00290 break; 00291 } 00292 // 00293 // Insert the Irp context in the workqueue. 00294 // 00295 00296 UdfAddToWorkque( IrpContext, Irp ); 00297 00298 // 00299 // Otherwise complete the request. 00300 // 00301 00302 } else { 00303 00304 UdfCompleteRequest( IrpContext, Irp, Irp->IoStatus.Status ); 00305 } 00306 00307 return; 00308 } 00309 00310 00311 // 00312 // Local support routine 00313 // 00314 00315 VOID 00316 UdfAddToWorkque ( 00317 IN PIRP_CONTEXT IrpContext, 00318 IN PIRP Irp 00319 ) 00320 00321 /*++ 00322 00323 Routine Description: 00324 00325 This routine is called to acually store the posted Irp to the Fsp 00326 workque. 00327 00328 Arguments: 00329 00330 IrpContext - Pointer to the IrpContext to be queued to the Fsp 00331 00332 Irp - I/O Request Packet. 00333 00334 Return Value: 00335 00336 None. 00337 00338 --*/ 00339 00340 { 00341 PVOLUME_DEVICE_OBJECT Vdo; 00342 KIRQL SavedIrql; 00343 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 00344 00345 // 00346 // Check if this request has an associated file object, and thus volume 00347 // device object. 00348 // 00349 00350 if (IrpSp->FileObject != NULL) { 00351 00352 00353 Vdo = CONTAINING_RECORD( IrpSp->DeviceObject, 00354 VOLUME_DEVICE_OBJECT, 00355 DeviceObject ); 00356 00357 // 00358 // Check to see if this request should be sent to the overflow 00359 // queue. If not, then send it off to an exworker thread. 00360 // 00361 00362 KeAcquireSpinLock( &Vdo->OverflowQueueSpinLock, &SavedIrql ); 00363 00364 if (Vdo->PostedRequestCount > FSP_PER_DEVICE_THRESHOLD) { 00365 00366 // 00367 // We cannot currently respond to this IRP so we'll just enqueue it 00368 // to the overflow queue on the volume. 00369 // 00370 00371 InsertTailList( &Vdo->OverflowQueue, 00372 &IrpContext->WorkQueueItem.List ); 00373 00374 Vdo->OverflowQueueCount += 1; 00375 00376 KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql ); 00377 00378 return; 00379 00380 } else { 00381 00382 // 00383 // We are going to send this Irp to an ex worker thread so up 00384 // the count. 00385 // 00386 00387 Vdo->PostedRequestCount += 1; 00388 00389 KeReleaseSpinLock( &Vdo->OverflowQueueSpinLock, SavedIrql ); 00390 } 00391 } 00392 00393 // 00394 // Send it off..... 00395 // 00396 00397 ExInitializeWorkItem( &IrpContext->WorkQueueItem, 00398 UdfFspDispatch, 00399 IrpContext ); 00400 00401 ExQueueWorkItem( &IrpContext->WorkQueueItem, CriticalWorkQueue ); 00402 00403 return; 00404 } 00405 00406

Generated on Sat May 15 19:42:27 2004 for test by doxygen 1.3.7