test: pinsup.c File Reference

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

# pinsup.c File Reference

`#include "cc.h"`

Go to the source code of this file.

## Defines

#define | me 0x00000008

## Functions

POBCB | CcAllocateObcb (IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN PBCB FirstBcb)
BOOLEAN | CcMapData (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, OUT PVOID *Bcb, OUT PVOID *Buffer)
BOOLEAN | CcPinMappedData (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, IN OUT PVOID *Bcb)
BOOLEAN | CcPinRead (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer)
BOOLEAN | CcPreparePinWrite (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Zero, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer)
VOID | CcUnpinData (IN PVOID Bcb)
VOID | CcSetBcbOwnerPointer (IN PVOID Bcb, IN PVOID OwnerPointer)
VOID | CcUnpinDataForThread (IN PVOID Bcb, IN ERESOURCE_THREAD ResourceThreadId)

## Define Documentation

#define me 0x00000008

| Definition at line 28 of file pinsup.c.

## Function Documentation

POBCB CcAllocateObcb | ( | IN PLARGE_INTEGER | FileOffset,
|  | IN ULONG | Length,
|  | IN PBCB | FirstBcb
| ) |

Definition at line 1230 of file pinsup.c.

References _OBCB::Bcbs, _OBCB::ByteLength, _BCB::ByteLength, CACHE_NTC_OBCB, _OBCB::FileOffset, _BCB::FileOffset, FsRtlAllocatePoolWithTag, _OBCB::NodeByteSize, _OBCB::NodeTypeCode, NonPagedPool, OBCB, PAGE_SIZE, and USHORT.

Referenced by CcPinMappedData(), CcPinRead(), and CcPreparePinWrite().

    01238                    :
    01239
    01240     This routine is called by the various pinning routines to allocate and
    01241     initialize an overlap Bcb.
    01242
    01243 Arguments:
    01244
    01245     FileOffset - Starting file offset for the Obcb (An Obcb starts with a
    01246                  public structure, which someone could use)
    01247
    01248     Length - Length of the range covered by the Obcb
    01249
    01250     FirstBcb - First Bcb already created, which only covers the start of
    01251                the desired range (low order bit may be set to indicate ReadOnly)
    01252
    01253 Return Value:
    01254
    01255     Pointer to the allocated Obcb
    01256
    01257 --*/
    01258
    01259 {
    01260     ULONG LengthToAllocate;
    01261     POBCB Obcb;
    01262     PBCB Bcb = (PBCB)((ULONG_PTR)FirstBcb & ~1);
    01263
    01264     //
    01265     //  Allocate according to the worst case, assuming that we
    01266     //  will need as many additional Bcbs as there are pages
    01267     //  remaining. Also throw in one more pointer to guarantee
    01268     //  users of the OBCB can always terminate on NULL.
    01269     //
    01270     //  We remove fron consideration the range described by the
    01271     //  first Bcb (note that the range of the Obcb is not strictly
    01272     //  starting at the first Bcb) and add in locations for the first
    01273     //  bcb and the null.
    01274     //
    01275
    01276     LengthToAllocate = FIELD_OFFSET(OBCB, Bcbs) + (2 * sizeof(PBCB)) +
    01277                        ((Length -
    01278                          (Bcb->ByteLength -
    01279                           (FileOffset->HighPart?
    01280                            (ULONG)(FileOffset->QuadPart - Bcb->FileOffset.QuadPart) :
    01281                            FileOffset->LowPart - Bcb->FileOffset.LowPart)) +
    01282                          PAGE_SIZE - 1) / PAGE_SIZE) * sizeof(PBCB);
    01283
    01284     Obcb = FsRtlAllocatePoolWithTag( NonPagedPool, LengthToAllocate, 'bOcC' );
    01285     RtlZeroMemory( Obcb, LengthToAllocate );
    01286     Obcb->NodeTypeCode = CACHE_NTC_OBCB;
    01287     Obcb->NodeByteSize = (USHORT)LengthToAllocate;
    01288     Obcb->ByteLength = Length;
    01289     Obcb->FileOffset = *FileOffset;
    01290     Obcb->Bcbs[0] = FirstBcb;
    01291
    01292     return Obcb;
    01293 }
    }

BOOLEAN CcMapData | ( | IN PFILE_OBJECT | FileObject,
|  | IN PLARGE_INTEGER | FileOffset,
|  | IN ULONG | Length,
|  | IN BOOLEAN | Wait,
|  | OUT PVOID * | Bcb,
|  | OUT PVOID * | Buffer
| ) |

Definition at line 52 of file pinsup.c.

References ASSERT, Buffer, CcBcbSpinLock, CcGetVirtualAddress(), CcMapDataNoWait, CcMapDataNoWaitMiss, CcMapDataWait, CcMapDataWaitMiss, CcMissCounter, CcPinFileData(), CcThrowAway, CcUnpinFileData(), COMPUTE_PAGES_SPANNED, DebugTrace, FALSE, me, MmResetPageFaultReadAhead, MmSavePageFaultReadAhead, MmSetPageFaultReadAhead, NULL, PAGE_SIZE, PsGetCurrentThread, TRUE, and UNPIN.

