Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenflush.c
Go to the documentation of this file.
00001 /************************************************************************* 00002 * 00003 * File: flush.c 00004 * 00005 * Module: Ext2 File System Driver (Kernel mode execution only) 00006 * 00007 * Description: 00008 * Contains code to handle the "Flush Buffers" dispatch entry point. 00009 * 00010 * Author: Manoj Paul Joseph 00011 * 00012 * 00013 *************************************************************************/ 00014 00015 #include "ext2fsd.h" 00016 00017 // define the file specific bug-check id 00018 #define EXT2_BUG_CHECK_ID EXT2_FILE_FLUSH 00019 00020 #define DEBUG_LEVEL (DEBUG_TRACE_FLUSH) 00021 00022 00023 /************************************************************************* 00024 * 00025 * Function: Ext2Flush() 00026 * 00027 * Description: 00028 * The I/O Manager will invoke this routine to handle a flush buffers 00029 * request 00030 * 00031 * Expected Interrupt Level (for execution) : 00032 * 00033 * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 00034 * to be deferred to a worker thread context) 00035 * 00036 * Return Value: STATUS_SUCCESS/Error 00037 * 00038 *************************************************************************/ 00039 NTSTATUS NTAPI Ext2Flush( 00040 PDEVICE_OBJECT DeviceObject, // the logical volume device object 00041 PIRP Irp) // I/O Request Packet 00042 { 00043 NTSTATUS RC = STATUS_SUCCESS; 00044 PtrExt2IrpContext PtrIrpContext = NULL; 00045 BOOLEAN AreWeTopLevel = FALSE; 00046 00047 DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Flush IRP Received...", 0); 00048 00049 // Ext2BreakPoint(); 00050 00051 FsRtlEnterFileSystem(); 00052 ASSERT(DeviceObject); 00053 ASSERT(Irp); 00054 00055 // set the top level context 00056 AreWeTopLevel = Ext2IsIrpTopLevel(Irp); 00057 00058 try 00059 { 00060 00061 // get an IRP context structure and issue the request 00062 PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject); 00063 ASSERT(PtrIrpContext); 00064 00065 RC = Ext2CommonFlush(PtrIrpContext, Irp); 00066 00067 } except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 00068 00069 RC = Ext2ExceptionHandler(PtrIrpContext, Irp); 00070 00071 Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC); 00072 } 00073 00074 if (AreWeTopLevel) { 00075 IoSetTopLevelIrp(NULL); 00076 } 00077 00078 FsRtlExitFileSystem(); 00079 00080 return(RC); 00081 } 00082 00083 00084 /************************************************************************* 00085 * 00086 * Function: Ext2CommonFlush() 00087 * 00088 * Description: 00089 * The actual work is performed here. This routine may be invoked in one' 00090 * of the two possible contexts: 00091 * (a) in the context of a system worker thread 00092 * (b) in the context of the original caller 00093 * 00094 * Expected Interrupt Level (for execution) : 00095 * 00096 * IRQL_PASSIVE_LEVEL 00097 * 00098 * Return Value: STATUS_SUCCESS/Error 00099 * 00100 *************************************************************************/ 00101 NTSTATUS NTAPI Ext2CommonFlush( 00102 PtrExt2IrpContext PtrIrpContext, 00103 PIRP PtrIrp) 00104 { 00105 NTSTATUS RC = STATUS_SUCCESS; 00106 PIO_STACK_LOCATION PtrIoStackLocation = NULL; 00107 PFILE_OBJECT PtrFileObject = NULL; 00108 PtrExt2FCB PtrFCB = NULL; 00109 PtrExt2CCB PtrCCB = NULL; 00110 PtrExt2VCB PtrVCB = NULL; 00111 PtrExt2NTRequiredFCB PtrReqdFCB = NULL; 00112 BOOLEAN AcquiredFCB = FALSE; 00113 BOOLEAN PostRequest = FALSE; 00114 BOOLEAN CanWait = TRUE; 00115 00116 try { 00117 // First, get a pointer to the current I/O stack location 00118 PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 00119 ASSERT(PtrIoStackLocation); 00120 00121 PtrFileObject = PtrIoStackLocation->FileObject; 00122 ASSERT(PtrFileObject); 00123 00124 // Get the FCB and CCB pointers 00125 PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2); 00126 ASSERT(PtrCCB); 00127 PtrFCB = PtrCCB->PtrFCB; 00128 AssertFCB( PtrFCB ); 00129 00130 /*ASSERT(PtrFCB); 00131 ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );*/ 00132 00133 PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 00134 00135 // Get some of the parameters supplied to us 00136 CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 00137 00138 // If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous. 00139 if (!CanWait) { 00140 PostRequest = TRUE; 00141 try_return(); 00142 } 00143 00144 // Check the type of object passed-in. That will determine the course of 00145 // action we take. 00146 if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || (PtrFCB->FCBFlags & EXT2_FCB_ROOT_DIRECTORY)) { 00147 00148 if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) { 00149 PtrVCB = (PtrExt2VCB)(PtrFCB); 00150 } else { 00151 PtrVCB = PtrFCB->PtrVCB; 00152 } 00153 00154 // The caller wishes to flush all files for the mounted 00155 // logical volume. The flush volume routine below should simply 00156 // walk through all of the open file streams, acquire the 00157 // FCB resource, and request the flush operation from the Cache 00158 // Manager. Basically, the sequence of operations listed below 00159 // for a single file should be executed on all open files. 00160 00161 Ext2FlushLogicalVolume(PtrIrpContext, PtrIrp, PtrVCB); 00162 00163 try_return(); 00164 } 00165 00166 if (!(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) 00167 { 00168 // This is a regular file. 00169 ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE); 00170 AcquiredFCB = TRUE; 00171 00172 // Request the Cache Manager to perform a flush operation. 00173 // Further, instruct the Cache Manager that we wish to flush the 00174 // entire file stream. 00175 Ext2FlushAFile(PtrReqdFCB, &(PtrIrp->IoStatus)); 00176 RC = PtrIrp->IoStatus.Status; 00177 // All done. You may want to also flush the directory entry for the 00178 // file stream at this time. 00179 00180 // Some log-based FSD implementations may wish to flush their 00181 // log files at this time. Finally, you should update the time-stamp 00182 // values for the file stream appropriately. This would involve 00183 // obtaining the current time and modifying the appropriate directory 00184 // entry fields. 00185 } 00186 00187 try_exit: 00188 00189 if (AcquiredFCB) 00190 { 00191 Ext2ReleaseResource(&(PtrReqdFCB->MainResource)); 00192 DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Flush]", 0); 00193 DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Flush]", 00194 PtrReqdFCB->MainResource.ActiveCount, 00195 PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 00196 PtrReqdFCB->MainResource.NumberOfSharedWaiters ); 00197 00198 AcquiredFCB = FALSE; 00199 } 00200 00201 if (!PostRequest) 00202 { 00203 PIO_STACK_LOCATION PtrNextIoStackLocation = NULL; 00204 NTSTATUS RC1 = STATUS_SUCCESS; 00205 00206 // Send the request down at this point. 00207 // To do this, you must set the next IRP stack location, and 00208 // maybe set a completion routine. 00209 // Be careful about marking the IRP pending if the lower level 00210 // driver returned pending and you do have a completion routine! 00211 PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp); 00212 *PtrNextIoStackLocation = *PtrIoStackLocation; 00213 00214 // Set the completion routine to "eat-up" any 00215 // STATUS_INVALID_DEVICE_REQUEST error code returned by the lower 00216 // level driver. 00217 IoSetCompletionRoutine(PtrIrp, Ext2FlushCompletion, NULL, TRUE, TRUE, TRUE); 00218 00219 /* 00220 * The exception handlers propably masked out the 00221 * fact that PtrVCB was never set. 00222 * -- Filip Navara, 18/08/2004 00223 */ 00224 PtrVCB = PtrFCB->PtrVCB; 00225 RC1 = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp); 00226 00227 RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1); 00228 } 00229 00230 } finally { 00231 if (PostRequest) { 00232 // Nothing to lock now. 00233 RC = Ext2PostRequest(PtrIrpContext, PtrIrp); 00234 } else { 00235 // Release the IRP context at this time. 00236 Ext2ReleaseIrpContext(PtrIrpContext); 00237 } 00238 } 00239 00240 return(RC); 00241 } 00242 00243 /************************************************************************* 00244 * 00245 * Function: Ext2FlushAFile() 00246 * 00247 * Description: 00248 * Tell the Cache Manager to perform a flush. 00249 * 00250 * Expected Interrupt Level (for execution) : 00251 * 00252 * IRQL_PASSIVE_LEVEL 00253 * 00254 * Return Value: None 00255 * 00256 *************************************************************************/ 00257 void NTAPI Ext2FlushAFile( 00258 PtrExt2NTRequiredFCB PtrReqdFCB, 00259 PIO_STATUS_BLOCK PtrIoStatus) 00260 { 00261 CcFlushCache(&(PtrReqdFCB->SectionObject), NULL, 0, PtrIoStatus); 00262 return; 00263 } 00264 00265 /************************************************************************* 00266 * 00267 * Function: Ext2FlushLogicalVolume() 00268 * 00269 * Description: 00270 * Flush everything beginning at root directory. 00271 * 00272 * Expected Interrupt Level (for execution) : 00273 * 00274 * IRQL_PASSIVE_LEVEL 00275 * 00276 * Return Value: None 00277 * 00278 *************************************************************************/ 00279 void NTAPI Ext2FlushLogicalVolume( 00280 PtrExt2IrpContext PtrIrpContext, 00281 PIRP PtrIrp, 00282 PtrExt2VCB PtrVCB) 00283 { 00284 BOOLEAN AcquiredVCB = FALSE; 00285 00286 try { 00287 ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE); 00288 00289 AcquiredVCB = TRUE; 00290 DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired Ex [Flush] ", 0); 00291 00292 // Go through the list of FCB's. You would probably 00293 // flush all of the files. Then, you could flush the 00294 // directories that you may have have pinned into memory. 00295 00296 // NOTE: This function may also be invoked internally as part of 00297 // processing a shutdown request. 00298 00299 } 00300 finally 00301 { 00302 if (AcquiredVCB) 00303 { 00304 Ext2ReleaseResource(&(PtrVCB->VCBResource)); 00305 DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Flush]", 0); 00306 DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Flush]", 00307 PtrVCB->VCBResource.ActiveCount, 00308 PtrVCB->VCBResource.NumberOfExclusiveWaiters, 00309 PtrVCB->VCBResource.NumberOfSharedWaiters ); 00310 } 00311 } 00312 00313 return; 00314 } 00315 00316 00317 /************************************************************************* 00318 * 00319 * Function: Ext2FlushCompletion() 00320 * 00321 * Description: 00322 * Eat up any bad errors. 00323 * 00324 * Expected Interrupt Level (for execution) : 00325 * 00326 * IRQL_PASSIVE_LEVEL 00327 * 00328 * Return Value: None 00329 * 00330 *************************************************************************/ 00331 NTSTATUS NTAPI Ext2FlushCompletion( 00332 PDEVICE_OBJECT PtrDeviceObject, 00333 PIRP PtrIrp, 00334 PVOID Context) 00335 { 00336 if (PtrIrp->PendingReturned) { 00337 IoMarkIrpPending(PtrIrp); 00338 } 00339 00340 if (PtrIrp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) { 00341 // cannot do much here, can we? 00342 PtrIrp->IoStatus.Status = STATUS_SUCCESS; 00343 } 00344 00345 return(STATUS_SUCCESS); 00346 } Generated on Sun May 27 2012 04:27:39 for ReactOS by
1.7.6.1
|