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

logsup.c File Reference

#include "cc.h"

Go to the source code of this file.

Defines

#define me   0x0000040

Functions

VOID CcSetAdditionalCacheAttributes (IN PFILE_OBJECT FileObject, IN BOOLEAN DisableReadAhead, IN BOOLEAN DisableWriteBehind)
VOID CcSetLogHandleForFile (IN PFILE_OBJECT FileObject, IN PVOID LogHandle, IN PFLUSH_TO_LSN FlushToLsnRoutine)
LARGE_INTEGER CcGetDirtyPages (IN PVOID LogHandle, IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine, IN PVOID Context1, IN PVOID Context2)
BOOLEAN CcIsThereDirtyData (IN PVPB Vpb)
LARGE_INTEGER CcGetLsnForFileObject (IN PFILE_OBJECT FileObject, OUT PLARGE_INTEGER OldestLsn OPTIONAL)


Define Documentation

#define me   0x0000040
 

Definition at line 28 of file logsup.c.


Function Documentation

LARGE_INTEGER CcGetDirtyPages IN PVOID  LogHandle,
IN PDIRTY_PAGE_ROUTINE  DirtyPageRoutine,
IN PVOID  Context1,
IN PVOID  Context2
 

Definition at line 142 of file logsup.c.

References _BCB::BcbLinks, _SHARED_CACHE_MAP::BcbList, _SHARED_CACHE_MAP::BcbSpinLock, _BCB::ByteLength, CACHE_NTC_BCB, CcAcquireMasterLock, CcDecrementOpenCount, CcDirtySharedCacheMapList, CcIncrementOpenCount, CcReleaseMasterLock, CcUnpinFileData(), Context1, Context2, _BCB::Dirty, _SHARED_CACHE_MAP::DirtyPages, _SHARED_CACHE_MAP::FileObject, _BCB::FileOffset, FlagOn, _SHARED_CACHE_MAP::Flags, IS_CURSOR, _SHARED_CACHE_MAP::LogHandle, _BCB::NewestLsn, _BCB::NodeTypeCode, NTSTATUS(), NULL, _BCB::OldestLsn, _BCB::PinCount, _SHARED_CACHE_MAP_LIST_CURSOR::SharedCacheMapLinks, _SHARED_CACHE_MAP::SharedCacheMapLinks, TRUE, UNPIN, and UNREF.