Referenced by LfsFlushLfcb(), LfsPinOrMapData(), UdfLookupDirEntryPostProcessing(), UdfLookupInitialDirEntry(), UdfLookupPsnOfExtent(), UdfMapMetadataView(), and UdfUpdateVcbPhase0().

    00063                    :
    00064
    00065     This routine attempts to map the specified file data in the cache.
    00066     A pointer is returned to the desired data in the cache.
    00067
    00068     If the caller does not want to block on this call, then
    00069     Wait should be supplied as FALSE.  If Wait was supplied as FALSE and
    00070     it is currently impossible to supply the requested data without
    00071     blocking, then this routine will return FALSE.  However, if the
    00072     data is immediately accessible in the cache and no blocking is
    00073     required, this routine returns TRUE with a pointer to the data.
    00074
    00075     Note that a call to this routine with Wait supplied as TRUE is
    00076     considerably faster than a call with Wait supplies as FALSE, because
    00077     in the Wait TRUE case we only have to make sure the data is mapped
    00078     in order to return.
    00079
    00080     It is illegal to modify data that is only mapped, and can in fact lead
    00081     to serious problems.  It is impossible to check for this in all cases,
    00082     however CcSetDirtyPinnedData may implement some Assertions to check for
    00083     this.  If the caller wishes to modify data that it has only mapped, then
    00084     it must *first* call CcPinMappedData.
    00085
    00086     In any case, the caller MUST subsequently call CcUnpinData.
    00087     Naturally if CcPinRead or CcPreparePinWrite were called multiple
    00088     times for the same data, CcUnpinData must be called the same number
    00089     of times.
    00090
    00091     The returned Buffer pointer is valid until the data is unpinned, at
    00092     which point it is invalid to use the pointer further.  This buffer pointer
    00093     will remain valid if CcPinMappedData is called.
    00094
    00095     Note that under some circumstances (like Wait supplied as FALSE or more
    00096     than a page is requested), this routine may actually pin the data, however
    00097     it is not necessary, and in fact not correct, for the caller to be concerned
    00098     about this.
    00099
    00100 Arguments:
    00101
    00102     FileObject - Pointer to the file object for a file which was
    00103                  opened with NO_INTERMEDIATE_BUFFERING clear, i.e., for
    00104                  which CcInitializeCacheMap was called by the file system.
    00105
    00106     FileOffset - Byte offset in file for desired data.
    00107
    00108     Length - Length of desired data in bytes.
    00109
    00110     Wait - FALSE if caller may not block, TRUE otherwise (see description
    00111            above)
    00112
    00113     Bcb - On the first call this returns a pointer to a Bcb
    00114           parameter which must be supplied as input on all subsequent
    00115           calls, for this buffer
    00116
    00117     Buffer - Returns pointer to desired data, valid until the buffer is
    00118              unpinned or freed.  This pointer will remain valid if CcPinMappedData
    00119              is called.
    00120
    00121 Return Value:
    00122
    00123     FALSE - if Wait was supplied as FALSE and the data was not delivered
    00124
    00125     TRUE - if the data is being delivered
    00126
    00127 --*/
    00128
    00129 {
    00130     PSHARED_CACHE_MAP SharedCacheMap;
    00131     LARGE_INTEGER BeyondLastByte;
    00132     ULONG ReceivedLength;
    00133     ULONG SavedState;
    00134     volatile UCHAR ch;
    00135     ULONG PageCount = COMPUTE_PAGES_SPANNED((ULongToPtr(FileOffset->LowPart)), Length);
    00136     PETHREAD Thread = PsGetCurrentThread();
    00137
    00138     DebugTrace(+1, me, "CcMapData\n", 0 );
    00139
    00140     MmSavePageFaultReadAhead( Thread, &SavedState );
    00141
    00142     //
    00143     //  Increment performance counters
    00144     //
    00145
    00146     if (Wait) {
    00147
    00148         CcMapDataWait += 1;
    00149
    00150         //
    00151         //  Initialize the indirect pointer to our miss counter.
    00152         //
    00153
    00154         CcMissCounter = &CcMapDataWaitMiss;
    00155
    00156     } else {
    00157         CcMapDataNoWait += 1;
    00158     }
    00159
    00160     //
    00161     //  Get pointer to SharedCacheMap.
    00162     //
    00163
    00164     SharedCacheMap = *(PSHARED_CACHE_MAP *)((PCHAR)FileObject->SectionObjectPointer
    00165                                             + sizeof(PVOID));
    00166
    00167     //
    00168     //  Call local routine to Map or Access the file data.  If we cannot map
    00169     //  the data because of a Wait condition, return FALSE.
    00170     //
    00171
    00172     if (Wait) {
    00173
    00174         *Buffer = CcGetVirtualAddress( SharedCacheMap,
    00175                                        *FileOffset,
    00176                                        (PVACB *)Bcb,
    00177                                        &ReceivedLength );
    00178
    00179         ASSERT( ReceivedLength >= Length );
    00180
    00181     } else if (!CcPinFileData( FileObject,
    00182                                FileOffset,
    00183                                Length,
    00184                                TRUE,
    00185                                FALSE,
    00186                                Wait,
    00187                                (PBCB *)Bcb,
    00188                                Buffer,
    00189                                &BeyondLastByte )) {
    00190
    00191         DebugTrace(-1, me, "CcMapData -> FALSE\n", 0 );
    00192
    00193         CcMapDataNoWaitMiss += 1;
    00194
    00195         return FALSE;
    00196
    00197     } else {
    00198
    00199         ASSERT( (BeyondLastByte.QuadPart - FileOffset->QuadPart) >= Length );
    00200
    00201 #if LIST_DBG
    00202         {
    00203             KIRQL OldIrql;
    00204             PBCB BcbTemp = (PBCB)*Bcb;
    00205
    00206             ExAcquireSpinLock( &CcBcbSpinLock, &OldIrql );
    00207
    00208             if (BcbTemp->CcBcbLinks.Flink == NULL) {
    00209
    00210                 InsertTailList( &CcBcbList, &BcbTemp->CcBcbLinks );
    00211                 CcBcbCount += 1;
    00212                 ExReleaseSpinLock( &CcBcbSpinLock, OldIrql );
    00213                 SetCallersAddress( BcbTemp );
    00214
    00215             } else {
    00216                 ExReleaseSpinLock( &CcBcbSpinLock, OldIrql );
    00217             }
    00218
    00219         }
    00220 #endif
    00221
    00222     }
    00223
    00224     //
    00225     //  Now let's just sit here and take the miss(es) like a man (and count them).
    00226     //
    00227
    00228     try {
    00229
    00230         //
    00231         //  Loop to touch each page
    00232         //
    00233
    00234         BeyondLastByte.LowPart = 0;
    00235
    00236         while (PageCount != 0) {
    00237
    00238             MmSetPageFaultReadAhead( Thread, PageCount - 1 );
    00239
    00240             ch = *((volatile UCHAR *)(*Buffer) + BeyondLastByte.LowPart);
    00241
    00242             BeyondLastByte.LowPart += PAGE_SIZE;
    00243             PageCount -= 1;
    00244         }
    00245
    00246     } finally {
    00247
    00248         MmResetPageFaultReadAhead( Thread, SavedState );
    00249
    00250         if (AbnormalTermination() && (*Bcb != NULL)) {
    00251             CcUnpinFileData( (PBCB)*Bcb, TRUE, UNPIN );
    00252             *Bcb = NULL;
    00253         }
    00254     }
    00255
    00256     CcMissCounter = &CcThrowAway;
    00257
    00258     //
    00259     // Increment the pointer as a reminder that it is read only.
    00260     //
    00261
    00262     *(PCHAR *)Bcb += 1;
    00263
    00264     DebugTrace(-1, me, "CcMapData -> TRUE\n", 0 );
    00265
    00266     return TRUE;
    00267 }

