ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

flush.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.