00151 : 00152 00153 This routine may be called to return all of the dirty pages in all files 00154 for a given log handle. Each page is returned by an individual call to 00155 the Dirty Page Routine. The Dirty Page Routine is defined by a prototype 00156 in ntos\inc\cache.h. 00157 00158 Arguments: 00159 00160 LogHandle - Log Handle which must match the log handle previously stored 00161 for all files which are to be returned. 00162 00163 DirtyPageRoutine -- The routine to call as each dirty page for this log 00164 handle is found. 00165 00166 Context1 - First context parameter to be passed to the Dirty Page Routine. 00167 00168 Context2 - First context parameter to be passed to the Dirty Page Routine. 00169 00170 Return Value: 00171 00172 LARGE_INTEGER - Oldest Lsn found of all the dirty pages, or 0 if no dirty pages 00173 00174 --*/ 00175 00176 { 00177 PSHARED_CACHE_MAP SharedCacheMap; 00178 PBCB Bcb, BcbToUnpin = NULL; 00179 KIRQL OldIrql; 00180 NTSTATUS ExceptionStatus; 00181 LARGE_INTEGER SavedFileOffset, SavedOldestLsn, SavedNewestLsn; 00182 ULONG SavedByteLength; 00183 LARGE_INTEGER OldestLsn = {0,0}; 00184 00185 // 00186 // Synchronize with changes to the SharedCacheMap list. 00187 // 00188 00189 CcAcquireMasterLock( &OldIrql ); 00190 00191 SharedCacheMap = CONTAINING_RECORD( CcDirtySharedCacheMapList.SharedCacheMapLinks.Flink, 00192 SHARED_CACHE_MAP, 00193 SharedCacheMapLinks ); 00194 00195 // 00196 // Use try/finally for cleanup. The only spot where we can raise is out of the 00197 // filesystem callback, but we have the exception handler out here so we aren't 00198 // constantly setting/unsetting it. 00199 // 00200 00201 try { 00202 00203 while (&SharedCacheMap->SharedCacheMapLinks != &CcDirtySharedCacheMapList.SharedCacheMapLinks) { 00204 00205 // 00206 // Skip over cursors, SharedCacheMaps for other LogHandles, and ones with 00207 // no dirty pages 00208 // 00209 00210 if (!FlagOn(SharedCacheMap->Flags, IS_CURSOR) && (SharedCacheMap->LogHandle == LogHandle) && 00211 (SharedCacheMap->DirtyPages != 0)) { 00212 00213 // 00214 // This SharedCacheMap should stick around for a while in the dirty list. 00215 // 00216 00217 CcIncrementOpenCount( SharedCacheMap, 'pdGS' ); 00218 SharedCacheMap->DirtyPages += 1; 00219 CcReleaseMasterLock( OldIrql ); 00220 00221 // 00222 // Set our initial resume point and point to first Bcb in List. 00223 // 00224 00225 ExAcquireFastLock( &SharedCacheMap->BcbSpinLock, &OldIrql ); 00226 Bcb = CONTAINING_RECORD( SharedCacheMap->BcbList.Flink, BCB, BcbLinks ); 00227 00228 // 00229 // Scan to the end of the Bcb list. 00230 // 00231 00232 while (&Bcb->BcbLinks != &SharedCacheMap->BcbList) { 00233 00234 // 00235 // If the Bcb is dirty, then capture the inputs for the 00236 // callback routine so we can call without holding a spinlock. 00237 // 00238 00239 if ((Bcb->NodeTypeCode == CACHE_NTC_BCB) && Bcb->Dirty) { 00240 00241 SavedFileOffset = Bcb->FileOffset; 00242 SavedByteLength = Bcb->ByteLength; 00243 SavedOldestLsn = Bcb->OldestLsn; 00244 SavedNewestLsn = Bcb->NewestLsn; 00245 00246 // 00247 // Increment PinCount so the Bcb sticks around 00248 // 00249 00250 Bcb->PinCount += 1; 00251 00252 ExReleaseFastLock( &SharedCacheMap->BcbSpinLock, OldIrql ); 00253 00254 // 00255 // Any Bcb to unpin from a previous loop? 00256 // 00257 00258 if (BcbToUnpin != NULL) { 00259 CcUnpinFileData( BcbToUnpin, TRUE, UNREF ); 00260 BcbToUnpin = NULL; 00261 } 00262 00263 // 00264 // Call the file system. This callback may raise status. 00265 // 00266 00267 (*DirtyPageRoutine)( SharedCacheMap->FileObject, 00268 &SavedFileOffset, 00269 SavedByteLength, 00270 &SavedOldestLsn, 00271 &SavedNewestLsn, 00272 Context1, 00273 Context2 ); 00274 00275 // 00276 // Possibly update OldestLsn 00277 // 00278 00279 if ((SavedOldestLsn.QuadPart != 0) && 00280 ((OldestLsn.QuadPart == 0) || (SavedOldestLsn.QuadPart < OldestLsn.QuadPart ))) { 00281 OldestLsn = SavedOldestLsn; 00282 } 00283 00284 // 00285 // Now reacquire the spinlock and scan from the resume point 00286 // point to the next Bcb to return in the descending list. 00287 // 00288 00289 ExAcquireFastLock( &SharedCacheMap->BcbSpinLock, &OldIrql ); 00290 00291 // 00292 // Normally the Bcb can stay around a while, but if not, 00293 // we will just remember it for the next time we do not 00294 // have the spin lock. We cannot unpin it now, because 00295 // we would lose our place in the list. 00296 // 00297 00298 if (Bcb->PinCount > 1) { 00299 Bcb->PinCount -= 1; 00300 } else { 00301 BcbToUnpin = Bcb; 00302 } 00303 } 00304 00305 Bcb = CONTAINING_RECORD( Bcb->BcbLinks.Flink, BCB, BcbLinks ); 00306 } 00307 ExReleaseFastLock( &SharedCacheMap->BcbSpinLock, OldIrql ); 00308 00309 // 00310 // We need to unpin any Bcb we are holding before moving on to 00311 // the next SharedCacheMap, or else CcDeleteSharedCacheMap will 00312 // also delete this Bcb. 00313 // 00314 00315 if (BcbToUnpin != NULL) { 00316 00317 CcUnpinFileData( BcbToUnpin, TRUE, UNREF ); 00318 BcbToUnpin = NULL; 00319 } 00320 00321 CcAcquireMasterLock( &OldIrql ); 00322 00323 // 00324 // Now release the SharedCacheMap, leaving it in the dirty list. 00325 // 00326 00327 CcDecrementOpenCount( SharedCacheMap, 'pdGF' ); 00328 SharedCacheMap->DirtyPages -= 1; 00329 } 00330 00331 // 00332 // Now loop back for the next cache map. 00333 // 00334 00335 SharedCacheMap = 00336 CONTAINING_RECORD( SharedCacheMap->SharedCacheMapLinks.Flink, 00337 SHARED_CACHE_MAP, 00338 SharedCacheMapLinks ); 00339 } 00340 00341 CcReleaseMasterLock( OldIrql ); 00342 00343 } finally { 00344 00345 // 00346 // Drop the Bcb if we are being ejected. We are guaranteed that the 00347 // only raise is from the callback, at which point we have an incremented 00348 // pincount. 00349 // 00350 00351 if (AbnormalTermination()) { 00352 00353 CcUnpinFileData( Bcb, TRUE, UNPIN ); 00354 } 00355 } 00356 00357 return OldestLsn; 00358 }

LARGE_INTEGER CcGetLsnForFileObject IN PFILE_OBJECT  FileObject,
OUT PLARGE_INTEGER OldestLsn  OPTIONAL
 

Definition at line 450 of file logsup.c.

References _BCB::BcbLinks, _SHARED_CACHE_MAP::BcbList, _SHARED_CACHE_MAP::BcbSpinLock, CACHE_NTC_BCB, _BCB::Dirty, _BCB::NewestLsn, _BCB::NodeTypeCode, NULL, and _BCB::OldestLsn.

00457 : 00458 00459 This routine returns the oldest and newest LSNs for a file object. 00460 00461 Arguments: 00462 00463 FileObject - File for which the log handle should be stored. 00464 00465 OldestLsn - pointer to location to store oldest LSN for file object. 00466 00467 Return Value: 00468 00469 The newest LSN for the file object. 00470 00471 --*/ 00472 00473 { 00474 PBCB Bcb; 00475 KIRQL OldIrql; 00476 LARGE_INTEGER Oldest, Newest; 00477 PSHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 00478 00479 // 00480 // initialize lsn variables 00481 // 00482 00483 Oldest.LowPart = 0; 00484 Oldest.HighPart = 0; 00485 Newest.LowPart = 0; 00486 Newest.HighPart = 0; 00487 00488 if(SharedCacheMap == NULL) { 00489 return Oldest; 00490 } 00491 00492 ExAcquireFastLock(&SharedCacheMap->BcbSpinLock, &OldIrql); 00493 00494 // 00495 // Now point to first Bcb in List, and loop through it. 00496 // 00497 00498 Bcb = CONTAINING_RECORD( SharedCacheMap->BcbList.Flink, BCB, BcbLinks ); 00499 00500 while (&Bcb->BcbLinks != &SharedCacheMap->BcbList) { 00501 00502 // 00503 // If the Bcb is dirty then capture the oldest and newest lsn 00504 // 00505 00506 00507 if ((Bcb->NodeTypeCode == CACHE_NTC_BCB) && Bcb->Dirty) { 00508 00509 LARGE_INTEGER BcbLsn, BcbNewest; 00510 00511 BcbLsn = Bcb->OldestLsn; 00512 BcbNewest = Bcb->NewestLsn; 00513 00514 if ((BcbLsn.QuadPart != 0) && 00515 ((Oldest.QuadPart == 0) || 00516 (BcbLsn.QuadPart < Oldest.QuadPart))) { 00517 00518 Oldest = BcbLsn; 00519 } 00520 00521 if ((BcbLsn.QuadPart != 0) && (BcbNewest.QuadPart > Newest.QuadPart)) { 00522 00523 Newest = BcbNewest; 00524 } 00525 } 00526 00527 00528 Bcb = CONTAINING_RECORD( Bcb->BcbLinks.Flink, BCB, BcbLinks ); 00529 } 00530 00531 // 00532 // Now release the spin lock for this Bcb list and generate a callback 00533 // if we got something. 00534 // 00535 00536 ExReleaseFastLock( &SharedCacheMap->BcbSpinLock, OldIrql ); 00537 00538 if (ARGUMENT_PRESENT(OldestLsn)) { 00539 00540 *OldestLsn = Oldest; 00541 } 00542 00543 return Newest; 00544 } }

BOOLEAN CcIsThereDirtyData IN PVPB  Vpb  ) 
 

Definition at line 362 of file logsup.c.

References CcAcquireMasterLock, CcDirtySharedCacheMapList, CcReleaseMasterLock, ClearFlag, _SHARED_CACHE_MAP::DirtyPages, FALSE, _SHARED_CACHE_MAP::FileObject, FlagOn, _SHARED_CACHE_MAP::Flags, _FILE_OBJECT::Flags, FO_TEMPORARY_FILE, IS_CURSOR, SetFlag, _SHARED_CACHE_MAP_LIST_CURSOR::SharedCacheMapLinks, _SHARED_CACHE_MAP::SharedCacheMapLinks, TRUE, _FILE_OBJECT::Vpb, and WRITE_QUEUED.

00368 : 00369 00370 This routine returns TRUE if the specified Vcb has any unwritten dirty 00371 data in the cache. 00372 00373 Arguments: 00374 00375 Vpb - specifies Vpb to check for 00376 00377 Return Value: 00378 00379 FALSE - if the Vpb has no dirty data 00380 TRUE - if the Vpb has dirty data 00381 00382 --*/ 00383 00384 { 00385 PSHARED_CACHE_MAP SharedCacheMap; 00386 KIRQL OldIrql; 00387 ULONG LoopsWithLockHeld = 0; 00388 00389 // 00390 // Synchronize with changes to the SharedCacheMap list. 00391 // 00392 00393 CcAcquireMasterLock( &OldIrql ); 00394 00395 SharedCacheMap = CONTAINING_RECORD( CcDirtySharedCacheMapList.SharedCacheMapLinks.Flink, 00396 SHARED_CACHE_MAP, 00397 SharedCacheMapLinks ); 00398 00399 while (&SharedCacheMap->SharedCacheMapLinks != &CcDirtySharedCacheMapList.SharedCacheMapLinks) { 00400 00401 // 00402 // Look at this one if the Vpb matches and if there is dirty data. 00403 // For what it's worth, don't worry about dirty data in temporary files, 00404 // as that should not concern the caller if it wants to dismount. 00405 // 00406 00407 if (!FlagOn(SharedCacheMap->Flags, IS_CURSOR) && 00408 (SharedCacheMap->FileObject->Vpb == Vpb) && 00409 (SharedCacheMap->DirtyPages != 0) && 00410 !FlagOn(SharedCacheMap->FileObject->Flags, FO_TEMPORARY_FILE)) { 00411 00412 CcReleaseMasterLock( OldIrql ); 00413 return TRUE; 00414 } 00415 00416 // 00417 // Make sure we occassionally drop the lock. Set WRITE_QUEUED 00418 // to keep the guy from going away, and increment DirtyPages to 00419 // keep in in this list. 00420 // 00421 00422 if ((++LoopsWithLockHeld >= 20) && 00423 !FlagOn(SharedCacheMap->Flags, WRITE_QUEUED | IS_CURSOR)) { 00424 00425 SetFlag( (volatile ULONG) SharedCacheMap->Flags, WRITE_QUEUED); 00426 (volatile ULONG) SharedCacheMap->DirtyPages += 1; 00427 CcReleaseMasterLock( OldIrql ); 00428 LoopsWithLockHeld = 0; 00429 CcAcquireMasterLock( &OldIrql ); 00430 ClearFlag( (volatile ULONG) SharedCacheMap->Flags, WRITE_QUEUED); 00431 (volatile ULONG) SharedCacheMap->DirtyPages -= 1; 00432 } 00433 00434 // 00435 // Now loop back for the next cache map. 00436 // 00437 00438 SharedCacheMap = 00439 CONTAINING_RECORD( SharedCacheMap->SharedCacheMapLinks.Flink, 00440 SHARED_CACHE_MAP, 00441 SharedCacheMapLinks ); 00442 } 00443 00444 CcReleaseMasterLock( OldIrql ); 00445 00446 return FALSE; 00447 }

VOID CcSetAdditionalCacheAttributes IN PFILE_OBJECT  FileObject,
IN BOOLEAN  DisableReadAhead,
IN BOOLEAN  DisableWriteBehind
 

Definition at line 32 of file logsup.c.

References CcAcquireMasterLock, CcReleaseMasterLock, ClearFlag, DISABLE_READ_AHEAD, DISABLE_WRITE_BEHIND, _SHARED_CACHE_MAP::Flags, MODIFIED_WRITE_DISABLED, and SetFlag.

Referenced by LfsInitializeLogFile(), and LfsOpenLogFile().

00040 : 00041 00042 This routine supports the setting of disable read ahead or disable write 00043 behind flags to control Cache Manager operation. This routine may be 00044 called any time after calling CcInitializeCacheMap. Initially both 00045 read ahead and write behind are enabled. Note that the state of both 00046 of these flags must be specified on each call to this routine. 00047 00048 Arguments: 00049 00050 FileObject - File object for which the respective flags are to be set. 00051 00052 DisableReadAhead - FALSE to enable read ahead, TRUE to disable it. 00053 00054 DisableWriteBehind - FALSE to enable write behind, TRUE to disable it. 00055 00056 Return Value: 00057 00058 None. 00059 00060 --*/ 00061 00062 { 00063 PSHARED_CACHE_MAP SharedCacheMap; 00064 KIRQL OldIrql; 00065 00066 // 00067 // Get pointer to SharedCacheMap. 00068 // 00069 00070 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 00071 00072 // 00073 // Now set the flags and return. 00074 // 00075 00076 CcAcquireMasterLock( &OldIrql ); 00077 if (DisableReadAhead) { 00078 SetFlag(SharedCacheMap->Flags, DISABLE_READ_AHEAD); 00079 } else { 00080 ClearFlag(SharedCacheMap->Flags, DISABLE_READ_AHEAD); 00081 } 00082 if (DisableWriteBehind) { 00083 SetFlag(SharedCacheMap->Flags, DISABLE_WRITE_BEHIND | MODIFIED_WRITE_DISABLED); 00084 } else { 00085 ClearFlag(SharedCacheMap->Flags, DISABLE_WRITE_BEHIND); 00086 } 00087 CcReleaseMasterLock( OldIrql ); 00088 }

VOID CcSetLogHandleForFile IN PFILE_OBJECT  FileObject,
IN PVOID  LogHandle,
IN PFLUSH_TO_LSN  FlushToLsnRoutine
 

Definition at line 92 of file logsup.c.

References _SHARED_CACHE_MAP::FlushToLsnRoutine, and _SHARED_CACHE_MAP::LogHandle.

00100 : 00101 00102 This routine may be called to instruct the Cache Manager to store the 00103 specified log handle with the shared cache map for a file, to support 00104 subsequent calls to the other routines in this module which effectively 00105 perform an associative search for files by log handle. 00106 00107 Arguments: 00108 00109 FileObject - File for which the log handle should be stored. 00110 00111 LogHandle - Log Handle to store. 00112 00113 FlushToLsnRoutine - A routine to call before flushing buffers for this 00114 file, to insure a log file is flushed to the most 00115 recent Lsn for any Bcb being flushed. 00116 00117 Return Value: 00118 00119 None. 00120 00121 --*/ 00122 00123 { 00124 PSHARED_CACHE_MAP SharedCacheMap; 00125 00126 // 00127 // Get pointer to SharedCacheMap. 00128 // 00129 00130 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 00131 00132 // 00133 // Now set the log file handle and flush routine 00134 // 00135 00136 SharedCacheMap->LogHandle = LogHandle; 00137 SharedCacheMap->FlushToLsnRoutine = FlushToLsnRoutine; 00138 }


Generated on Sat May 15 19:44:33 2004 for test by doxygen 1.3.7