BOOLEAN CcPinMappedData | ( | IN PFILE_OBJECT | FileObject,
|  | IN PLARGE_INTEGER | FileOffset,
|  | IN ULONG | Length,
|  | IN ULONG | Flags,
|  | IN OUT PVOID * | Bcb
| ) |

Definition at line 271 of file pinsup.c.

References BooleanFlagOn, Buffer, CACHE_NTC_BCB, CcAllocateObcb(), CcBcbSpinLock, CcFreeVirtualAddress(), CcPinFileData(), CcPinMappedDataCount, CcUnpinData(), DebugTrace, ExAcquireSharedStarveExclusive(), FALSE, FlagOn, _SHARED_CACHE_MAP::Flags, me, MODIFIED_WRITE_DISABLED, NULL, PIN_WAIT, Resource, TRUE, and try_return.

    00281                    :
    00282
    00283     This routine attempts to pin data that was previously only mapped.
    00284     If the routine determines that in fact it was necessary to actually
    00285     pin the data when CcMapData was called, then this routine does not
    00286     have to do anything.
    00287
    00288     If the caller does not want to block on this call, then
    00289     Wait should be supplied as FALSE.  If Wait was supplied as FALSE and
    00290     it is currently impossible to supply the requested data without
    00291     blocking, then this routine will return FALSE.  However, if the
    00292     data is immediately accessible in the cache and no blocking is
    00293     required, this routine returns TRUE with a pointer to the data.
    00294
    00295     If the data is not returned in the first call, the caller
    00296     may request the data later with Wait = TRUE.  It is not required
    00297     that the caller request the data later.
    00298
    00299     If the caller subsequently modifies the data, it should call
    00300     CcSetDirtyPinnedData.
    00301
    00302     In any case, the caller MUST subsequently call CcUnpinData.
    00303     Naturally if CcPinRead or CcPreparePinWrite were called multiple
    00304     times for the same data, CcUnpinData must be called the same number
    00305     of times.
    00306
    00307     Note there are no performance counters in this routine, as the misses
    00308     will almost always occur on the map above, and there will seldom be a
    00309     miss on this conversion.
    00310
    00311 Arguments:
    00312
    00313     FileObject - Pointer to the file object for a file which was
    00314                  opened with NO_INTERMEDIATE_BUFFERING clear, i.e., for
    00315                  which CcInitializeCacheMap was called by the file system.
    00316
    00317     FileOffset - Byte offset in file for desired data.
    00318
    00319     Length - Length of desired data in bytes.
    00320
    00321     Flags - (PIN_WAIT, PIN_EXCLUSIVE, PIN_NO_READ, etc. as defined in cache.h)
    00322             If the caller specifies PIN_NO_READ and PIN_EXCLUSIVE, then he must
    00323             guarantee that no one else will be attempting to map the view, if he
    00324             wants to guarantee that the Bcb is not mapped (view may be purged).
    00325             If the caller specifies PIN_NO_READ without PIN_EXCLUSIVE, the data
    00326             may or may not be mapped in the return Bcb.
    00327
    00328     Bcb - On the first call this returns a pointer to a Bcb
    00329           parameter which must be supplied as input on all subsequent
    00330           calls, for this buffer
    00331
    00332 Return Value:
    00333
    00334     FALSE - if Wait was not set and the data was not delivered
    00335
    00336     TRUE - if the data is being delivered
    00337
    00338 --*/
    00339
    00340 {
    00341     PVOID Buffer;
    00342     LARGE_INTEGER BeyondLastByte;
    00343     PSHARED_CACHE_MAP SharedCacheMap;
    00344     LARGE_INTEGER LocalFileOffset = *FileOffset;
    00345     POBCB MyBcb = NULL;
    00346     PBCB *CurrentBcbPtr = (PBCB *)&MyBcb;
    00347     BOOLEAN Result = FALSE;
    00348
    00349     DebugTrace(+1, me, "CcPinMappedData\n", 0 );
    00350
    00351     //
    00352     // If the Bcb is no longer ReadOnly, then just return.
    00353     //
    00354
    00355     if ((*(PULONG)Bcb & 1) == 0) {
    00356         return TRUE;
    00357     }
    00358
    00359     //
    00360     // Remove the Read Only flag
    00361     //
    00362
    00363     *(PCHAR *)Bcb -= 1;
    00364
    00365     //
    00366     //  Get pointer to SharedCacheMap.
    00367     //
    00368
    00369     SharedCacheMap = *(PSHARED_CACHE_MAP *)((PCHAR)FileObject->SectionObjectPointer
    00370                                             + sizeof(PVOID));
    00371
    00372     //
    00373     //  We only count the calls to this routine, since they are almost guaranteed
    00374     //  to be hits.
    00375     //
    00376
    00377     CcPinMappedDataCount += 1;
    00378
    00379     //
    00380     //  Guarantee we will put the flag back if required.
    00381     //
    00382
    00383     try {
    00384
    00385         if (((PBCB)*Bcb)->NodeTypeCode != CACHE_NTC_BCB) {
    00386
    00387             //
    00388             //  Form loop to handle occassional overlapped Bcb case.
    00389             //
    00390
    00391             do {
    00392
    00393                 //
    00394                 //  If we have already been through the loop, then adjust
    00395                 //  our file offset and length from the last time.
    00396                 //
    00397
    00398                 if (MyBcb != NULL) {
    00399
    00400                     //
    00401                     //  If this is the second time through the loop, then it is time
    00402                     //  to handle the overlap case and allocate an OBCB.
    00403                     //
    00404
    00405                     if (CurrentBcbPtr == (PBCB *)&MyBcb) {
    00406
    00407                         MyBcb = CcAllocateObcb( FileOffset, Length, (PBCB)MyBcb );
    00408
    00409                         //
    00410                         //  Set CurrentBcbPtr to point at the first entry in
    00411                         //  the vector (which is already filled in), before
    00412                         //  advancing it below.
    00413                         //
    00414
    00415                         CurrentBcbPtr = &MyBcb->Bcbs[0];
    00416                     }
    00417
    00418                     Length -= (ULONG)(BeyondLastByte.QuadPart - LocalFileOffset.QuadPart);
    00419                     LocalFileOffset.QuadPart = BeyondLastByte.QuadPart;
    00420                     CurrentBcbPtr += 1;
    00421                 }
    00422
    00423                 //
    00424                 //  Call local routine to Map or Access the file data.  If we cannot map
    00425                 //  the data because of a Wait condition, return FALSE.
    00426                 //
    00427
    00428                 if (!CcPinFileData( FileObject,
    00429                                     &LocalFileOffset,
    00430                                     Length,
    00431                                     (BOOLEAN)!FlagOn(SharedCacheMap->Flags, MODIFIED_WRITE_DISABLED),
    00432                                     FALSE,
    00433                                     Flags,
    00434                                     CurrentBcbPtr,
    00435                                     &Buffer,
    00436                                     &BeyondLastByte )) {
    00437
    00438                     try_return( Result = FALSE );
    00439                 }
    00440
    00441             //
    00442             //  Continue looping if we did not get everything.
    00443             //
    00444
    00445             } while((BeyondLastByte.QuadPart - LocalFileOffset.QuadPart) < Length);
    00446
    00447             //
    00448             //  Free the Vacb before going on.
    00449             //
    00450
    00451             CcFreeVirtualAddress( (PVACB)*Bcb );
    00452
    00453             *Bcb = MyBcb;
    00454
    00455             //
    00456             //  Debug routines used to insert and remove Bcbs from the global list
    00457             //
    00458
    00459 #if LIST_DBG
    00460             {
    00461                 KIRQL OldIrql;
    00462                 PBCB BcbTemp = (PBCB)*Bcb;
    00463
    00464                 ExAcquireSpinLock( &CcBcbSpinLock, &OldIrql );
    00465
    00466                 if (BcbTemp->CcBcbLinks.Flink == NULL) {
    00467
    00468                     InsertTailList( &CcBcbList, &BcbTemp->CcBcbLinks );
    00469                     CcBcbCount += 1;
    00470                     ExReleaseSpinLock( &CcBcbSpinLock, OldIrql );
    00471                     SetCallersAddress( BcbTemp );
    00472
    00473                 } else {
    00474                     ExReleaseSpinLock( &CcBcbSpinLock, OldIrql );
    00475                 }
    00476
    00477             }
    00478 #endif
    00479         }
    00480
    00481         //
    00482         //  If he really has a Bcb, all we have to do is acquire it shared since he is
    00483         //  no longer ReadOnly.
    00484         //
    00485
    00486         else {
    00487
    00488             if (!ExAcquireSharedStarveExclusive( &((PBCB)*Bcb)->Resource, BooleanFlagOn(Flags, PIN_WAIT))) {
    00489
    00490                 try_return( Result = FALSE );
    00491             }
    00492         }
    00493
    00494         Result = TRUE;
    00495
    00496     try_exit: NOTHING;
    00497     }
    00498     finally {
    00499
    00500         if (!Result) {
    00501
    00502             //
    00503             //  Put the Read Only flag back
    00504             //
    00505
    00506             *(PCHAR *)Bcb += 1;
    00507
    00508             //
    00509             //  We may have gotten partway through
    00510             //
    00511
    00512             if (MyBcb != NULL) {
    00513                 CcUnpinData( MyBcb );
    00514             }
    00515         }
    00516
    00517         DebugTrace(-1, me, "CcPinMappedData -> %02lx\n", Result );
    00518     }
    00519     return Result;
    00520 }

