test: cachesup.c Source File

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

# cachesup.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1996  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     CacheSup.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the cache management routines for the Udfs
    00012     FSD and FSP, by calling the Common Cache Manager.
    00013
    00014 Author:
    00015
    00016     Dan Lovinger    [DanLo]     12-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_CACHESUP)
    00029
    00030 //
    00031 //  The local debug trace level
    00032 //
    00033
    00034 #define Dbg                              (UDFS_DEBUG_LEVEL_CACHESUP)
    00035
    00036 #ifdef ALLOC_PRAGMA
    00037 #pragma alloc_text(PAGE, UdfCompleteMdl)
    00038 #pragma alloc_text(PAGE, UdfCreateInternalStream)
    00039 #pragma alloc_text(PAGE, UdfDeleteInternalStream)
    00040 #pragma alloc_text(PAGE, UdfMapMetadataView)
    00041 #pragma alloc_text(PAGE, UdfPurgeVolume)
    00042 #endif
    00043
    00044
    00045 VOID
    00046 UdfCreateInternalStream (
    00047     IN PIRP_CONTEXT IrpContext,
    00048     IN PVCB Vcb,
    00049     IN PFCB Fcb
    00050     )
    00051
    00052 /*++
    00053
    00054 Routine Description:
    00055
    00056     This function creates an internal stream file for interaction
    00057     with the cache manager.  The Fcb here will be for a directory
    00058     stream.
    00059
    00060 Arguments:
    00061
    00062     Vcb - Vcb for this volume.
    00063
    00064     Fcb - Points to the Fcb for this file.  It is an Index Fcb.
    00065
    00066 Return Value:
    00067
    00068     None.
    00069
    00070 --*/
    00071
    00072 {
    00073     PFILE_OBJECT StreamFile = NULL;
    00074     BOOLEAN DecrementReference = FALSE;
    00075
    00076     PAGED_CODE();
    00077
    00078     //
    00079     //  Check inputs.
    00080     //
    00081
    00082     ASSERT_IRP_CONTEXT( IrpContext );
    00083     ASSERT_FCB_INDEX( Fcb );
    00084
    00085     //
    00086     //  We may only have the Fcb shared.  Lock the Fcb and do a
    00087     //  safe test to see if we need to really create the file object.
    00088     //
    00089
    00090     UdfLockFcb( IrpContext, Fcb );
    00091
    00092     if (Fcb->FileObject != NULL) {
    00093
    00094         UdfUnlockFcb( IrpContext, Fcb );
    00095         return;
    00096     }
    00097
    00098     //
    00099     //  Use a try-finally to facilitate cleanup.
    00100     //
    00101
    00102     try {
    00103
    00104         //
    00105         //  Create the internal stream.  The Vpb should be pointing at our volume
    00106         //  device object at this point.
    00107         //
    00108
    00109         StreamFile = IoCreateStreamFileObject( NULL, Vcb->Vpb->RealDevice );
    00110
    00111         if (StreamFile == NULL) {
    00112
    00113             UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
    00114         }
    00115
    00116         //
    00117         //  Initialize the fields of the file object.
    00118         //
    00119
    00120         StreamFile->ReadAccess = TRUE;
    00121         StreamFile->WriteAccess = FALSE;
    00122         StreamFile->DeleteAccess = FALSE;
    00123
    00124         StreamFile->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject;
    00125
    00126         //
    00127         //  Set the file object type and increment the Vcb counts.
    00128         //
    00129
    00130         UdfSetFileObject( IrpContext,
    00131                          StreamFile,
    00132                          StreamFileOpen,
    00133                          Fcb,
    00134                          NULL );
    00135
    00136         //
    00137         //  We will reference the current Fcb twice to keep it from going
    00138         //  away in the error path.  Otherwise if we dereference it
    00139         //  below in the finally clause a close could cause the Fcb to
    00140         //  be deallocated.
    00141         //
    00142
    00143         UdfLockVcb( IrpContext, Vcb );
    00144
    00145         DebugTrace(( +1, Dbg,
    00146                      "UdfCreateInternalStream, Fcb %08x Vcb %d/%d Fcb %d/%d\n",
    00147                      Fcb,
    00148                      Vcb->VcbReference,
    00149                      Vcb->VcbUserReference,
    00150                      Fcb->FcbReference,
    00151                      Fcb->FcbUserReference ));
    00152
    00153         UdfIncrementReferenceCounts( IrpContext, Fcb, 2, 0 );
    00154         UdfUnlockVcb( IrpContext, Vcb );
    00155         DecrementReference = TRUE;
    00156
    00157         //
    00158         //  Initialize the cache map for the file.
    00159         //
    00160
    00161         CcInitializeCacheMap( StreamFile,
    00162                               (PCC_FILE_SIZES)&Fcb->AllocationSize,
    00163                               TRUE,
    00164                               &UdfData.CacheManagerCallbacks,
    00165                               Fcb );
    00166
    00167         //
    00168         //  Go ahead and store the stream file into the Fcb.
    00169         //
    00170
    00171         Fcb->FileObject = StreamFile;
    00172         StreamFile = NULL;
    00173
    00174     } finally {
    00175
    00176         DebugUnwind( "UdfCreateInternalStream" );
    00177
    00178         //
    00179         //  If we raised then we need to dereference the file object.
    00180         //
    00181
    00182         if (StreamFile != NULL) {
    00183
    00184             ObDereferenceObject( StreamFile );
    00185             Fcb->FileObject = NULL;
    00186         }
    00187
    00188         //
    00189         //  Dereference and unlock the Fcb.
    00190         //
    00191
    00192         if (DecrementReference) {
    00193
    00194             UdfLockVcb( IrpContext, Vcb );
    00195             UdfDecrementReferenceCounts( IrpContext, Fcb, 1, 0 );
    00196
    00197             DebugTrace(( -1, Dbg,
    00198                          "UdfCreateInternalStream, Vcb %d/%d Fcb %d/%d\n",
    00199                          Vcb->VcbReference,
    00200                          Vcb->VcbUserReference,
    00201                          Fcb->FcbReference,
    00202                          Fcb->FcbUserReference ));
    00203
    00204             UdfUnlockVcb( IrpContext, Vcb );
    00205         }
    00206
    00207         UdfUnlockFcb( IrpContext, Fcb );
    00208     }
    00209
    00210     return;
    00211 }
    00212
    00213
    00214 VOID
    00215 UdfDeleteInternalStream (
    00216     IN PIRP_CONTEXT IrpContext,
    00217     IN PFCB Fcb
    00218     )
    00219
    00220 /*++
    00221
    00222 Routine Description:
    00223
    00224     This function creates an internal stream file for interaction
    00225     with the cache manager.  The Fcb here can be for either a
    00226     directory stream or for a metadata stream.
    00227
    00228 Arguments:
    00229
    00230     Fcb - Points to the Fcb for this file.  It is either an Index or
    00231         Metadata Fcb.
    00232
    00233 Return Value:
    00234
    00235     None.
    00236
    00237 --*/
    00238
    00239 {
    00240     PFILE_OBJECT FileObject;
    00241
    00242     PAGED_CODE();
    00243
    00244     ASSERT_IRP_CONTEXT( IrpContext );
    00245     ASSERT_FCB( Fcb );
    00246
    00247     //
    00248     //  Lock the Fcb.
    00249     //
    00250
    00251     UdfLockFcb( IrpContext, Fcb );
    00252
    00253     //
    00254     //  Capture the file object.
    00255     //
    00256
    00257     FileObject = Fcb->FileObject;
    00258     Fcb->FileObject = NULL;
    00259
    00260     //
    00261     //  It is now safe to unlock the Fcb.
    00262     //
    00263
    00264     UdfUnlockFcb( IrpContext, Fcb );
    00265
    00266     //
    00267     //  Dereference the file object if present.
    00268     //
    00269
    00270     if (FileObject != NULL) {
    00271
    00272         if (FileObject->PrivateCacheMap != NULL) {
    00273
    00274             CcUninitializeCacheMap( FileObject, NULL, NULL );
    00275         }
    00276
    00277         ObDereferenceObject( FileObject );
    00278     }
    00279
    00280     return;
    00281 }
    00282
    00283
    00284 NTSTATUS
    00285 UdfCompleteMdl (
    00286     IN PIRP_CONTEXT IrpContext,
    00287     IN PIRP Irp
    00288     )
    00289
    00290 /*++
    00291
    00292 Routine Description:
    00293
    00294     This routine performs the function of completing Mdl reads.
    00295     It should be called only from UdfCommonRead.
    00296
    00297 Arguments:
    00298
    00299     Irp - Supplies the originating Irp.
    00300
    00301 Return Value:
    00302
    00303     NTSTATUS - Will always be STATUS_SUCCESS.
    00304
    00305 --*/
    00306
    00307 {
    00308     PFILE_OBJECT FileObject;
    00309
    00310     PAGED_CODE();
    00311
    00312     //
    00313     // Do completion processing.
    00314     //
    00315
    00316     FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
    00317
    00318     CcMdlReadComplete( FileObject, Irp->MdlAddress );
    00319
    00320     //
    00321     // Mdl is now deallocated.
    00322     //
    00323
    00324     Irp->MdlAddress = NULL;
    00325
    00326     //
    00327     // Complete the request and exit right away.
    00328     //
    00329
    00330     UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00331
    00332     return STATUS_SUCCESS;
    00333 }
    00334
    00335
    00336 VOID
    00337 UdfMapMetadataView (
    00338     IN PIRP_CONTEXT IrpContext,
    00339     IN PMAPPED_PVIEW View,
    00340     IN PVCB Vcb,
    00341     IN USHORT Partition,
    00342     IN ULONG Lbn,
    00343     IN ULONG Length
    00344     )
    00345
    00346 /*++
    00347
    00348 Routine Description:
    00349
    00350     Perform the common work of mapping an extent of metadata into a mapped view.
    00351
    00352 Arguments:
    00353
    00354     View - View structure to map the bytes into
    00355
    00356     Vcb - Vcb of the volume the extent is on
    00357
    00358     Partition - Partition of the extent
    00359
    00360     Lbn - Lbn of the extent
    00361
    00362     Length - Length of the extent
    00363
    00364 Return Value:
    00365
    00366     None.
    00367
    00368 --*/
    00369
    00370 {
    00371     LARGE_INTEGER Offset;
    00372     ULONG Vsn;
    00373
    00374     ASSERT_IRP_CONTEXT( IrpContext );
    00375
    00376     //
    00377     //  Remove any existing mapping
    00378     //
    00379
    00380     UdfUnpinView( IrpContext, View );
    00381
    00382     //
    00383     //  Update the view information.
    00384     //
    00385
    00386     View->Partition = Partition;
    00387     View->Lbn = Lbn;
    00388     View->Length = Length;
    00389
    00390     //
    00391     //  Find the mapping of this extent in the Metadata stream.
    00392     //
    00393
    00394     Vsn = UdfLookupMetaVsnOfExtent( IrpContext,
    00395                                     Vcb,
    00396                                     Partition,
    00397                                     Lbn,
    00398                                     Length,
    00399                                     FALSE );
    00400
    00401     Offset.QuadPart = LlBytesFromSectors( Vcb, Vsn );
    00402
    00403     //
    00404     //  Map the extent
    00405     //
    00406
    00407     CcMapData( Vcb->MetadataFcb->FileObject,
    00408                &Offset,
    00409                Length,
    00410                TRUE,
    00411                &View->Bcb,
    00412                &View->View );
    00413 }
    00414
    00415
    00416 NTSTATUS
    00417 UdfPurgeVolume (
    00418     IN PIRP_CONTEXT IrpContext,
    00419     IN PVCB Vcb,
    00420     IN BOOLEAN DismountUnderway
    00421     )
    00422
    00423 /*++
    00424
    00425 Routine Description:
    00426
    00427     This routine is called to purge the volume.  The purpose is to make all the stale file
    00428     objects in the system go away, minimizing the reference counts, so that the volume may
    00429     be locked or deleted.
    00430
    00431     The Vcb is already acquired exclusively.  We will lock out all file operations by
    00432     acquiring the global file resource.  Then we will walk through all of the Fcb's and
    00433     perform the purge.
    00434
    00435 Arguments:
    00436
    00437     Vcb - Vcb for the volume to purge.
    00438
    00439     DismountUnderway - Indicates that we are trying to delete all of the objects.
    00440         We will purge the Metadata and VolumeDasd and dereference all internal streams.
    00441
    00442 Return Value:
    00443
    00444     NTSTATUS - The first failure of the purge operation.
    00445
    00446 --*/
    00447
    00448 {
    00449     NTSTATUS Status = STATUS_SUCCESS;
    00450
    00451     PVOID RestartKey = NULL;
    00452     PFCB ThisFcb = NULL;
    00453     PFCB NextFcb;
    00454
    00455     BOOLEAN RemovedFcb;
    00456
    00457     PAGED_CODE();
    00458
    00459     //
    00460     //  Force any remaining Fcb's in the delayed close queue to be closed.
    00461     //
    00462
    00463     UdfFspClose( Vcb );
    00464
    00465     //
    00466     //  Acquire the global file resource.
    00467     //
    00468
    00469     UdfAcquireAllFiles( IrpContext, Vcb );
    00470
    00471     //
    00472     //  Loop through each Fcb in the Fcb Table and perform the flush.
    00473     //
    00474
    00475     while (TRUE) {
    00476
    00477         //
    00478         //  Lock the Vcb to lookup the next Fcb.
    00479         //
    00480
    00481         UdfLockVcb( IrpContext, Vcb );
    00482         NextFcb = UdfGetNextFcb( IrpContext, Vcb, &RestartKey );
    00483
    00484         //
    00485         //  Reference the NextFcb if present.
    00486         //
    00487
    00488         if (NextFcb != NULL) {
    00489
    00490             NextFcb->FcbReference += 1;
    00491         }
    00492
    00493         //
    00494         //  If the last Fcb is present then decrement reference count and call teardown
    00495         //  to see if it should be removed.
    00496         //
    00497
    00498         if (ThisFcb != NULL) {
    00499
    00500             ThisFcb->FcbReference -= 1;
    00501
    00502             UdfUnlockVcb( IrpContext, Vcb );
    00503
    00504             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00505
    00506         } else {
    00507
    00508             UdfUnlockVcb( IrpContext, Vcb );
    00509         }
    00510
    00511         //
    00512         //  Break out of the loop if no more Fcb's.
    00513         //
    00514
    00515         if (NextFcb == NULL) {
    00516
    00517             break;
    00518         }
    00519
    00520         //
    00521         //  Move to the next Fcb.
    00522         //
    00523
    00524         ThisFcb = NextFcb;
    00525
    00526         //
    00527         //  If there is a image section then see if that can be closed.
    00528         //
    00529
    00530         if (ThisFcb->FcbNonpaged->SegmentObject.ImageSectionObject != NULL) {
    00531
    00532             MmFlushImageSection( &ThisFcb->FcbNonpaged->SegmentObject, MmFlushForWrite );
    00533         }
    00534
    00535         //
    00536         //  If there is a data section then purge this.  If there is an image
    00537         //  section then we won't be able to.  Remember this if it is our first
    00538         //  error.
    00539         //
    00540
    00541         if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00542             !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00543                                    NULL,
    00544                                    0,
    00545                                    FALSE ) &&
    00546             (Status == STATUS_SUCCESS)) {
    00547
    00548             Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00549         }
    00550
    00551         //
    00552         //  Dereference the internal stream if dismounting.
    00553         //
    00554
    00555         if (DismountUnderway &&
    00556             (SafeNodeType( ThisFcb ) != UDFS_NTC_FCB_DATA) &&
    00557             (ThisFcb->FileObject != NULL)) {
    00558
    00559             UdfDeleteInternalStream( IrpContext, ThisFcb );
    00560         }
    00561     }
    00562
    00563     //
    00564     //  Now look at the Root Index, Metadata, Volume Dasd and VAT Fcbs.
    00565     //  Note that we usually hit the Root Index in the loop above, but
    00566     //  it is possible miss it if it didn't get into the Fcb table in the
    00567     //  first place!
    00568     //
    00569
    00570     if (DismountUnderway) {
    00571
    00572         if (Vcb->RootIndexFcb != NULL) {
    00573
    00574             ThisFcb = Vcb->RootIndexFcb;
    00575             InterlockedIncrement( &ThisFcb->FcbReference );
    00576
    00577             if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00578                 !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00579                                        NULL,
    00580                                        0,
    00581                                        FALSE ) &&
    00582                 (Status == STATUS_SUCCESS)) {
    00583
    00584                 Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00585             }
    00586
    00587             UdfDeleteInternalStream( IrpContext, ThisFcb );
    00588             InterlockedDecrement( &ThisFcb->FcbReference );
    00589             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00590         }
    00591
    00592         if (Vcb->MetadataFcb != NULL) {
    00593
    00594             ThisFcb = Vcb->MetadataFcb;
    00595             InterlockedIncrement( &ThisFcb->FcbReference );
    00596
    00597             if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00598                 !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00599                                        NULL,
    00600                                        0,
    00601                                        FALSE ) &&
    00602                 (Status == STATUS_SUCCESS)) {
    00603
    00604                 Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00605             }
    00606
    00607             UdfDeleteInternalStream( IrpContext, ThisFcb );
    00608             InterlockedDecrement( &ThisFcb->FcbReference );
    00609             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00610         }
    00611
    00612         if (Vcb->VatFcb != NULL) {
    00613
    00614             ThisFcb = Vcb->VatFcb;
    00615             InterlockedIncrement( &ThisFcb->FcbReference );
    00616
    00617             if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00618                 !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00619                                        NULL,
    00620                                        0,
    00621                                        FALSE ) &&
    00622                 (Status == STATUS_SUCCESS)) {
    00623
    00624                 Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00625             }
    00626
    00627             UdfDeleteInternalStream( IrpContext, ThisFcb );
    00628             InterlockedDecrement( &ThisFcb->FcbReference );
    00629             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00630         }
    00631
    00632         if (Vcb->VolumeDasdFcb != NULL) {
    00633
    00634             ThisFcb = Vcb->VolumeDasdFcb;
    00635             InterlockedIncrement( &ThisFcb->FcbReference );
    00636
    00637             if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00638                 !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00639                                        NULL,
    00640                                        0,
    00641                                        FALSE ) &&
    00642                 (Status == STATUS_SUCCESS)) {
    00643
    00644                 Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00645             }
    00646
    00647             InterlockedDecrement( &ThisFcb->FcbReference );
    00648             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00649         }
    00650     }
    00651
    00652     //
    00653     //  Release all of the files.
    00654     //
    00655
    00656     UdfReleaseAllFiles( IrpContext, Vcb );
    00657
    00658     return Status;
    00659 }
    00660