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 }


Generated on Sat May 15 19:45:09 2004 for test by doxygen 1.3.7