BOOLEAN CcPinRead | ( | IN PFILE_OBJECT | FileObject,
|  | IN PLARGE_INTEGER | FileOffset,
|  | IN ULONG | Length,
|  | IN ULONG | Flags,
|  | OUT PVOID * | Bcb,
|  | OUT PVOID * | Buffer
| ) |

Definition at line 524 of file pinsup.c.

References Buffer, CcAllocateObcb(), CcBcbSpinLock, CcMissCounter, CcPinFileData(), CcPinReadNoWait, CcPinReadNoWaitMiss, CcPinReadWait, CcPinReadWaitMiss, CcThrowAway, CcUnpinData(), DebugTrace, FALSE, FlagOn, _SHARED_CACHE_MAP::Flags, me, MODIFIED_WRITE_DISABLED, NULL, PIN_WAIT, TRUE, and try_return.

Referenced by LfsPinOrMapData().

    00535                    :
    00536
    00537     This routine attempts to pin the specified file data in the cache.
    00538     A pointer is returned to the desired data in the cache.  This routine
    00539     is intended for File System support and is not intended to be called
    00540     from Dpc level.
    00541
    00542     If the caller does not want to block on this call, then
    00543     Wait should be supplied as FALSE.  If Wait was supplied as FALSE and
    00544     it is currently impossible to supply the requested data without
    00545     blocking, then this routine will return FALSE.  However, if the
    00546     data is immediately accessible in the cache and no blocking is
    00547     required, this routine returns TRUE with a pointer to the data.
    00548
    00549     If the data is not returned in the first call, the caller
    00550     may request the data later with Wait = TRUE.  It is not required
    00551     that the caller request the data later.
    00552
    00553     If the caller subsequently modifies the data, it should call
    00554     CcSetDirtyPinnedData.
    00555
    00556     In any case, the caller MUST subsequently call CcUnpinData.
    00557     Naturally if CcPinRead or CcPreparePinWrite were called multiple
    00558     times for the same data, CcUnpinData must be called the same number
    00559     of times.
    00560
    00561     The returned Buffer pointer is valid until the data is unpinned, at
    00562     which point it is invalid to use the pointer further.
    00563
    00564 Arguments:
    00565
    00566     FileObject - Pointer to the file object for a file which was
    00567                  opened with NO_INTERMEDIATE_BUFFERING clear, i.e., for
    00568                  which CcInitializeCacheMap was called by the file system.
    00569
    00570     FileOffset - Byte offset in file for desired data.
    00571
    00572     Length - Length of desired data in bytes.
    00573
    00574     Flags - (PIN_WAIT, PIN_EXCLUSIVE, PIN_NO_READ, etc. as defined in cache.h)
    00575             If the caller specifies PIN_NO_READ and PIN_EXCLUSIVE, then he must
    00576             guarantee that no one else will be attempting to map the view, if he
    00577             wants to guarantee that the Bcb is not mapped (view may be purged).
    00578             If the caller specifies PIN_NO_READ without PIN_EXCLUSIVE, the data
    00579             may or may not be mapped in the return Bcb.
    00580
    00581     Bcb - On the first call this returns a pointer to a Bcb
    00582           parameter which must be supplied as input on all subsequent
    00583           calls, for this buffer
    00584
    00585     Buffer - Returns pointer to desired data, valid until the buffer is
    00586              unpinned or freed.
    00587
    00588 Return Value:
    00589
    00590     FALSE - if Wait was not set and the data was not delivered
    00591
    00592     TRUE - if the data is being delivered
    00593
    00594 --*/
    00595
    00596 {
    00597     PSHARED_CACHE_MAP SharedCacheMap;
    00598     PVOID LocalBuffer;
    00599     LARGE_INTEGER BeyondLastByte;
    00600     LARGE_INTEGER LocalFileOffset = *FileOffset;
    00601     POBCB MyBcb = NULL;
    00602     PBCB *CurrentBcbPtr = (PBCB *)&MyBcb;
    00603     BOOLEAN Result = FALSE;
    00604
    00605     DebugTrace(+1, me, "CcPinRead\n", 0 );
    00606
    00607     //
    00608     //  Increment performance counters
    00609     //
    00610
    00611     if (FlagOn(Flags, PIN_WAIT)) {
    00612
    00613         CcPinReadWait += 1;
    00614
    00615         //
    00616         //  Initialize the indirect pointer to our miss counter.
    00617         //
    00618
    00619         CcMissCounter = &CcPinReadWaitMiss;
    00620
    00621     } else {
    00622         CcPinReadNoWait += 1;
    00623     }
    00624
    00625     //
    00626     //  Get pointer to SharedCacheMap.
    00627     //
    00628
    00629     SharedCacheMap = *(PSHARED_CACHE_MAP *)((PCHAR)FileObject->SectionObjectPointer
    00630                                             + sizeof(PVOID));
    00631
    00632     try {
    00633
    00634         //
    00635         //  Form loop to handle occassional overlapped Bcb case.
    00636         //
    00637
    00638         do {
    00639
    00640             //
    00641             //  If we have already been through the loop, then adjust
    00642             //  our file offset and length from the last time.
    00643             //
    00644
    00645             if (MyBcb != NULL) {
    00646
    00647                 //
    00648                 //  If this is the second time through the loop, then it is time
    00649                 //  to handle the overlap case and allocate an OBCB.
    00650                 //
    00651
    00652                 if (CurrentBcbPtr == (PBCB *)&MyBcb) {
    00653
    00654                     MyBcb = CcAllocateObcb( FileOffset, Length, (PBCB)MyBcb );
    00655
    00656                     //
    00657                     //  Set CurrentBcbPtr to point at the first entry in
    00658                     //  the vector (which is already filled in), before
    00659                     //  advancing it below.
    00660                     //
    00661
    00662                     CurrentBcbPtr = &MyBcb->Bcbs[0];
    00663
    00664                     //
    00665                     //  Also on second time through, return starting Buffer
    00666                     //
    00667
    00668                     *Buffer = LocalBuffer;
    00669                 }
    00670
    00671                 Length -= (ULONG)(BeyondLastByte.QuadPart - LocalFileOffset.QuadPart);
    00672                 LocalFileOffset.QuadPart = BeyondLastByte.QuadPart;
    00673                 CurrentBcbPtr += 1;
    00674             }
    00675
    00676             //
    00677             //  Call local routine to Map or Access the file data.  If we cannot map
    00678             //  the data because of a Wait condition, return FALSE.
    00679             //
    00680
    00681             if (!CcPinFileData( FileObject,
    00682                                 &LocalFileOffset,
    00683                                 Length,
    00684                                 (BOOLEAN)!FlagOn(SharedCacheMap->Flags, MODIFIED_WRITE_DISABLED),
    00685                                 FALSE,
    00686                                 Flags,
    00687                                 CurrentBcbPtr,
    00688                                 &LocalBuffer,
    00689                                 &BeyondLastByte )) {
    00690
    00691                 CcPinReadNoWaitMiss += 1;
    00692
    00693                 try_return( Result = FALSE );
    00694             }
    00695
    00696         //
    00697         //  Continue looping if we did not get everything.
    00698         //
    00699
    00700         } while((BeyondLastByte.QuadPart - LocalFileOffset.QuadPart) < Length);
    00701
    00702         *Bcb = MyBcb;
    00703
    00704         //
    00705         //  Debug routines used to insert and remove Bcbs from the global list
    00706         //
    00707
    00708 #if LIST_DBG
    00709
    00710         {
    00711             KIRQL OldIrql;
    00712             PBCB BcbTemp = (PBCB)*Bcb;
    00713
    00714             ExAcquireSpinLock( &CcBcbSpinLock, &OldIrql );
    00715
    00716             if (BcbTemp->CcBcbLinks.Flink == NULL) {
    00717
    00718                 InsertTailList( &CcBcbList, &BcbTemp->CcBcbLinks );
    00719                 CcBcbCount += 1;
    00720                 ExReleaseSpinLock( &CcBcbSpinLock, OldIrql );
    00721                 SetCallersAddress( BcbTemp );
    00722
    00723             } else {
    00724                 ExReleaseSpinLock( &CcBcbSpinLock, OldIrql );
    00725             }
    00726
    00727         }
    00728
    00729 #endif
    00730
    00731         //
    00732         //  In the normal (nonoverlapping) case we return the
    00733         //  correct buffer address here.
    00734         //
    00735
    00736         if (CurrentBcbPtr == (PBCB *)&MyBcb) {
    00737             *Buffer = LocalBuffer;
    00738         }
    00739
    00740         Result = TRUE;
    00741
    00742     try_exit: NOTHING;
    00743     }
    00744     finally {
    00745
    00746         CcMissCounter = &CcThrowAway;
    00747
    00748         if (!Result) {
    00749
    00750             //
    00751             //  We may have gotten partway through
    00752             //
    00753
    00754             if (MyBcb != NULL) {
    00755                 CcUnpinData( MyBcb );
    00756             }
    00757         }
    00758
    00759         DebugTrace(-1, me, "CcPinRead -> %02lx\n", Result );
    00760     }
    00761
    00762     return Result;
    00763 }

