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

rstrtsup.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 RstrtSup.c 00008 00009 Abstract: 00010 00011 This module implements support for dealing with the Lfs restart area. 00012 00013 Author: 00014 00015 Brian Andrew [BrianAn] 20-June-1991 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "lfsprocs.h" 00022 00023 // 00024 // The debug trace level 00025 // 00026 00027 #define Dbg (DEBUG_TRACE_RESTART_SUP) 00028 00029 #ifdef ALLOC_PRAGMA 00030 #pragma alloc_text(PAGE, LfsFindOldestClientLsn) 00031 #pragma alloc_text(PAGE, LfsWriteLfsRestart) 00032 #endif 00033 00034 00035 VOID 00036 LfsWriteLfsRestart ( 00037 IN PLFCB Lfcb, 00038 IN ULONG ThisRestartSize, 00039 IN BOOLEAN WaitForIo 00040 ) 00041 00042 /*++ 00043 00044 Routine Description: 00045 00046 This routine puts the Lfs restart area on the queue of operations to 00047 write to the file. We do this by allocating a second restart area 00048 and attaching it to the Lfcb. We also allocate a buffer control 00049 block to use for this write. We look at the WaitForIo boolean to 00050 determine whether this thread can perform the I/O. This also indicates 00051 whether this thread gives up the Lfcb. 00052 00053 Arguments: 00054 00055 Lfcb - A pointer to the log file control block for this operation. 00056 00057 ThisRestartSize - This is the size to use for the restart area. 00058 00059 WaitForIo - Indicates if this thread is to perform the work. 00060 00061 Return Value: 00062 00063 None. 00064 00065 --*/ 00066 00067 { 00068 PLBCB NewLbcb = NULL; 00069 PLFS_RESTART_AREA NewRestart = NULL; 00070 00071 PAGED_CODE(); 00072 00073 DebugTrace( +1, Dbg, "LfsWriteLfsRestart: Entered\n", 0 ); 00074 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00075 DebugTrace( 0, Dbg, "Write Chkdsk -> %04x\n", WriteChkdsk ); 00076 DebugTrace( 0, Dbg, "Restart Size -> %08lx\n", ThisRestartSize ); 00077 DebugTrace( 0, Dbg, "WaitForIo -> %08lx\n", WaitForIo ); 00078 00079 // 00080 // Use a try-finally to facilitate cleanup. 00081 // 00082 00083 try { 00084 00085 PLBCB ActiveLbcb; 00086 00087 // 00088 // We allocate another restart area and 00089 // copy the current area into it. Attach the new area to the Lfcb. 00090 // 00091 00092 LfsAllocateRestartArea( &NewRestart, ThisRestartSize ); 00093 00094 // 00095 // We allocate a Lbcb structure and update the values to 00096 // reflect this restart area. 00097 // 00098 00099 LfsAllocateLbcb( Lfcb, &NewLbcb ); 00100 SetFlag( NewLbcb->LbcbFlags, LBCB_RESTART_LBCB ); 00101 00102 // 00103 // If this is the second page, then add a system page to the offset. 00104 // 00105 00106 if (!Lfcb->InitialRestartArea) { 00107 00108 NewLbcb->FileOffset = Lfcb->SystemPageSize + NewLbcb->FileOffset; 00109 } 00110 00111 (ULONG)NewLbcb->Length = ThisRestartSize; 00112 00113 NewLbcb->PageHeader = (PVOID) Lfcb->RestartArea; 00114 00115 // 00116 // Lets put the current lsn in the Lbcb. 00117 // 00118 00119 NewLbcb->LastEndLsn = NewLbcb->LastLsn = Lfcb->NextRestartLsn; 00120 Lfcb->NextRestartLsn.QuadPart = 1 + Lfcb->NextRestartLsn.QuadPart; 00121 00122 // 00123 // Copy the existing restart area into the new area. 00124 // 00125 00126 RtlCopyMemory( NewRestart, Lfcb->RestartArea, ThisRestartSize ); 00127 Lfcb->RestartArea = NewRestart; 00128 00129 Lfcb->ClientArray = Add2Ptr( NewRestart, Lfcb->ClientArrayOffset, PLFS_CLIENT_RECORD ); 00130 00131 NewRestart = NULL; 00132 00133 // 00134 // Update the Lfcb to indicate that the other restart area 00135 // on the disk is to be used. 00136 // 00137 00138 Lfcb->InitialRestartArea = !Lfcb->InitialRestartArea; 00139 00140 // 00141 // Add this Lbcb to the end of the workque and flush to that point. 00142 // 00143 00144 InsertTailList( &Lfcb->LbcbWorkque, &NewLbcb->WorkqueLinks ); 00145 00146 // 00147 // If we don't support a packed log file then we need to make 00148 // sure that all file records written out ahead of this 00149 // restart area make it out to disk and we don't add anything 00150 // to this page. 00151 // 00152 00153 if (!FlagOn( Lfcb->Flags, LFCB_PACK_LOG ) 00154 && !IsListEmpty( &Lfcb->LbcbActive )) { 00155 00156 ActiveLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink, 00157 LBCB, 00158 ActiveLinks ); 00159 00160 if (FlagOn( ActiveLbcb->LbcbFlags, LBCB_NOT_EMPTY )) { 00161 00162 RemoveEntryList( &ActiveLbcb->ActiveLinks ); 00163 ClearFlag( ActiveLbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE ); 00164 } 00165 } 00166 00167 if (WaitForIo) { 00168 00169 LfsFlushLbcb( Lfcb, NewLbcb ); 00170 } 00171 00172 } finally { 00173 00174 DebugUnwind( LfsWriteLfsRestart ); 00175 00176 if (NewRestart != NULL) { 00177 00178 ExFreePool( NewRestart ); 00179 } 00180 00181 DebugTrace( -1, Dbg, "LfsWriteLfsRestart: Exit\n", 0 ); 00182 } 00183 00184 return; 00185 } 00186 00187 00188 VOID 00189 LfsFindOldestClientLsn ( 00190 IN PLFS_RESTART_AREA RestartArea, 00191 IN PLFS_CLIENT_RECORD ClientArray, 00192 OUT PLSN OldestLsn 00193 ) 00194 00195 /*++ 00196 00197 Routine Description: 00198 00199 This routine walks through the active clients to determine the oldest 00200 Lsn the system must maintain. 00201 00202 Arguments: 00203 00204 RestartArea - This is the Restart Area to examine. 00205 00206 ClientArray - This is the start of the client data array. 00207 00208 OldestLsn - We store the oldest Lsn we find in this value. It is 00209 initialized with a starting value, we won't return a more recent 00210 Lsn. 00211 00212 Return Value: 00213 00214 None. 00215 00216 --*/ 00217 00218 { 00219 USHORT NextClient; 00220 00221 PLFS_CLIENT_RECORD ClientBlock; 00222 00223 PAGED_CODE(); 00224 00225 DebugTrace( +1, Dbg, "LfsFindOldestClientLsn: Entered\n", 0 ); 00226 DebugTrace( 0, Dbg, "RestartArea -> %08lx\n", RestartArea ); 00227 DebugTrace( 0, Dbg, "Base Lsn (Low) -> %08lx\n", BaseLsn.LowPart ); 00228 DebugTrace( 0, Dbg, "Base Lsn (High) -> %08lx\n", BaseLsn.HighPart ); 00229 00230 // 00231 // Take the first client off the in use list. 00232 // 00233 00234 NextClient = RestartArea->ClientInUseList; 00235 00236 // 00237 // While there are more clients, compare their oldest Lsn with the 00238 // current oldest. 00239 // 00240 00241 while (NextClient != LFS_NO_CLIENT) { 00242 00243 ClientBlock = ClientArray + NextClient; 00244 00245 // 00246 // We ignore this block if it's oldest Lsn is 0. 00247 // 00248 00249 if (( ClientBlock->OldestLsn.QuadPart != 0 ) 00250 && ( ClientBlock->OldestLsn.QuadPart < OldestLsn->QuadPart )) { 00251 00252 *OldestLsn = ClientBlock->OldestLsn; 00253 } 00254 00255 // 00256 // Try the next client block. 00257 // 00258 00259 NextClient = ClientBlock->NextClient; 00260 } 00261 00262 DebugTrace( 0, Dbg, "OldestLsn (Low) -> %08lx\n", BaseLsn.LowPart ); 00263 DebugTrace( 0, Dbg, "OldestLsn (High) -> %08lx\n", BaseLsn.HighPart ); 00264 DebugTrace( -1, Dbg, "LfsFindOldestClientLsn: Exit\n", 0 ); 00265 00266 return; 00267 } 00268

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