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

restart.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 Restart.c 00008 00009 Abstract: 00010 00011 This module implements the routines which access the client restart 00012 areas. 00013 00014 Author: 00015 00016 Brian Andrew [BrianAn] 20-June-1991 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "lfsprocs.h" 00023 00024 // 00025 // The debug trace level 00026 // 00027 00028 #define Dbg (DEBUG_TRACE_RESTART) 00029 00030 VOID 00031 LfsSetBaseLsnPriv ( 00032 IN PLFCB Lfcb, 00033 IN PLFS_CLIENT_RECORD ClientRecord, 00034 IN LSN BaseLsn 00035 ); 00036 00037 #ifdef ALLOC_PRAGMA 00038 #pragma alloc_text(PAGE, LfsReadRestartArea) 00039 #pragma alloc_text(PAGE, LfsSetBaseLsn) 00040 #pragma alloc_text(PAGE, LfsSetBaseLsnPriv) 00041 #pragma alloc_text(PAGE, LfsWriteRestartArea) 00042 #endif 00043 00044 00045 NTSTATUS 00046 LfsReadRestartArea ( 00047 IN LFS_LOG_HANDLE LogHandle, 00048 IN OUT PULONG BufferLength, 00049 IN PVOID Buffer, 00050 OUT PLSN Lsn 00051 ) 00052 00053 /*++ 00054 00055 Routine Description: 00056 00057 This routine is called by the client when he wishes to read his restart 00058 area in the log file. 00059 00060 Arguments: 00061 00062 LogHandle - Pointer to private Lfs structure used to identify this 00063 client. 00064 00065 BufferLength - On entry it is the length of the user buffer. On exit 00066 it is the size of the data stored in the buffer. 00067 00068 Buffer - Pointer to the buffer where the client restart data is to be 00069 copied. 00070 00071 Lsn - This is the Lsn for client restart area. 00072 00073 Return Value: 00074 00075 None 00076 00077 --*/ 00078 00079 { 00080 volatile NTSTATUS Status = STATUS_SUCCESS; 00081 00082 BOOLEAN UsaError; 00083 00084 PLCH Lch; 00085 00086 PLFS_CLIENT_RECORD ClientRecord; 00087 00088 PLFS_RECORD_HEADER RecordHeader; 00089 PBCB RecordHeaderBcb; 00090 00091 PLFCB Lfcb; 00092 NTSTATUS RetStatus = STATUS_SUCCESS; 00093 00094 00095 PAGED_CODE(); 00096 00097 DebugTrace( +1, Dbg, "LfsReadRestartArea: Entered\n", 0 ); 00098 DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); 00099 DebugTrace( 0, Dbg, "Buffer Length -> %08lx\n", *BufferLength ); 00100 DebugTrace( 0, Dbg, "Buffer -> %08lx\n", Buffer ); 00101 00102 RecordHeaderBcb = NULL; 00103 00104 Lch = (PLCH) LogHandle; 00105 00106 // 00107 // Check that the structure is a valid log handle structure. 00108 // 00109 00110 LfsValidateLch( Lch ); 00111 00112 // 00113 // Use a try-except to catch errors. 00114 // 00115 00116 try { 00117 00118 // 00119 // Use a try-finally to facilitate cleanup. 00120 // 00121 00122 try { 00123 00124 // 00125 // Acquire the log file control block for this log file. 00126 // 00127 00128 LfsAcquireLch( Lch ); 00129 Lfcb = Lch->Lfcb; 00130 00131 // 00132 // If the Log file has been closed then refuse access. 00133 // 00134 00135 if (Lfcb == NULL) { 00136 00137 ExRaiseStatus( STATUS_ACCESS_DENIED ); 00138 } 00139 00140 // 00141 // Check that the client Id is valid. 00142 // 00143 00144 LfsValidateClientId( Lfcb, Lch ); 00145 00146 ClientRecord = Add2Ptr( Lfcb->ClientArray, 00147 Lch->ClientArrayByteOffset, 00148 PLFS_CLIENT_RECORD ); 00149 00150 // 00151 // If the client doesn't have a restart area, go ahead and exit 00152 // now. 00153 // 00154 00155 if ( ClientRecord->ClientRestartLsn.QuadPart == 0 ) { //**** xxEqlZero( ClientRecord->ClientRestartLsn ) 00156 00157 // 00158 // We show there is no restart area by returning a length 00159 // of zero. We also set the Lsn value to zero so that 00160 // we can catch it if the user tries to use the Lsn. 00161 // 00162 00163 DebugTrace( 0, Dbg, "No client restart area exists\n", 0 ); 00164 00165 *BufferLength = 0; 00166 *Lsn = LfsZeroLsn; 00167 00168 try_return( NOTHING ); 00169 } 00170 00171 // 00172 // Release the Lfcb as we won't be modifying any fields in it. 00173 // 00174 00175 LfsReleaseLfcb( Lfcb ); 00176 00177 // 00178 // Pin the log record for this Lsn. 00179 // 00180 00181 LfsPinOrMapLogRecordHeader( Lfcb, 00182 ClientRecord->ClientRestartLsn, 00183 FALSE, 00184 FALSE, 00185 &UsaError, 00186 &RecordHeader, 00187 &RecordHeaderBcb ); 00188 00189 // 00190 // If the Lsn values don't match, then the disk is corrupt. 00191 // 00192 00193 if ( ClientRecord->ClientRestartLsn.QuadPart != RecordHeader->ThisLsn.QuadPart ) { //**** xxNeq( ClientRecord->ClientRestartLsn, RecordHeader->ThisLsn ) 00194 00195 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00196 } 00197 00198 00199 // 00200 // Check that the user's buffer is big enough to hold the restart 00201 // data. We raise an error status for this error. 00202 // 00203 00204 if (RecordHeader->ClientDataLength > *BufferLength) { 00205 00206 DebugTrace( 0, Dbg, "Client buffer is too small\n", 0 ); 00207 *BufferLength = RecordHeader->ClientDataLength; 00208 *Lsn = LfsZeroLsn; 00209 try_return( RetStatus = STATUS_BUFFER_TOO_SMALL ); 00210 } 00211 00212 00213 // 00214 // Use the cache manager to copy the data into the user's buffer. 00215 // 00216 00217 LfsCopyReadLogRecord( Lfcb, 00218 RecordHeader, 00219 Buffer ); 00220 00221 // 00222 // Pass the length and the Lsn of the restart area back to the 00223 // caller. 00224 // 00225 00226 *BufferLength = RecordHeader->ClientDataLength; 00227 *Lsn = RecordHeader->ThisLsn; 00228 00229 try_exit: NOTHING; 00230 } finally { 00231 00232 DebugUnwind( LfsReadRestartArea ); 00233 00234 // 00235 // Release the log file control block if held. 00236 // 00237 00238 LfsReleaseLch( Lch ); 00239 00240 // 00241 // Unpin the log record header for the client restart if pinned. 00242 // 00243 00244 if (RecordHeaderBcb != NULL) { 00245 00246 CcUnpinData( RecordHeaderBcb ); 00247 } 00248 00249 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn->LowPart ); 00250 DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn->HighPart ); 00251 DebugTrace( 0, Dbg, "Buffer Length -> %08lx\n", *BufferLength ); 00252 DebugTrace( -1, Dbg, "LfsReadRestartArea: Exit\n", 0 ); 00253 } 00254 00255 } except (LfsExceptionFilter( GetExceptionInformation() )) { 00256 00257 Status = GetExceptionCode(); 00258 } 00259 00260 if (Status != STATUS_SUCCESS) { 00261 00262 ExRaiseStatus( Status ); 00263 } 00264 00265 return RetStatus; 00266 } 00267 00268 00269 VOID 00270 LfsWriteRestartArea ( 00271 IN LFS_LOG_HANDLE LogHandle, 00272 IN ULONG BufferLength, 00273 IN PVOID Buffer, 00274 OUT PLSN Lsn 00275 ) 00276 00277 /*++ 00278 00279 Routine Description: 00280 00281 This routine is called by the client to write a restart area to the 00282 disk. This routine will not return to the caller until the client 00283 restart area and all prior Lsn's have been flushed and the Lfs 00284 restart area on the disk has been updated. 00285 00286 On return, all log records up to and including 'Lsn' have been flushed 00287 to the disk. 00288 00289 Arguments: 00290 00291 LogHandle - Pointer to private Lfs structure used to identify this 00292 client. 00293 00294 BufferLength - On entry it is the length of the user buffer. 00295 00296 Buffer - Pointer to the buffer where the client restart data resides. 00297 00298 Lsn - This is the Lsn for this write operation. On input, this will be the 00299 new Base Lsn for this client. 00300 00301 **** This was used to prevent adding an interface change to 00302 the Beta release. 00303 00304 Return Value: 00305 00306 None 00307 00308 --*/ 00309 00310 { 00311 volatile NTSTATUS Status = STATUS_SUCCESS; 00312 00313 PLCH Lch; 00314 00315 PLFCB Lfcb; 00316 00317 PLFS_CLIENT_RECORD ClientRecord; 00318 00319 LFS_WRITE_ENTRY WriteEntry; 00320 00321 PAGED_CODE(); 00322 00323 DebugTrace( +1, Dbg, "LfsWriteRestartArea: Entered\n", 0 ); 00324 DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); 00325 DebugTrace( 0, Dbg, "Buffer Length -> %08lx\n", BufferLength ); 00326 DebugTrace( 0, Dbg, "Buffer -> %08lx\n", Buffer ); 00327 00328 Lch = (PLCH) LogHandle; 00329 00330 // 00331 // Check that the structure is a valid log handle structure. 00332 // 00333 00334 LfsValidateLch( Lch ); 00335 00336 // 00337 // Use a try-except to catch errors. 00338 // 00339 00340 try { 00341 00342 // 00343 // Use a try-finally to facilitate cleanup. 00344 // 00345 00346 try { 00347 00348 // 00349 // Acquire the log file control block for this log file. 00350 // 00351 00352 LfsAcquireLch( Lch ); 00353 Lfcb = Lch->Lfcb; 00354 00355 // 00356 // If the Log file has been closed then refuse access. 00357 // 00358 00359 if (Lfcb == NULL) { 00360 00361 ExRaiseStatus( STATUS_ACCESS_DENIED ); 00362 } 00363 00364 // 00365 // Check that the client Id is valid. 00366 // 00367 00368 LfsValidateClientId( Lfcb, Lch ); 00369 00370 ClientRecord = Add2Ptr( Lfcb->ClientArray, 00371 Lch->ClientArrayByteOffset, 00372 PLFS_CLIENT_RECORD ); 00373 00374 // 00375 // Go ahead and update the Base Lsn in the client area if the value 00376 // given is not zero. 00377 // 00378 00379 if ( Lsn->QuadPart != 0 ) { //**** xxNeqZero( *Lsn ) 00380 00381 LfsSetBaseLsnPriv( Lfcb, 00382 ClientRecord, 00383 *Lsn ); 00384 } 00385 00386 // 00387 // Write this restart area as a log record into a log page. 00388 // 00389 00390 WriteEntry.Buffer = Buffer; 00391 WriteEntry.ByteLength = BufferLength; 00392 00393 LfsWriteLogRecordIntoLogPage( Lfcb, 00394 Lch, 00395 1, 00396 &WriteEntry, 00397 LfsClientRestart, 00398 NULL, 00399 LfsZeroLsn, 00400 LfsZeroLsn, 00401 0, 00402 TRUE, 00403 Lsn ); 00404 00405 // 00406 // Update the restart area for the client. 00407 // 00408 00409 ClientRecord->ClientRestartLsn = *Lsn; 00410 00411 // 00412 // Write the restart area to the disk. 00413 // 00414 00415 LfsWriteLfsRestart( Lfcb, Lfcb->RestartAreaSize, TRUE ); 00416 00417 } finally { 00418 00419 DebugUnwind( LfsWriteRestartArea ); 00420 00421 // 00422 // Release the log file control block if still held. 00423 // 00424 00425 LfsReleaseLch( Lch ); 00426 00427 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn->LowPart ); 00428 DebugTrace( 0, Dbg, "Log (High) -> %08lx\n", Lsn->HighPart ); 00429 DebugTrace( -1, Dbg, "LfsWriteRestartArea: Exit\n", 0 ); 00430 } 00431 00432 } except (LfsExceptionFilter( GetExceptionInformation() )) { 00433 00434 Status = GetExceptionCode(); 00435 } 00436 00437 if (Status != STATUS_SUCCESS) { 00438 00439 ExRaiseStatus( Status ); 00440 } 00441 00442 return; 00443 } 00444 00445 00446 VOID 00447 LfsSetBaseLsn ( 00448 IN LFS_LOG_HANDLE LogHandle, 00449 IN LSN BaseLsn 00450 ) 00451 00452 /*++ 00453 00454 Routine Description: 00455 00456 This routine is called by the client to notify the log service of the 00457 oldest Lsn he expects to need during restart. The Lfs is allowed to 00458 reuse any part of the circular log file which logically precedes 00459 this Lsn. A client may only specify a Lsn which follows the previous 00460 Lsn specified by this client. 00461 00462 Arguments: 00463 00464 LogHandle - Pointer to private Lfs structure used to identify this 00465 client. 00466 00467 BaseLsn - This is the oldest Lsn the client may require during a 00468 restart. 00469 00470 Return Value: 00471 00472 None 00473 00474 --*/ 00475 00476 { 00477 volatile NTSTATUS Status = STATUS_SUCCESS; 00478 00479 PLCH Lch; 00480 00481 PLFCB Lfcb; 00482 00483 PLFS_CLIENT_RECORD ClientRecord; 00484 00485 PAGED_CODE(); 00486 00487 DebugTrace( +1, Dbg, "LfsSetBaseLsn: Entered\n", 0 ); 00488 DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); 00489 DebugTrace( 0, Dbg, "Base Lsn (Low) -> %08lx\n", BaseLsn.LowPart ); 00490 DebugTrace( 0, Dbg, "Base Lsn (High) -> %08lx\n", BaseLsn.HighPart ); 00491 00492 Lch = (PLCH) LogHandle; 00493 00494 // 00495 // Check that the structure is a valid log handle structure. 00496 // 00497 00498 LfsValidateLch( Lch ); 00499 00500 // 00501 // Use a try-except to catch errors. 00502 // 00503 00504 try { 00505 00506 // 00507 // Use a try-finally to facilitate cleanup. 00508 // 00509 00510 try { 00511 00512 // 00513 // Acquire the log file control block for this log file. 00514 // 00515 00516 LfsAcquireLch( Lch ); 00517 Lfcb = Lch->Lfcb; 00518 00519 // 00520 // If the Log file has been closed then refuse access. 00521 // 00522 00523 if (Lfcb == NULL) { 00524 00525 ExRaiseStatus( STATUS_ACCESS_DENIED ); 00526 } 00527 00528 // 00529 // Check that the client Id is valid. 00530 // 00531 00532 LfsValidateClientId( Lfcb, Lch ); 00533 00534 ClientRecord = Add2Ptr( Lfcb->ClientArray, 00535 Lch->ClientArrayByteOffset, 00536 PLFS_CLIENT_RECORD ); 00537 00538 // 00539 // We simply call the worker routine to advance the base lsn. 00540 // If we moved forward in the file, we will put our restart area in the 00541 // queue. 00542 // 00543 00544 LfsSetBaseLsnPriv( Lfcb, 00545 ClientRecord, 00546 BaseLsn ); 00547 00548 LfsWriteLfsRestart( Lfcb, Lfcb->RestartAreaSize, FALSE ); 00549 00550 } finally { 00551 00552 DebugUnwind( LfsSetBaseLsn ); 00553 00554 // 00555 // Release the log file control block if held. 00556 // 00557 00558 LfsReleaseLch( Lch ); 00559 00560 DebugTrace( -1, Dbg, "LfsSetBaseLsn: Exit\n", 0 ); 00561 } 00562 00563 } except (LfsExceptionFilter( GetExceptionInformation() )) { 00564 00565 Status = GetExceptionCode(); 00566 } 00567 00568 if (Status != STATUS_SUCCESS) { 00569 00570 ExRaiseStatus( Status ); 00571 } 00572 00573 return; 00574 } 00575 00576 00577 // 00578 // Local support routine 00579 // 00580 00581 VOID 00582 LfsSetBaseLsnPriv ( 00583 IN PLFCB Lfcb, 00584 IN PLFS_CLIENT_RECORD ClientRecord, 00585 IN LSN BaseLsn 00586 ) 00587 00588 /*++ 00589 00590 Routine Description: 00591 00592 This worker routine is called internally by Lfs to modify the 00593 oldest Lsn a client expects to need during restart. The Lfs is allowed to 00594 reuse any part of the circular log file which logically precedes 00595 this Lsn. A client may only specify a Lsn which follows the previous 00596 Lsn specified by this client. 00597 00598 Arguments: 00599 00600 Lfcb - Log context block for this file. 00601 00602 ClientRecord - For the client whose base Lsn is being modified. 00603 00604 BaseLsn - This is the oldest Lsn the client may require during a 00605 restart. 00606 00607 Return Value: 00608 00609 None. 00610 00611 --*/ 00612 00613 { 00614 PAGED_CODE(); 00615 00616 DebugTrace( +1, Dbg, "LfsSetBaseLsn: Entered\n", 0 ); 00617 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00618 DebugTrace( 0, Dbg, "Base Lsn (Low) -> %08lx\n", BaseLsn.LowPart ); 00619 DebugTrace( 0, Dbg, "Base Lsn (High) -> %08lx\n", BaseLsn.HighPart ); 00620 00621 // 00622 // We only proceed if the client is moving forward in the file. 00623 // 00624 00625 if ( BaseLsn.QuadPart > Lfcb->OldestLsn.QuadPart ) { //**** xxGtr( BaseLsn, Lfcb->OldestLsn ) 00626 00627 if ( BaseLsn.QuadPart > ClientRecord->OldestLsn.QuadPart ) { //**** xxGtr( BaseLsn, ClientRecord->OldestLsn ) 00628 00629 ClientRecord->OldestLsn = BaseLsn; 00630 } 00631 00632 Lfcb->OldestLsn = BaseLsn; 00633 00634 // 00635 // We walk through all the active clients and find the new 00636 // oldest Lsn for the log file. 00637 // 00638 00639 LfsFindOldestClientLsn( Lfcb->RestartArea, 00640 Lfcb->ClientArray, 00641 &Lfcb->OldestLsn ); 00642 00643 Lfcb->OldestLsnOffset = LfsLsnToFileOffset( Lfcb, Lfcb->OldestLsn ); 00644 ClearFlag( Lfcb->Flags, LFCB_NO_OLDEST_LSN ); 00645 00646 LfsFindCurrentAvail( Lfcb ); 00647 } 00648 00649 DebugTrace( -1, Dbg, "LfsSetBaseLsnPriv: Exit\n", 0 ); 00650 00651 return; 00652 } 00653

Generated on Sat May 15 19:41:39 2004 for test by doxygen 1.3.7