BOOLEAN CcPreparePinWrite | ( | IN PFILE_OBJECT | FileObject,
|  | IN PLARGE_INTEGER | FileOffset,
|  | IN ULONG | Length,
|  | IN BOOLEAN | Zero,
|  | IN ULONG | Flags,
|  | OUT PVOID * | Bcb,
|  | OUT PVOID * | Buffer
| ) |

Definition at line 767 of file pinsup.c.

References Buffer, CcAllocateObcb(), CcBcbSpinLock, CcMissCounter, CcPinFileData(), CcSetDirtyPinnedData(), CcThrowAway, CcUnpinData(), DebugTrace, FALSE, me, NULL, TRUE, try_return, and Zero.

    00779                    :
    00780
    00781     This routine attempts to lock the specified file data in the cache
    00782     and return a pointer to it along with the correct
    00783     I/O status.  Pages to be completely overwritten may be satisfied
    00784     with emtpy pages.
    00785
    00786     If not all of the pages can be prepared, and Wait was supplied as
    00787     FALSE, then this routine will return FALSE, and its outputs will
    00788     be meaningless.  The caller may request the data later with
    00789     Wait = TRUE.  However, it is not required that the caller request
    00790     the data later.
    00791
    00792     If Wait is supplied as TRUE, and all of the pages can be prepared
    00793     without blocking, this call will return TRUE immediately.  Otherwise,
    00794     this call will block until all of the pages can be prepared, and
    00795     then return TRUE.
    00796
    00797     When this call returns with TRUE, the caller may immediately begin
    00798     to transfer data into the buffers via the Buffer pointer.  The
    00799     buffer will already be marked dirty.
    00800
    00801     The caller MUST subsequently call CcUnpinData.
    00802     Naturally if CcPinRead or CcPreparePinWrite were called multiple
    00803     times for the same data, CcUnpinData must be called the same number
    00804     of times.
    00805
    00806     The returned Buffer pointer is valid until the data is unpinned, at
    00807     which point it is invalid to use the pointer further.
    00808
    00809 Arguments:
    00810
    00811     FileObject - Pointer to the file object for a file which was
    00812                  opened with NO_INTERMEDIATE_BUFFERING clear, i.e., for
    00813                  which CcInitializeCacheMap was called by the file system.
    00814
    00815     FileOffset - Byte offset in file for desired data.
    00816
    00817     Length - Length of desired data in bytes.
    00818
    00819     Zero - If supplied as TRUE, the buffer will be zeroed on return.
    00820
    00821     Flags - (PIN_WAIT, PIN_EXCLUSIVE, PIN_NO_READ, etc. as defined in cache.h)
    00822             If the caller specifies PIN_NO_READ and PIN_EXCLUSIVE, then he must
    00823             guarantee that no one else will be attempting to map the view, if he
    00824             wants to guarantee that the Bcb is not mapped (view may be purged).
    00825             If the caller specifies PIN_NO_READ without PIN_EXCLUSIVE, the data
    00826             may or may not be mapped in the return Bcb.
    00827
    00828     Bcb - This returns a pointer to a Bcb parameter which must be
    00829           supplied as input to CcPinWriteComplete.
    00830
    00831     Buffer - Returns pointer to desired data, valid until the buffer is
    00832              unpinned or freed.
    00833
    00834 Return Value:
    00835
    00836     FALSE - if Wait was not set and the data was not delivered
    00837
    00838     TRUE - if the pages are being delivered
    00839
    00840 --*/
    00841
    00842 {
    00843     PSHARED_CACHE_MAP SharedCacheMap;
    00844     PVOID LocalBuffer;
    00845     LARGE_INTEGER BeyondLastByte;
    00846     LARGE_INTEGER LocalFileOffset = *FileOffset;
    00847     POBCB MyBcb = NULL;
    00848     PBCB *CurrentBcbPtr = (PBCB *)&MyBcb;
    00849     ULONG OriginalLength = Length;
    00850     BOOLEAN Result = FALSE;
    00851
    00852     DebugTrace(+1, me, "CcPreparePinWrite\n", 0 );
    00853
    00854     //
    00855     //  Get pointer to SharedCacheMap.
    00856     //
    00857
    00858     SharedCacheMap = *(PSHARED_CACHE_MAP *)((PCHAR)FileObject->SectionObjectPointer
    00859                                             + sizeof(PVOID));
    00860
    00861     try {
    00862
    00863         //
    00864         //  Form loop to handle occassional overlapped Bcb case.
    00865         //
    00866
    00867         do {
    00868
    00869             //
    00870             //  If we have already been through the loop, then adjust
    00871             //  our file offset and length from the last time.
    00872             //
    00873
    00874             if (MyBcb != NULL) {
    00875
    00876                 //
    00877                 //  If this is the second time through the loop, then it is time
    00878                 //  to handle the overlap case and allocate an OBCB.
    00879                 //
    00880
    00881                 if (CurrentBcbPtr == (PBCB *)&MyBcb) {
    00882
    00883                     MyBcb = CcAllocateObcb( FileOffset, Length, (PBCB)MyBcb );
    00884
    00885                     //
    00886                     //  Set CurrentBcbPtr to point at the first entry in
    00887                     //  the vector (which is already filled in), before
    00888                     //  advancing it below.
    00889                     //
    00890
    00891                     CurrentBcbPtr = &MyBcb->Bcbs[0];
    00892
    00893                     //
    00894                     //  Also on second time through, return starting Buffer
    00895                     //
    00896
    00897                     *Buffer = LocalBuffer;
    00898                 }
    00899
    00900                 Length -= (ULONG)(BeyondLastByte.QuadPart - LocalFileOffset.QuadPart);
    00901                 LocalFileOffset.QuadPart = BeyondLastByte.QuadPart;
    00902                 CurrentBcbPtr += 1;
    00903             }
    00904
    00905             //
    00906             //  Call local routine to Map or Access the file data.  If we cannot map
    00907             //  the data because of a Wait condition, return FALSE.
    00908             //
    00909
    00910             if (!CcPinFileData( FileObject,
    00911                                 &LocalFileOffset,
    00912                                 Length,
    00913                                 FALSE,
    00914                                 TRUE,
    00915                                 Flags,
    00916                                 CurrentBcbPtr,
    00917                                 &LocalBuffer,
    00918                                 &BeyondLastByte )) {
    00919
    00920                 try_return( Result = FALSE );
    00921             }
    00922
    00923         //
    00924         //  Continue looping if we did not get everything.
    00925         //
    00926
    00927         } while((BeyondLastByte.QuadPart - LocalFileOffset.QuadPart) < Length);
    00928
    00929         *Bcb = MyBcb;
    00930
    00931         //
    00932         //  Debug routines used to insert and remove Bcbs from the global list
    00933         //
    00934
    00935 #if LIST_DBG
    00936
    00937         {
    00938             KIRQL OldIrql;
    00939             PBCB BcbTemp = (PBCB)*Bcb;
    00940
    00941             ExAcquireSpinLock( &CcBcbSpinLock, &OldIrql );
    00942
    00943             if (BcbTemp->CcBcbLinks.Flink == NULL) {
    00944
    00945                 InsertTailList( &CcBcbList, &BcbTemp->CcBcbLinks );
    00946                 CcBcbCount += 1;
    00947                 ExReleaseSpinLock( &CcBcbSpinLock, OldIrql );
    00948                 SetCallersAddress( BcbTemp );
    00949
    00950             } else {
    00951                 ExReleaseSpinLock( &CcBcbSpinLock, OldIrql );
    00952             }
    00953
    00954         }
    00955
    00956 #endif
    00957
    00958         //
    00959         //  In the normal (nonoverlapping) case we return the
    00960         //  correct buffer address here.
    00961         //
    00962
    00963         if (CurrentBcbPtr == (PBCB *)&MyBcb) {
    00964             *Buffer = LocalBuffer;
    00965         }
    00966
    00967         if (Zero) {
    00968             RtlZeroMemory( *Buffer, OriginalLength );
    00969         }
    00970
    00971         CcSetDirtyPinnedData( MyBcb, NULL );
    00972
    00973         Result = TRUE;
    00974
    00975     try_exit: NOTHING;
    00976     }
    00977     finally {
    00978
    00979         CcMissCounter = &CcThrowAway;
    00980
    00981         if (!Result) {
    00982
    00983             //
    00984             //  We may have gotten partway through
    00985             //
    00986
    00987             if (MyBcb != NULL) {
    00988                 CcUnpinData( MyBcb );
    00989             }
    00990         }
    00991
    00992         DebugTrace(-1, me, "CcPreparePinWrite -> %02lx\n", Result );
    00993     }
    00994
    00995     return Result;
    00996 }

VOID CcSetBcbOwnerPointer | ( | IN PVOID | Bcb,
|  | IN PVOID | OwnerPointer
| ) |

Definition at line 1078 of file pinsup.c.

References ASSERT, CACHE_NTC_OBCB, ExSetResourceOwnerPointer(), NULL, and Resource.

Referenced by LfsGetLbcb().

    01085                    :
    01086
    01087     This routine may be called to set the resource owner for the Bcb resource,
    01088     for cases where another thread will do the unpin *and* the current thread
    01089     may exit.
    01090
    01091 Arguments:
    01092
    01093     Bcb - Bcb parameter returned from the last call to CcPinRead.
    01094
    01095     OwnerPointer - A valid resource owner pointer, which means a pointer to
    01096                    an allocated system address, with the low-order two bits
    01097                    set.  The address may not be deallocated until after the
    01098                    unpin call.
    01099
    01100 Return Value:
    01101
    01102     None.
    01103
    01104 --*/
    01105
    01106 {
    01107     ASSERT(((ULONG_PTR)Bcb & 1) == 0);
    01108
    01109     //
    01110     //  Handle the overlapped Bcb case.
    01111     //
    01112
    01113     if (((POBCB)Bcb)->NodeTypeCode == CACHE_NTC_OBCB) {
    01114
    01115         PBCB *BcbPtrPtr = &((POBCB)Bcb)->Bcbs[0];
    01116
    01117         //
    01118         //  Loop to set owner for all Bcbs.
    01119         //
    01120
    01121         while (*BcbPtrPtr != NULL) {
    01122             ExSetResourceOwnerPointer( &(*BcbPtrPtr)->Resource, OwnerPointer );
    01123             BcbPtrPtr++;
    01124         }
    01125
    01126     //
    01127     //  Otherwise, it is a normal Bcb
    01128     //
    01129
    01130     } else {
    01131
    01132         //
    01133         //  Handle normal case.
    01134         //
    01135
    01136         ExSetResourceOwnerPointer( &((PBCB)Bcb)->Resource, OwnerPointer );
    01137     }
    01138 }

VOID CcUnpinData | ( | IN PVOID | Bcb | ) |

Definition at line 1000 of file pinsup.c.

References CACHE_NTC_OBCB, CcUnpinFileData(), DebugTrace, ExFreePool(), FALSE, me, NULL, TRUE, and UNPIN.

Referenced by CcPinMappedData(), CcPinRead(), CcPreparePinWrite(), LfsCopyReadLogRecord(), LfsDeallocateLcb(), LfsFindLastLsn(), LfsFindNextLsn(), LfsFlushLfcb(), LfsFlushLogPage(), LfsGetLbcb(), LfsInitializeLogFilePriv(), LfsPinOrMapData(), LfsReadNextLogRecord(), LfsReadRestart(), LfsReadRestartArea(), LfsRestartLogFile(), and LfsSearchForwardByClient().

    01006                    :
    01007
    01008     This routine must be called at IPL0, some time after calling CcPinRead
    01009     or CcPreparePinWrite.  It performs any cleanup that is necessary.
    01010
    01011 Arguments:
    01012
    01013     Bcb - Bcb parameter returned from the last call to CcPinRead.
    01014
    01015 Return Value:
    01016
    01017     None.
    01018
    01019 --*/
    01020
    01021 {
    01022     DebugTrace(+1, me, "CcUnpinData:\n", 0 );
    01023     DebugTrace( 0, me, "    >Bcb = %08lx\n", Bcb );
    01024
    01025     //
    01026     //  Test for ReadOnly and unpin accordingly.
    01027     //
    01028
    01029     if (((ULONG_PTR)Bcb & 1) != 0) {
    01030
    01031         //
    01032         //  Remove the Read Only flag
    01033         //
    01034
    01035         (PCHAR)Bcb -= 1;
    01036
    01037         CcUnpinFileData( (PBCB)Bcb, TRUE, UNPIN );
    01038
    01039     } else {
    01040
    01041         //
    01042         //  Handle the overlapped Bcb case.
    01043         //
    01044
    01045         if (((POBCB)Bcb)->NodeTypeCode == CACHE_NTC_OBCB) {
    01046
    01047             PBCB *BcbPtrPtr = &((POBCB)Bcb)->Bcbs[0];
    01048
    01049             //
    01050             //  Loop to free all Bcbs with recursive calls
    01051             //  (rather than dealing with RO for this uncommon case).
    01052             //
    01053
    01054             while (*BcbPtrPtr != NULL) {
    01055                 CcUnpinData(*(BcbPtrPtr++));
    01056             }
    01057
    01058             //
    01059             //  Then free the pool for the Obcb
    01060             //
    01061
    01062             ExFreePool( Bcb );
    01063
    01064         //
    01065         //  Otherwise, it is a normal Bcb
    01066         //
    01067
    01068         } else {
    01069             CcUnpinFileData( (PBCB)Bcb, FALSE, UNPIN );
    01070         }
    01071     }
    01072
    01073     DebugTrace(-1, me, "CcUnPinData -> VOID\n", 0 );
    01074 }

VOID CcUnpinDataForThread | ( | IN PVOID | Bcb,
|  | IN ERESOURCE_THREAD | ResourceThreadId
| ) |

Definition at line 1142 of file pinsup.c.

References CACHE_NTC_OBCB, CcUnpinFileData(), DebugTrace, ExFreePool(), ExReleaseResourceForThread, me, NULL, Resource, TRUE, and UNPIN.

Referenced by LfsCloseLogFile(), and LfsFlushLfcb().

    01149                    :
    01150
    01151     This routine must be called at IPL0, some time after calling CcPinRead
    01152     or CcPreparePinWrite.  It performs any cleanup that is necessary,
    01153     releasing the Bcb resource for the given thread.
    01154
    01155 Arguments:
    01156
    01157     Bcb - Bcb parameter returned from the last call to CcPinRead.
    01158
    01159 Return Value:
    01160
    01161     None.
    01162
    01163 --*/
    01164
    01165 {
    01166     DebugTrace(+1, me, "CcUnpinDataForThread:\n", 0 );
    01167     DebugTrace( 0, me, "    >Bcb = %08lx\n", Bcb );
    01168     DebugTrace( 0, me, "    >ResoureceThreadId = %08lx\n", ResoureceThreadId );
    01169
    01170     //
    01171     //  Test for ReadOnly and unpin accordingly.
    01172     //
    01173
    01174     if (((ULONG_PTR)Bcb & 1) != 0) {
    01175
    01176         //
    01177         //  Remove the Read Only flag
    01178         //
    01179
    01180         (PCHAR)Bcb -= 1;
    01181
    01182         CcUnpinFileData( (PBCB)Bcb, TRUE, UNPIN );
    01183
    01184     } else {
    01185
    01186         //
    01187         //  Handle the overlapped Bcb case.
    01188         //
    01189
    01190         if (((POBCB)Bcb)->NodeTypeCode == CACHE_NTC_OBCB) {
    01191
    01192             PBCB *BcbPtrPtr = &((POBCB)Bcb)->Bcbs[0];
    01193
    01194             //
    01195             //  Loop to free all Bcbs with recursive calls
    01196             //  (rather than dealing with RO for this uncommon case).
    01197             //
    01198
    01199             while (*BcbPtrPtr != NULL) {
    01200                 CcUnpinDataForThread( *(BcbPtrPtr++), ResourceThreadId );
    01201             }
    01202
    01203             //
    01204             //  Then free the pool for the Obcb
    01205             //
    01206
    01207             ExFreePool( Bcb );
    01208
    01209         //
    01210         //  Otherwise, it is a normal Bcb
    01211         //
    01212
    01213         } else {
    01214
    01215             //
    01216             //  If not readonly, we can release the resource for the thread first,
    01217             //  and then call CcUnpinFileData.  Release resource first in case
    01218             //  Bcb gets deallocated.
    01219             //
    01220
    01221             ExReleaseResourceForThread( &((PBCB)Bcb)->Resource, ResourceThreadId );
    01222             CcUnpinFileData( (PBCB)Bcb, TRUE, UNPIN );
    01223         }
    01224     }
    01225     DebugTrace(-1, me, "CcUnpinDataForThread -> VOID\n", 0 );
    01226 }