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

hivesync.c File Reference

#include "cmp.h"

Go to the source code of this file.

Defines

#define DumpDirtyVector(Hive)

Functions

BOOLEAN HvpWriteLog (PHHIVE Hive)
BOOLEAN HvpFindNextDirtyBlock (PHHIVE Hive, PRTL_BITMAP BitMap, PULONG Current, PUCHAR *Address, PULONG Length, PULONG Offset)
VOID HvpDiscardBins (PHHIVE Hive)
VOID HvpTruncateBins (PHHIVE Hive)
VOID HvRefreshHive (PHHIVE Hive)
BOOLEAN HvMarkCellDirty (PHHIVE Hive, HCELL_INDEX Cell)
BOOLEAN HvIsBinDirty (IN PHHIVE Hive, IN HCELL_INDEX Cell)
BOOLEAN HvMarkDirty (PHHIVE Hive, HCELL_INDEX Start, ULONG Length)
BOOLEAN HvMarkClean (PHHIVE Hive, HCELL_INDEX Start, ULONG Length)
BOOLEAN HvpGrowLog1 (PHHIVE Hive, ULONG Count)
BOOLEAN HvpGrowLog2 (PHHIVE Hive, ULONG Size)
BOOLEAN HvSyncHive (PHHIVE Hive)
BOOLEAN HvpDoWriteHive (PHHIVE Hive, ULONG FileType)
NTSTATUS HvWriteHive (PHHIVE Hive)
VOID HvpDiscardBins (IN PHHIVE Hive)
VOID HvpTruncateBins (IN PHHIVE Hive)

Variables

BOOLEAN HvShutdownComplete


Define Documentation

#define DumpDirtyVector Hive   ) 
 

Definition at line 52 of file hivesync.c.

Referenced by HvSyncHive().


Function Documentation

BOOLEAN HvIsBinDirty IN PHHIVE  Hive,
IN HCELL_INDEX  Cell
 

Definition at line 200 of file hivesync.c.

References ASSERT, Bin, _HMAP_ENTRY::BinAddress, Cell, CML_MINOR, CMLOG, CMS_IO, _HHIVE::DirtyVector, FALSE, _HBIN::FileOffset, HHIVE_SIGNATURE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HMAP_BASE, HSECTOR_SIZE, HvGetCellType, HvpGetCellMap(), _HHIVE::ReadOnly, _HHIVE::Signature, _HBIN::Size, TRUE, VALIDATE_CELL_MAP, and Volatile.

00207 : 00208 00209 Given a hive and a cell, checks whether the bin containing 00210 that cell has any dirty clusters or not. 00211 00212 Arguments: 00213 00214 Hive - Supplies a pointer to the hive control structure 00215 00216 Cell - Supplies the HCELL_INDEX of the Cell. 00217 00218 Return Value: 00219 00220 TRUE - Bin contains dirty data. 00221 00222 FALSE - Bin does not contain dirty data. 00223 00224 --*/ 00225 00226 { 00227 ULONG Type; 00228 PHCELL pcell; 00229 PRTL_BITMAP Bitmap; 00230 ULONG First; 00231 ULONG Last; 00232 ULONG i; 00233 PHMAP_ENTRY Map; 00234 PHBIN Bin; 00235 00236 CMLOG(CML_MINOR, CMS_IO) { 00237 KdPrint(("HvIsBinDirty:\n\t")); 00238 KdPrint(("Hive:%08lx Cell:%08lx\n", Hive, Cell)); 00239 } 00240 00241 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00242 ASSERT(Hive->ReadOnly == FALSE); 00243 00244 Type = HvGetCellType(Cell); 00245 00246 if ( (Hive->HiveFlags & HIVE_VOLATILE) || 00247 (Type == Volatile) ) 00248 { 00249 return FALSE; 00250 } 00251 00252 Bitmap = &(Hive->DirtyVector); 00253 00254 Map = HvpGetCellMap(Hive, Cell); 00255 VALIDATE_CELL_MAP(__LINE__,Map,Hive,Cell); 00256 Bin = (PHBIN)(Map->BinAddress & HMAP_BASE); 00257 First = Bin->FileOffset / HSECTOR_SIZE; 00258 Last = (Bin->FileOffset + Bin->Size - 1) / HSECTOR_SIZE; 00259 00260 for (i=First; i<=Last; i++) { 00261 if (RtlCheckBit(Bitmap, i)==1) { 00262 return(TRUE); 00263 } 00264 } 00265 return(FALSE); 00266 }

BOOLEAN HvMarkCellDirty PHHIVE  Hive,
HCELL_INDEX  Cell
 

Definition at line 117 of file hivesync.c.

References ASSERT, Bin, _HMAP_ENTRY::BinAddress, Cell, CML_MINOR, CMLOG, CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, _HBIN::FileOffset, HBIN_SIGNATURE, HCELL_INDEX, HHIVE_SIGNATURE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HMAP_BASE, HvGetCellType, HvMarkDirty(), HvpGetCellMap(), HvpGetHCell, _HHIVE::ReadOnly, RtlNumberOfSetBits(), _HBIN::Signature, _HHIVE::Signature, _HCELL::Size, _HBIN::Size, Size, TRUE, USE_OLD_CELL, VALIDATE_CELL_MAP, and Volatile.

Referenced by CmDeleteValueKey(), CmpAddToLeaf(), CmpAssignSecurityDescriptor(), CmpCheckKey(), CmpDoCreate(), CmpInsertSecurityCellList(), CmpMarkIndexDirty(), CmpMarkKeyDirty(), CmpMarkKeyParentDirty(), CmpMarkKeyValuesDirty(), CmpSelectLeaf(), CmpSetSecurityDescriptorInfo(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpSplitLeaf(), CmSetLastWriteTimeKey(), and CmSetValueKey().

00123 : 00124 00125 Marks the data for the specified cell dirty. 00126 00127 Arguments: 00128 00129 Hive - supplies a pointer to the hive control structure for the 00130 hive of interest 00131 00132 Cell - hcell_index of cell that is being edited 00133 00134 Return Value: 00135 00136 TRUE - it worked 00137 00138 FALSE - could not allocate log space, failure! 00139 00140 --*/ 00141 { 00142 ULONG Type; 00143 ULONG Size; 00144 PHCELL pCell; 00145 PHMAP_ENTRY Me; 00146 HCELL_INDEX Base; 00147 PHBIN Bin; 00148 00149 CMLOG(CML_MINOR, CMS_IO) { 00150 KdPrint(("HvMarkCellDirty:\n\t")); 00151 KdPrint(("Hive:%08lx Cell:%08lx\n", Hive, Cell)); 00152 } 00153 00154 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00155 ASSERT(Hive->ReadOnly == FALSE); 00156 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00157 00158 Type = HvGetCellType(Cell); 00159 00160 if ( (Hive->HiveFlags & HIVE_VOLATILE) || 00161 (Type == Volatile) ) 00162 { 00163 return TRUE; 00164 } 00165 00166 pCell = HvpGetHCell(Hive,Cell); 00167 #if DBG 00168 Me = HvpGetCellMap(Hive, Cell); 00169 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Cell); 00170 Bin = (PHBIN)(Me->BinAddress & HMAP_BASE); 00171 ASSERT(Bin->Signature == HBIN_SIGNATURE); 00172 #endif 00173 // 00174 // If it's an old format hive, mark the entire 00175 // bin dirty, because the Last backpointers are 00176 // such a pain to deal with in the partial 00177 // alloc and free-coalescing cases. 00178 // 00179 00180 if (USE_OLD_CELL(Hive)) { 00181 Me = HvpGetCellMap(Hive, Cell); 00182 VALIDATE_CELL_MAP(__LINE__,Me,Hive,Cell); 00183 Bin = (PHBIN)(Me->BinAddress & HMAP_BASE); 00184 Base = Bin->FileOffset; 00185 Size = Bin->Size; 00186 return HvMarkDirty(Hive, Base, Size); 00187 } else { 00188 if (pCell->Size < 0) { 00189 Size = -pCell->Size; 00190 } else { 00191 Size = pCell->Size; 00192 } 00193 ASSERT(Size < Bin->Size); 00194 return HvMarkDirty(Hive, Cell-FIELD_OFFSET(HCELL,u.NewCell), Size); 00195 } 00196 }

BOOLEAN HvMarkClean PHHIVE  Hive,
HCELL_INDEX  Start,
ULONG  Length
 

Definition at line 401 of file hivesync.c.

References ASSERT, BitMap, _HHIVE::Cluster, CML_MINOR, CMLOG, CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, HHIVE_SIGNATURE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HSECTOR_SIZE, HvGetCellType, _HHIVE::ReadOnly, ROUND_UP, RtlClearBits(), RtlNumberOfSetBits(), _HHIVE::Signature, Start, TRUE, and Volatile.

Referenced by HvpAddBin().

00408 : 00409 00410 Clears the dirty bits for a given portion of a hive. This is 00411 the inverse of HvMarkDirty, although it does not give up any 00412 file space in the primary or log that HvMarkDirty may have reserved. 00413 00414 This is a noop for Volatile address range. 00415 00416 Arguments: 00417 00418 Hive - supplies a pointer to the hive control structure for the 00419 hive of interest 00420 00421 Start - supplies a hive virtual address (i.e., an HCELL_INDEX or 00422 like form address) of the start of the area to mark dirty. 00423 00424 Length - inclusive length in bytes of area to mark dirty. 00425 00426 Return Value: 00427 00428 TRUE - it worked 00429 00430 --*/ 00431 { 00432 ULONG Type; 00433 PRTL_BITMAP BitMap; 00434 ULONG First; 00435 ULONG Last; 00436 ULONG i; 00437 ULONG Cluster; 00438 00439 CMLOG(CML_MINOR, CMS_IO) { 00440 KdPrint(("HvMarkClean:\n\t")); 00441 KdPrint(("Hive:%08lx Start:%08lx Length:%08lx\n", Hive, Start, Length)); 00442 } 00443 00444 00445 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00446 ASSERT(Hive->ReadOnly == FALSE); 00447 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00448 00449 Type = HvGetCellType(Start); 00450 00451 if ( (Hive->HiveFlags & HIVE_VOLATILE) || 00452 (Type == Volatile) ) 00453 { 00454 return TRUE; 00455 } 00456 00457 BitMap = &(Hive->DirtyVector); 00458 00459 First = Start / HSECTOR_SIZE; 00460 Last = (Start + Length - 1) / HSECTOR_SIZE; 00461 00462 Cluster = Hive->Cluster; 00463 if (Cluster > 1) { 00464 00465 // 00466 // Force Start down to base of cluster 00467 // Force End up to top of cluster 00468 // 00469 First = First & ~(Cluster - 1); 00470 Last = ROUND_UP(Last+1, Cluster) - 1; 00471 } 00472 00473 if (Last >= BitMap->SizeOfBitMap) { 00474 Last = BitMap->SizeOfBitMap-1; 00475 } 00476 00477 // 00478 // Subtract out the dirty count and 00479 // and clear the dirty bits. 00480 // 00481 for (i=First; i<=Last; i++) { 00482 if (RtlCheckBit(BitMap,i)==1) { 00483 --Hive->DirtyCount; 00484 RtlClearBits(BitMap, i, 1); 00485 } 00486 } 00487 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00488 00489 return(TRUE); 00490 }

BOOLEAN HvMarkDirty PHHIVE  Hive,
HCELL_INDEX  Start,
ULONG  Length
 

Definition at line 270 of file hivesync.c.

References ASSERT, BitMap, _HHIVE::Cluster, CML_MINOR, CMLOG, CmpLazyFlush(), CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, HHIVE_SIGNATURE, Hive, HIVE_NOLAZYFLUSH, HIVE_VOLATILE, _HHIVE::HiveFlags, HSECTOR_SIZE, HvGetCellType, HvpGrowLog1(), HvpMarkBinReadWrite, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), RtlSetBits(), _HHIVE::Signature, Start, TRUE, and Volatile.

Referenced by HvMarkCellDirty(), HvpAddBin(), and HvpRecoverData().

00277 : 00278 00279 Marks the relevent parts of a hive dirty, so that they will 00280 be flushed to backing store. 00281 00282 If Hive->Cluster is not 1, then adjacent all logical sectors 00283 in the given cluster will be forced dirty (and log space 00284 allocated for them.) This must be done here rather than in 00285 HvSyncHive so that we can know how much to grow the log. 00286 00287 This is a noop for Volatile address range. 00288 00289 NOTE: Range will not be marked dirty if operation fails. 00290 00291 Arguments: 00292 00293 Hive - supplies a pointer to the hive control structure for the 00294 hive of interest 00295 00296 Start - supplies a hive virtual address (i.e., an HCELL_INDEX or 00297 like form address) of the start of the area to mark dirty. 00298 00299 Length - inclusive length in bytes of area to mark dirty. 00300 00301 Return Value: 00302 00303 TRUE - it worked 00304 00305 FALSE - could not allocate log space, failure! 00306 00307 --*/ 00308 { 00309 ULONG Type; 00310 PRTL_BITMAP BitMap; 00311 ULONG First; 00312 ULONG Last; 00313 ULONG i; 00314 ULONG Cluster; 00315 ULONG OriginalDirtyCount; 00316 ULONG DirtySectors; 00317 BOOLEAN Result = TRUE; 00318 00319 CMLOG(CML_MINOR, CMS_IO) { 00320 KdPrint(("HvMarkDirty:\n\t")); 00321 KdPrint(("Hive:%08lx Start:%08lx Length:%08lx\n", Hive, Start, Length)); 00322 } 00323 00324 00325 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00326 ASSERT(Hive->ReadOnly == FALSE); 00327 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00328 00329 Type = HvGetCellType(Start); 00330 00331 if ( (Hive->HiveFlags & HIVE_VOLATILE) || 00332 (Type == Volatile) ) 00333 { 00334 return TRUE; 00335 } 00336 00337 00338 BitMap = &(Hive->DirtyVector); 00339 OriginalDirtyCount = Hive->DirtyCount; 00340 00341 First = Start / HSECTOR_SIZE; 00342 Last = (Start + Length - 1) / HSECTOR_SIZE; 00343 00344 Cluster = Hive->Cluster; 00345 if (Cluster > 1) { 00346 00347 // 00348 // Force Start down to base of cluster 00349 // Force End up to top of cluster 00350 // 00351 First = First & ~(Cluster - 1); 00352 Last = ROUND_UP(Last+1, Cluster) - 1; 00353 } 00354 00355 if (Last >= BitMap->SizeOfBitMap) { 00356 Last = BitMap->SizeOfBitMap-1; 00357 } 00358 00359 // 00360 // Try and grow the log enough to accomodate all the dirty sectors. 00361 // 00362 DirtySectors = 0; 00363 for (i = First; i <= Last; i++) { 00364 if (RtlCheckBit(BitMap, i)==0) { 00365 ++DirtySectors; 00366 } 00367 } 00368 if (DirtySectors != 0) { 00369 if (HvpGrowLog1(Hive, DirtySectors) == FALSE) { 00370 return(FALSE); 00371 } 00372 00373 if ((OriginalDirtyCount == 0) && (First != 0)) { 00374 Result = HvMarkDirty(Hive, 0, sizeof(HBIN)); // force header of 1st bin dirty 00375 if (Result==FALSE) { 00376 return(FALSE); 00377 } 00378 } 00379 00380 // 00381 // Log has been successfully grown, go ahead 00382 // and set the dirty bits. 00383 // 00384 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00385 Hive->DirtyCount += DirtySectors; 00386 RtlSetBits(BitMap, First, Last-First+1); 00387 } 00388 00389 // mark this bin as writable 00390 HvpMarkBinReadWrite(Hive,Start); 00391 00392 if (!(Hive->HiveFlags & HIVE_NOLAZYFLUSH)) { 00393 CmpLazyFlush(); 00394 } 00395 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00396 return(TRUE); 00397 }

VOID HvpDiscardBins IN PHHIVE  Hive  ) 
 

Definition at line 1885 of file hivesync.c.

References ASSERT, ASSERT_LISTENTRY, Bin, _HMAP_ENTRY::BinAddress, ExFreePool(), _FREE_HBIN::FileOffset, _FREE_HBIN::Flags, FREE_HBIN_DISCARDABLE, Hive, HMAP_BASE, HMAP_DISCARDABLE, HvpGetCellMap(), List, Stable, and VALIDATE_CELL_MAP.

Referenced by HvSyncHive().

01891 : 01892 01893 Walks through the dirty bins in a hive to see if any are marked 01894 discardable. If so, they are discarded and the map is updated to 01895 reflect this. 01896 01897 Arguments: 01898 01899 Hive - Supplies the hive control structure. 01900 01901 Return Value: 01902 01903 None. 01904 01905 --*/ 01906 01907 { 01908 PHBIN Bin; 01909 PHMAP_ENTRY Map; 01910 PHMAP_ENTRY PreviousMap; 01911 PHMAP_ENTRY NextMap; 01912 PFREE_HBIN FreeBin; 01913 PFREE_HBIN PreviousFreeBin; 01914 PFREE_HBIN NextFreeBin; 01915 PLIST_ENTRY List; 01916 01917 List = Hive->Storage[Stable].FreeBins.Flink; 01918 01919 while (List != &Hive->Storage[Stable].FreeBins) { 01920 ASSERT_LISTENTRY(List); 01921 FreeBin = CONTAINING_RECORD(List, FREE_HBIN, ListEntry); 01922 01923 if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) { 01924 Map = HvpGetCellMap(Hive, FreeBin->FileOffset); 01925 VALIDATE_CELL_MAP(__LINE__,Map,Hive,FreeBin->FileOffset); 01926 Bin = (PHBIN)(Map->BinAddress & HMAP_BASE); 01927 ASSERT(Map->BinAddress & HMAP_DISCARDABLE); 01928 // 01929 // Note we use ExFreePool directly here to avoid 01930 // giving back the quota for this bin. By charging 01931 // registry quota for discarded bins, we prevent 01932 // sparse hives from requiring more quota after 01933 // a reboot than on a running system. 01934 // 01935 ExFreePool(Bin); 01936 FreeBin->Flags &= ~FREE_HBIN_DISCARDABLE; 01937 } 01938 List=List->Flink; 01939 } 01940 01941 }

VOID HvpDiscardBins PHHIVE  Hive  ) 
 

BOOLEAN HvpDoWriteHive PHHIVE  Hive,
ULONG  FileType
 

Definition at line 775 of file hivesync.c.

References ASSERT, _HHIVE::BaseBlock, Bin, BitMap, _HMAP_ENTRY::BlockAddress, _HBASE_BLOCK::CheckSum, _HHIVE::Cluster, _HBASE_BLOCK::Cluster, CML_MINOR, CMLOG, CmpDoFileSetSize(), CMS_IO, Count, CMP_OFFSET_ARRAY::DataBuffer, CMP_OFFSET_ARRAY::DataLength, _HHIVE::DirtyVector, ExAllocatePool, ExFreePool(), FALSE, _HHIVE::FileFlush, CMP_OFFSET_ARRAY::FileOffset, _HHIVE::FileWrite, _HBASE_BLOCK::Format, HBASE_BLOCK_SIGNATURE, HBASE_FORMAT_MEMORY, HBLOCK_SIZE, HFILE_TYPE_LOG, HFILE_TYPE_PRIMARY, Hive, HLOG_MINSIZE, HSECTOR_SIZE, HSYS_MAJOR, HvpFindNextDirtyBlock(), HvpGetCellMap(), HvpHeaderCheckSum(), _HBASE_BLOCK::Length, _HHIVE::Log, _HHIVE::LogSize, _HBASE_BLOCK::Major, NULL, Offset, PagedPool, PCMP_OFFSET_ARRAY, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), _HBASE_BLOCK::Sequence1, _HBASE_BLOCK::Sequence2, _HBASE_BLOCK::Signature, Stable, _HBASE_BLOCK::TimeStamp, _HBIN::TimeStamp, TRUE, _HBASE_BLOCK::Type, and VALIDATE_CELL_MAP.

Referenced by HvInitializeHive(), HvSyncHive(), and HvWriteHive().

00781 : 00782 00783 Write dirty parts of the hive out to either its primary or alternate 00784 file. Write the header, flush, write all data, flush, update header, 00785 flush. Assume either logging or primary/alternate pairs used. 00786 00787 NOTE: TimeStamp is not set, assumption is that HvpWriteLog set 00788 that. It is only used for checking if Logs correspond anyway. 00789 00790 Arguments: 00791 00792 Hive - pointer to Hive for which dirty data is to be written. 00793 00794 FileType - indicated whether primary or alternate file should be written. 00795 00796 Return Value: 00797 00798 TRUE - it worked 00799 00800 FALSE - it failed 00801 00802 --*/ 00803 { 00804 PHBASE_BLOCK BaseBlock; 00805 ULONG Offset; 00806 PUCHAR Address; 00807 ULONG Length; 00808 BOOLEAN rc; 00809 ULONG Current; 00810 PRTL_BITMAP BitMap; 00811 PHMAP_ENTRY Me; 00812 PHBIN Bin; 00813 BOOLEAN ShrinkHive; 00814 PCMP_OFFSET_ARRAY offsetArray; 00815 CMP_OFFSET_ARRAY offsetElement; 00816 ULONG Count; 00817 ULONG SetBitCount; 00818 00819 CMLOG(CML_MINOR, CMS_IO) { 00820 KdPrint(("HvpDoWriteHive:\n\t")); 00821 KdPrint(("Hive:%08lx FileType:%08lx\n", Hive, FileType)); 00822 } 00823 00824 // 00825 // flush first, so that the filesystem structures get written to 00826 // disk if we have grown the file. 00827 // 00828 if (!(Hive->FileFlush)(Hive, FileType)) { 00829 return(FALSE); 00830 } 00831 00832 BaseBlock = Hive->BaseBlock; 00833 00834 if (BaseBlock->Length > Hive->Storage[Stable].Length) { 00835 ShrinkHive = TRUE; 00836 } else { 00837 ShrinkHive = FALSE; 00838 } 00839 00840 // 00841 // --- Write out header first time, flush --- 00842 // 00843 ASSERT(BaseBlock->Signature == HBASE_BLOCK_SIGNATURE); 00844 ASSERT(BaseBlock->Major == HSYS_MAJOR); 00845 ASSERT(BaseBlock->Format == HBASE_FORMAT_MEMORY); 00846 ASSERT(Hive->ReadOnly == FALSE); 00847 00848 00849 if (BaseBlock->Sequence1 != BaseBlock->Sequence2) { 00850 00851 // 00852 // Some previous log attempt failed, or this hive needs to 00853 // be recovered, so punt. 00854 // 00855 return FALSE; 00856 } 00857 00858 BaseBlock->Length = Hive->Storage[Stable].Length; 00859 00860 BaseBlock->Sequence1++; 00861 BaseBlock->Type = HFILE_TYPE_PRIMARY; 00862 BaseBlock->Cluster = Hive->Cluster; 00863 BaseBlock->CheckSum = HvpHeaderCheckSum(BaseBlock); 00864 00865 Offset = 0; 00866 offsetElement.FileOffset = Offset; 00867 offsetElement.DataBuffer = (PVOID) BaseBlock; 00868 offsetElement.DataLength = HSECTOR_SIZE * Hive->Cluster; 00869 rc = (Hive->FileWrite)( 00870 Hive, 00871 FileType, 00872 &offsetElement, 00873 1, 00874 &Offset 00875 ); 00876 00877 if (rc == FALSE) { 00878 return FALSE; 00879 } 00880 if ( ! (Hive->FileFlush)(Hive, FileType)) { 00881 return FALSE; 00882 } 00883 Offset = ROUND_UP(Offset, HBLOCK_SIZE); 00884 00885 // 00886 // --- Write out dirty data (only if there is any) --- 00887 // 00888 00889 if (Hive->DirtyVector.Buffer != NULL) { 00890 // 00891 // First sector of first bin will always be dirty, write it out 00892 // with the TimeStamp value overlaid on its Link field. 00893 // 00894 BitMap = &(Hive->DirtyVector); 00895 00896 ASSERT(RtlCheckBit(BitMap, 0) == 1); 00897 ASSERT(RtlCheckBit(BitMap, (Hive->Cluster - 1)) == 1); 00898 ASSERT(sizeof(LIST_ENTRY) >= sizeof(LARGE_INTEGER)); 00899 00900 Me = HvpGetCellMap(Hive, 0); 00901 VALIDATE_CELL_MAP(__LINE__,Me,Hive,0); 00902 Address = (PUCHAR)Me->BlockAddress; 00903 Length = Hive->Cluster * HSECTOR_SIZE; 00904 Bin = (PHBIN)Address; 00905 Bin->TimeStamp = BaseBlock->TimeStamp; 00906 00907 offsetElement.FileOffset = Offset; 00908 offsetElement.DataBuffer = (PVOID) Address; 00909 offsetElement.DataLength = Length; 00910 rc = (Hive->FileWrite)( 00911 Hive, 00912 FileType, 00913 &offsetElement, 00914 1, 00915 &Offset 00916 ); 00917 ASSERT((Offset % (Hive->Cluster * HSECTOR_SIZE)) == 0); 00918 if (rc == FALSE) { 00919 return FALSE; 00920 } 00921 00922 00923 // 00924 // Write out the rest of the dirty data 00925 // 00926 Current = Hive->Cluster; // don't rewrite 1st bin or header 00927 00928 SetBitCount = RtlNumberOfSetBits(BitMap); 00929 offsetArray = 00930 (PCMP_OFFSET_ARRAY) 00931 ExAllocatePool(PagedPool, 00932 sizeof(CMP_OFFSET_ARRAY) * SetBitCount); 00933 if (offsetArray == NULL) { 00934 return FALSE; 00935 } 00936 Count = 0; 00937 00938 while (HvpFindNextDirtyBlock( 00939 Hive, 00940 BitMap, 00941 &Current, 00942 &Address, 00943 &Length, 00944 &Offset 00945 ) == TRUE) 00946 { 00947 // Gather data into array. 00948 ASSERT(Count < SetBitCount); 00949 offsetArray[Count].FileOffset = Offset; 00950 offsetArray[Count].DataBuffer = Address; 00951 offsetArray[Count].DataLength = Length; 00952 Offset += Length; 00953 Count++; 00954 ASSERT((Offset % (Hive->Cluster * HSECTOR_SIZE)) == 0); 00955 } 00956 00957 rc = (Hive->FileWrite)( 00958 Hive, 00959 FileType, 00960 offsetArray, 00961 Count, 00962 &Offset // Just an OUT parameter which returns the point 00963 // in the file after the last write. 00964 ); 00965 ExFreePool(offsetArray); 00966 if (rc == FALSE) { 00967 return FALSE; 00968 } 00969 } 00970 00971 if ( ! (Hive->FileFlush)(Hive, FileType)) { 00972 return FALSE; 00973 } 00974 00975 // 00976 // --- Write header again to report completion --- 00977 // 00978 BaseBlock->Sequence2++; 00979 BaseBlock->CheckSum = HvpHeaderCheckSum(BaseBlock); 00980 Offset = 0; 00981 00982 offsetElement.FileOffset = Offset; 00983 offsetElement.DataBuffer = (PVOID) BaseBlock; 00984 offsetElement.DataLength = HSECTOR_SIZE * Hive->Cluster; 00985 rc = (Hive->FileWrite)( 00986 Hive, 00987 FileType, 00988 &offsetElement, 00989 1, 00990 &Offset 00991 ); 00992 if (rc == FALSE) { 00993 return FALSE; 00994 } 00995 00996 if (ShrinkHive) { 00997 // 00998 // Hive has shrunk, give up the excess space. 00999 // 01000 CmpDoFileSetSize(Hive, FileType, Hive->Storage[Stable].Length + HBLOCK_SIZE); 01001 } 01002 01003 if ( ! (Hive->FileFlush)(Hive, FileType)) { 01004 return FALSE; 01005 } 01006 01007 if ((Hive->Log) && 01008 (Hive->LogSize > HLOG_MINSIZE(Hive))) { 01009 // 01010 // Shrink log back down, reserve at least two clusters 01011 // worth of space so that if all the disk space is 01012 // consumed, there will still be enough space prereserved 01013 // to allow a minimum of registry operations so the user 01014 // can log on. 01015 // 01016 CmpDoFileSetSize(Hive, HFILE_TYPE_LOG, HLOG_MINSIZE(Hive)); 01017 Hive->LogSize = HLOG_MINSIZE(Hive); 01018 } 01019 01020 return TRUE; 01021 }

BOOLEAN HvpFindNextDirtyBlock PHHIVE  Hive,
PRTL_BITMAP  BitMap,
PULONG  Current,
PUCHAR *  Address,
PULONG  Length,
PULONG  Offset
 

Definition at line 1233 of file hivesync.c.

References ASSERT, _HMAP_ENTRY::BinAddress, BitMap, _HMAP_ENTRY::BlockAddress, CML_FLOW, CMLOG, CMS_IO, End, FALSE, _FREE_HBIN::FileOffset, HBIN_SIGNATURE, HBLOCK_SIZE, HCELL_INDEX, HCELL_OFFSET_MASK, Hive, HMAP_BASE, HMAP_DISCARDABLE, HSECTOR_COUNT, HSECTOR_SIZE, HvpGetCellMap(), NULL, Offset, ROUND_UP, Start, TRUE, and VALIDATE_CELL_MAP.

Referenced by HvpDoWriteHive(), HvpWriteLog(), and HvRefreshHive().

01243 : 01244 01245 This routine finds and reports the largest run of dirty logical 01246 sectors in the hive, which are contiguous in memory and on disk. 01247 01248 Arguments: 01249 01250 Hive - pointer to Hive of interest. 01251 01252 BitMap - supplies a pointer to a bitmap structure, which 01253 describes what is dirty. 01254 01255 Current - supplies a pointer to a varible that tracks position 01256 in the bitmap. It is a bitnumber. It is updated by 01257 this call. 01258 01259 Address - supplies a pointer to a variable to receive a pointer 01260 to the area in memory to be written out. 01261 01262 Length - supplies a pointer to a variable to receive the length 01263 of the region to read/write 01264 01265 Offset - supplies a pointer to a variable to receive the offset 01266 in the backing file to which the data should be written. 01267 (not valid for log files) 01268 01269 Return Value: 01270 01271 TRUE - more to write, ret values good 01272 01273 FALSE - all data has been written 01274 01275 --*/ 01276 { 01277 ULONG i; 01278 ULONG EndOfBitMap; 01279 ULONG Start; 01280 ULONG End; 01281 HCELL_INDEX FileBaseAddress; 01282 HCELL_INDEX FileEndAddress; 01283 PHMAP_ENTRY Me; 01284 PUCHAR Block; 01285 PUCHAR StartBlock; 01286 PUCHAR NextBlock; 01287 ULONG RunSpan; 01288 ULONG RunLength; 01289 ULONG FileLength; 01290 PFREE_HBIN FreeBin; 01291 01292 CMLOG(CML_FLOW, CMS_IO) { 01293 KdPrint(("HvpFindNextDirtyBlock:\n\t")); 01294 KdPrint(("Hive:%08lx Current:%08lx\n", Hive, *Current)); 01295 } 01296 01297 01298 EndOfBitMap = BitMap->SizeOfBitMap; 01299 01300 if (*Current >= EndOfBitMap) { 01301 return FALSE; 01302 } 01303 01304 // 01305 // Find next run of set bits 01306 // 01307 for (i = *Current; i < EndOfBitMap; i++) { 01308 if (RtlCheckBit(BitMap, i) == 1) { 01309 break; 01310 } 01311 } 01312 Start = i; 01313 01314 for ( ; i < EndOfBitMap; i++) { 01315 if (RtlCheckBit(BitMap, i) == 0) { 01316 break; 01317 } 01318 } 01319 End = i; 01320 01321 01322 // 01323 // Compute hive virtual addresses, beginning file address, memory address 01324 // 01325 FileBaseAddress = Start * HSECTOR_SIZE; 01326 FileEndAddress = End * HSECTOR_SIZE; 01327 FileLength = FileEndAddress - FileBaseAddress; 01328 if (FileLength == 0) { 01329 *Address = NULL; 01330 *Current = 0xffffffff; 01331 *Length = 0; 01332 return FALSE; 01333 } 01334 Me = HvpGetCellMap(Hive, FileBaseAddress); 01335 VALIDATE_CELL_MAP(__LINE__,Me,Hive,FileBaseAddress); 01336 01337 if (Me->BinAddress & HMAP_DISCARDABLE) { 01338 FreeBin = (PFREE_HBIN)Me->BlockAddress; 01339 StartBlock = (PUCHAR)((Me->BinAddress & HMAP_BASE) + FileBaseAddress - FreeBin->FileOffset ); 01340 } else { 01341 StartBlock = (PUCHAR)Me->BlockAddress; 01342 } 01343 01344 Block = StartBlock; 01345 ASSERT(((PHBIN)(Me->BinAddress & HMAP_BASE))->Signature == HBIN_SIGNATURE); 01346 *Address = Block + (FileBaseAddress & HCELL_OFFSET_MASK); 01347 01348 *Offset = FileBaseAddress + HBLOCK_SIZE; 01349 01350 // 01351 // Build up length. First, account for sectors in first block. 01352 // 01353 RunSpan = HSECTOR_COUNT - (Start % HSECTOR_COUNT); 01354 01355 if ((End - Start) <= RunSpan) { 01356 01357 // 01358 // Entire length is in first block, return it 01359 // 01360 *Length = FileLength; 01361 *Current = End; 01362 return TRUE; 01363 01364 } else { 01365 01366 RunLength = RunSpan * HSECTOR_SIZE; 01367 FileBaseAddress = ROUND_UP(FileBaseAddress+1, HBLOCK_SIZE); 01368 01369 } 01370 01371 // 01372 // Scan forward through blocks, filling up length as we go. 01373 // 01374 // NOTE: This loop grows forward 1 block at time. If we were 01375 // really clever we'd fill forward a bin at time, since 01376 // bins are always contiguous. But most bins will be 01377 // one block long anyway, so we won't bother for now. 01378 // 01379 while (RunLength < FileLength) { 01380 01381 Me = HvpGetCellMap(Hive, FileBaseAddress); 01382 VALIDATE_CELL_MAP(__LINE__,Me,Hive,FileBaseAddress); 01383 ASSERT(((PHBIN)(Me->BinAddress & HMAP_BASE))->Signature == HBIN_SIGNATURE); 01384 01385 if (Me->BinAddress & HMAP_DISCARDABLE) { 01386 FreeBin = (PFREE_HBIN)Me->BlockAddress; 01387 NextBlock = (PUCHAR)((Me->BinAddress & HMAP_BASE) + FileBaseAddress - FreeBin->FileOffset ); 01388 } else { 01389 NextBlock = (PUCHAR)Me->BlockAddress; 01390 } 01391 01392 if ( (NextBlock - Block) != HBLOCK_SIZE) { 01393 01394 // 01395 // We've hit a discontinuity in memory. RunLength is 01396 // as long as it's going to get. 01397 // 01398 break; 01399 } 01400 01401 01402 if ((FileEndAddress - FileBaseAddress) <= HBLOCK_SIZE) { 01403 01404 // 01405 // We've reached the tail block, all is contiguous, 01406 // fill up to end and return. 01407 // 01408 *Length = FileLength; 01409 *Current = End; 01410 return TRUE; 01411 } 01412 01413 // 01414 // Just another contiguous block, fill forward 01415 // 01416 RunLength += HBLOCK_SIZE; 01417 RunSpan += HSECTOR_COUNT; 01418 FileBaseAddress += HBLOCK_SIZE; 01419 Block = NextBlock; 01420 } 01421 01422 // 01423 // We either hit a discontinuity, OR, we're at the end of the range 01424 // we're trying to fill. In either case, return. 01425 // 01426 *Length = RunLength; 01427 *Current = Start + RunSpan; 01428 return TRUE; 01429 }

BOOLEAN HvpGrowLog1 PHHIVE  Hive,
ULONG  Count
 

Definition at line 495 of file hivesync.c.

References ASSERT, _HHIVE::Cluster, CML_MINOR, CMLOG, CMS_IO, Count, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, _HHIVE::FileSetSize, HFILE_TYPE_LOG, Hive, HLOG_GROW, HSECTOR_SIZE, _HHIVE::Log, _HHIVE::LogSize, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), and TRUE.

Referenced by HvMarkDirty().

00501 : 00502 00503 Adjust the log for growth in the number of sectors of dirty 00504 data that are desired. 00505 00506 Arguments: 00507 00508 Hive - supplies a pointer to the hive control structure for the 00509 hive of interest 00510 00511 Count - number of additional logical sectors of log space needed 00512 00513 Return Value: 00514 00515 TRUE - it worked 00516 00517 FALSE - could not allocate log space, failure! 00518 00519 --*/ 00520 { 00521 ULONG ClusterSize; 00522 ULONG RequiredSize; 00523 ULONG tmp; 00524 00525 CMLOG(CML_MINOR, CMS_IO) { 00526 KdPrint(("HvpGrowLog1:\n\t")); 00527 KdPrint(("Hive:%08lx Count:%08lx\n", Hive, Count)); 00528 } 00529 00530 ASSERT(Hive->ReadOnly == FALSE); 00531 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00532 00533 // 00534 // If logging is off, tell caller world is OK. 00535 // 00536 if (Hive->Log == FALSE) { 00537 return TRUE; 00538 } 00539 00540 ClusterSize = Hive->Cluster * HSECTOR_SIZE; 00541 00542 tmp = Hive->DirtyVector.SizeOfBitMap / 8; // bytes 00543 tmp += sizeof(ULONG); // signature 00544 00545 RequiredSize = 00546 ClusterSize + // 1 cluster for header 00547 ROUND_UP(tmp, ClusterSize) + 00548 ((Hive->DirtyCount + Count) * HSECTOR_SIZE); 00549 00550 RequiredSize = ROUND_UP(RequiredSize, HLOG_GROW); 00551 00552 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00553 00554 if ( ! (Hive->FileSetSize)(Hive, HFILE_TYPE_LOG, RequiredSize)) { 00555 return FALSE; 00556 } 00557 00558 Hive->LogSize = RequiredSize; 00559 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00560 return TRUE; 00561 }

BOOLEAN HvpGrowLog2 PHHIVE  Hive,
ULONG  Size
 

Definition at line 565 of file hivesync.c.

References ASSERT, _HHIVE::Cluster, CML_MINOR, CMLOG, CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, FALSE, _HHIVE::FileSetSize, HFILE_TYPE_LOG, Hive, HLOG_GROW, HSECTOR_SIZE, _HHIVE::Log, _HHIVE::LogSize, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), Size, Stable, and TRUE.

Referenced by HvpAddBin().

00571 : 00572 00573 Adjust the log for growth in the size of the hive, in particular, 00574 account for the increased space needed for a bigger dirty vector. 00575 00576 Arguments: 00577 00578 Hive - supplies a pointer to the hive control structure for the 00579 hive of interest 00580 00581 Size - proposed growth in size in bytes. 00582 00583 Return Value: 00584 00585 TRUE - it worked 00586 00587 FALSE - could not allocate log space, failure! 00588 00589 --*/ 00590 { 00591 ULONG ClusterSize; 00592 ULONG RequiredSize; 00593 ULONG DirtyBytes; 00594 00595 CMLOG(CML_MINOR, CMS_IO) { 00596 KdPrint(("HvpGrowLog2:\n\t")); 00597 KdPrint(("Hive:%08lx Size:%08lx\n", Hive, Size)); 00598 } 00599 00600 ASSERT(Hive->ReadOnly == FALSE); 00601 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00602 00603 00604 // 00605 // If logging is off, tell caller world is OK. 00606 // 00607 if (Hive->Log == FALSE) { 00608 return TRUE; 00609 } 00610 00611 ASSERT( (Size % HSECTOR_SIZE) == 0 ); 00612 00613 ClusterSize = Hive->Cluster * HSECTOR_SIZE; 00614 00615 ASSERT( (((Hive->Storage[Stable].Length + Size) / HSECTOR_SIZE) % 8) == 0); 00616 00617 DirtyBytes = (Hive->DirtyVector.SizeOfBitMap / 8) + 00618 ((Size / HSECTOR_SIZE) / 8) + 00619 sizeof(ULONG); // signature 00620 DirtyBytes = ROUND_UP(DirtyBytes, ClusterSize); 00621 00622 RequiredSize = 00623 ClusterSize + // 1 cluster for header 00624 (Hive->DirtyCount * HSECTOR_SIZE) + 00625 DirtyBytes; 00626 00627 RequiredSize = ROUND_UP(RequiredSize, HLOG_GROW); 00628 00629 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00630 00631 if ( ! (Hive->FileSetSize)(Hive, HFILE_TYPE_LOG, RequiredSize)) { 00632 return FALSE; 00633 } 00634 00635 Hive->LogSize = RequiredSize; 00636 ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector)); 00637 return TRUE; 00638 }

VOID HvpTruncateBins IN PHHIVE  Hive  ) 
 

Definition at line 1946 of file hivesync.c.

References _HMAP_ENTRY::BinAddress, _HMAP_ENTRY::BlockAddress, _FREE_HBIN::FileOffset, HBLOCK_SIZE, HCELL_TYPE_MASK, Hive, HMAP_DISCARDABLE, HSTORAGE_TYPE, HTYPE_COUNT, HvFreeHivePartial(), HvpGetCellMap(), and VALIDATE_CELL_MAP.

Referenced by HvSyncHive().

01952 : 01953 01954 Attempts to shrink the hive by truncating any bins that are discardable at 01955 the end of the hive. Applies to both stable and volatile storage. 01956 01957 Arguments: 01958 01959 Hive - Supplies the hive to be truncated. 01960 01961 Return Value: 01962 01963 None. 01964 01965 --*/ 01966 01967 { 01968 HSTORAGE_TYPE i; 01969 PHMAP_ENTRY Map; 01970 ULONG NewLength; 01971 PFREE_HBIN FreeBin; 01972 01973 // 01974 // stable and volatile 01975 // 01976 for (i=0;i<HTYPE_COUNT;i++) { 01977 01978 // 01979 // find the last in-use bin in the hive 01980 // 01981 NewLength = Hive->Storage[i].Length; 01982 01983 while (NewLength > 0) { 01984 Map = HvpGetCellMap(Hive, (NewLength - HBLOCK_SIZE) + (i*HCELL_TYPE_MASK)); 01985 VALIDATE_CELL_MAP(__LINE__,Map,Hive,(NewLength - HBLOCK_SIZE) + (i*HCELL_TYPE_MASK)); 01986 if (Map->BinAddress & HMAP_DISCARDABLE) { 01987 FreeBin = (PFREE_HBIN)Map->BlockAddress; 01988 NewLength = FreeBin->FileOffset; 01989 } else { 01990 break; 01991 } 01992 } 01993 01994 if (NewLength < Hive->Storage[i].Length) { 01995 // 01996 // There are some free bins to truncate. 01997 // 01998 HvFreeHivePartial(Hive, NewLength, i); 01999 } 02000 } 02001 }

VOID HvpTruncateBins PHHIVE  Hive  ) 
 

BOOLEAN HvpWriteLog PHHIVE  Hive  ) 
 

Definition at line 1025 of file hivesync.c.

References ASSERT, _HHIVE::BaseBlock, BitMap, _HBASE_BLOCK::CheckSum, _HBASE_BLOCK::Cluster, _HHIVE::Cluster, CML_MINOR, CMLOG, CMS_IO, Count, CMP_OFFSET_ARRAY::DataBuffer, CMP_OFFSET_ARRAY::DataLength, _HHIVE::DirtyVector, ExAllocatePool, ExFreePool(), FALSE, _HHIVE::FileFlush, CMP_OFFSET_ARRAY::FileOffset, _HHIVE::FileWrite, _HBASE_BLOCK::Format, HBASE_BLOCK_SIGNATURE, HBASE_FORMAT_MEMORY, HFILE_TYPE_LOG, Hive, HLOG_DV_SIGNATURE, HLOG_HEADER_SIZE, HSECTOR_SIZE, HSYS_MAJOR, HvpFindNextDirtyBlock(), HvpHeaderCheckSum(), KeQuerySystemTime(), _HBASE_BLOCK::Major, NULL, Offset, PagedPool, PCMP_OFFSET_ARRAY, _HHIVE::ReadOnly, ROUND_UP, RtlNumberOfSetBits(), _HBASE_BLOCK::Sequence1, _HBASE_BLOCK::Sequence2, _HBASE_BLOCK::Signature, _HBASE_BLOCK::TimeStamp, TRUE, and _HBASE_BLOCK::Type.

Referenced by HvSyncHive().

01030 : 01031 01032 Write a header, the DirtyVector, and all the dirty data into 01033 the log file. Do flushes at the right places. Update the header. 01034 01035 Arguments: 01036 01037 Hive - pointer to Hive for which dirty data is to be logged. 01038 01039 Return Value: 01040 01041 TRUE - it worked 01042 01043 FALSE - it failed 01044 01045 --*/ 01046 { 01047 PHBASE_BLOCK BaseBlock; 01048 ULONG Offset; 01049 PUCHAR Address; 01050 ULONG Length; 01051 BOOLEAN rc; 01052 ULONG Current; 01053 ULONG junk; 01054 ULONG ClusterSize; 01055 ULONG HeaderLength; 01056 PRTL_BITMAP BitMap; 01057 ULONG DirtyVectorSignature = HLOG_DV_SIGNATURE; 01058 LARGE_INTEGER systemtime; 01059 PCMP_OFFSET_ARRAY offsetArray; 01060 CMP_OFFSET_ARRAY offsetElement; 01061 ULONG Count; 01062 ULONG SetBitCount; 01063 01064 CMLOG(CML_MINOR, CMS_IO) { 01065 KdPrint(("HvpWriteLog:\n\t")); 01066 KdPrint(("Hive:%08lx\n", Hive)); 01067 } 01068 01069 BitMap = &Hive->DirtyVector; 01070 // 01071 // --- Write out header first time, flush --- 01072 // 01073 BaseBlock = Hive->BaseBlock; 01074 ASSERT(BaseBlock->Signature == HBASE_BLOCK_SIGNATURE); 01075 ASSERT(BaseBlock->Major == HSYS_MAJOR); 01076 ASSERT(BaseBlock->Format == HBASE_FORMAT_MEMORY); 01077 ASSERT(Hive->ReadOnly == FALSE); 01078 01079 01080 if (BaseBlock->Sequence1 != BaseBlock->Sequence2) { 01081 01082 // 01083 // Some previous log attempt failed, or this hive needs to 01084 // be recovered, so punt. 01085 // 01086 return FALSE; 01087 } 01088 01089 BaseBlock->Sequence1++; 01090 KeQuerySystemTime(&systemtime); 01091 BaseBlock->TimeStamp = systemtime; 01092 01093 BaseBlock->Type = HFILE_TYPE_LOG; 01094 01095 ClusterSize = Hive->Cluster * HSECTOR_SIZE; 01096 HeaderLength = ROUND_UP(HLOG_HEADER_SIZE, ClusterSize); 01097 BaseBlock->Cluster = Hive->Cluster; 01098 01099 BaseBlock->CheckSum = HvpHeaderCheckSum(BaseBlock); 01100 01101 Offset = 0; 01102 offsetElement.FileOffset = Offset; 01103 offsetElement.DataBuffer = (PVOID) BaseBlock; 01104 offsetElement.DataLength = HSECTOR_SIZE * Hive->Cluster; 01105 rc = (Hive->FileWrite)( 01106 Hive, 01107 HFILE_TYPE_LOG, 01108 &offsetElement, 01109 1, 01110 &Offset 01111 ); 01112 if (rc == FALSE) { 01113 return FALSE; 01114 } 01115 Offset = ROUND_UP(Offset, HeaderLength); 01116 if ( ! (Hive->FileFlush)(Hive, HFILE_TYPE_LOG)) { 01117 return FALSE; 01118 } 01119 01120 // 01121 // --- Write out dirty vector --- 01122 // 01123 ASSERT(sizeof(ULONG) == sizeof(DirtyVectorSignature)); // See GrowLog1 above 01124 offsetElement.FileOffset = Offset; 01125 offsetElement.DataBuffer = (PVOID) &DirtyVectorSignature; 01126 offsetElement.DataLength = sizeof(DirtyVectorSignature); 01127 rc = (Hive->FileWrite)( 01128 Hive, 01129 HFILE_TYPE_LOG, 01130 &offsetElement, 01131 1, 01132 &Offset 01133 ); 01134 if (rc == FALSE) { 01135 return FALSE; 01136 } 01137 01138 Length = Hive->DirtyVector.SizeOfBitMap / 8; 01139 Address = (PUCHAR)(Hive->DirtyVector.Buffer); 01140 offsetElement.FileOffset = Offset; 01141 offsetElement.DataBuffer = (PVOID) Address; 01142 offsetElement.DataLength = Length; 01143 rc = (Hive->FileWrite)( 01144 Hive, 01145 HFILE_TYPE_LOG, 01146 &offsetElement, 01147 1, 01148 &Offset 01149 ); 01150 if (rc == FALSE) { 01151 return FALSE; 01152 } 01153 Offset = ROUND_UP(Offset, ClusterSize); 01154 01155 // 01156 // --- Write out body of log --- 01157 // 01158 SetBitCount = RtlNumberOfSetBits(BitMap); 01159 offsetArray = 01160 (PCMP_OFFSET_ARRAY) 01161 ExAllocatePool(PagedPool, 01162 sizeof(CMP_OFFSET_ARRAY) * SetBitCount); 01163 if (offsetArray == NULL) { 01164 return FALSE; 01165 } 01166 Count = 0; 01167 01168 Current = 0; 01169 while (HvpFindNextDirtyBlock( 01170 Hive, 01171 BitMap, 01172 &Current, 01173 &Address, 01174 &Length, 01175 &junk 01176 ) == TRUE) 01177 { 01178 // Gather data into array. 01179 ASSERT(Count < SetBitCount); 01180 offsetArray[Count].FileOffset = Offset; 01181 offsetArray[Count].DataBuffer = Address; 01182 offsetArray[Count].DataLength = Length; 01183 Offset += Length; 01184 Count++; 01185 ASSERT((Offset % ClusterSize) == 0); 01186 } 01187 01188 rc = (Hive->FileWrite)( 01189 Hive, 01190 HFILE_TYPE_LOG, 01191 offsetArray, 01192 Count, 01193 &Offset // Just an OUT parameter which returns the point 01194 // in the file after the last write. 01195 ); 01196 ExFreePool(offsetArray); 01197 if (rc == FALSE) { 01198 return FALSE; 01199 } 01200 01201 if ( ! (Hive->FileFlush)(Hive, HFILE_TYPE_LOG)) { 01202 return FALSE; 01203 } 01204 01205 // 01206 // --- Write header again to report completion --- 01207 // 01208 BaseBlock->Sequence2++; 01209 BaseBlock->CheckSum = HvpHeaderCheckSum(BaseBlock); 01210 Offset = 0; 01211 offsetElement.FileOffset = Offset; 01212 offsetElement.DataBuffer = (PVOID) BaseBlock; 01213 offsetElement.DataLength = HSECTOR_SIZE * Hive->Cluster; 01214 rc = (Hive->FileWrite)( 01215 Hive, 01216 HFILE_TYPE_LOG, 01217 &offsetElement, 01218 1, 01219 &Offset 01220 ); 01221 if (rc == FALSE) { 01222 return FALSE; 01223 } 01224 if ( ! (Hive->FileFlush)(Hive, HFILE_TYPE_LOG)) { 01225 return FALSE; 01226 } 01227 01228 return TRUE; 01229 }

VOID HvRefreshHive PHHIVE  Hive  ) 
 

Referenced by CmpWorker().

BOOLEAN HvSyncHive PHHIVE  Hive  ) 
 

Definition at line 647 of file hivesync.c.

References _HHIVE::Alternate, ASSERT, CML_BUGCHECK, CML_FLOW, CML_WORKER, CMLOG, CMS_IO, _HHIVE::DirtyCount, _HHIVE::DirtyVector, DumpDirtyVector, FALSE, HFILE_TYPE_ALTERNATE, HFILE_TYPE_PRIMARY, HHIVE_SIGNATURE, Hive, HIVE_VOLATILE, _HHIVE::HiveFlags, HvpDiscardBins(), HvpDoWriteHive(), HvpTruncateBins(), HvpWriteLog(), HvShutdownComplete, IoSetThreadHardErrorMode(), _HHIVE::Log, _HHIVE::ReadOnly, RtlClearAllBits(), _HHIVE::Signature, and TRUE.

Referenced by CmFlushKey(), CmpDoFlushAll(), CmpInitializeHiveList(), EhCloseHive(), and EhOpenHive().

00652 : 00653 00654 Force backing store to match the memory image of the Stable 00655 part of the hive's space. 00656 00657 Logs, primary, and alternate data can be written. Primary is 00658 always written. Normally either a log or an alternate, but 00659 not both, will also be written. 00660 00661 It is possible to write only the primary. 00662 00663 All dirty bits will be set clear. 00664 00665 Arguments: 00666 00667 Hive - supplies a pointer to the hive control structure for the 00668 hive of interest 00669 00670 Return Value: 00671 00672 TRUE - it worked 00673 00674 FALSE - some failure. 00675 00676 --*/ 00677 { 00678 BOOLEAN oldFlag; 00679 00680 CMLOG(CML_WORKER, CMS_IO) { 00681 KdPrint(("HvSyncHive:\n\t")); 00682 KdPrint(("Hive:%08lx\n", Hive)); 00683 } 00684 00685 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 00686 ASSERT(Hive->ReadOnly == FALSE); 00687 00688 // 00689 // Punt if post shutdown 00690 // 00691 if (HvShutdownComplete) { 00692 CMLOG(CML_BUGCHECK, CMS_IO) { 00693 KdPrint(("HvSyncHive: Attempt to sync AFTER SHUTDOWN\n")); 00694 } 00695 return FALSE; 00696 } 00697 00698 // 00699 // If nothing dirty, do nothing 00700 // 00701 if (Hive->DirtyCount == 0) { 00702 return TRUE; 00703 } 00704 00705 HvpTruncateBins(Hive); 00706 00707 // 00708 // If hive is volatile, do nothing 00709 // 00710 if (Hive->HiveFlags & HIVE_VOLATILE) { 00711 return TRUE; 00712 } 00713 00714 CMLOG(CML_FLOW, CMS_IO) { 00715 KdPrint(("\tDirtyCount:%08lx\n", Hive->DirtyCount)); 00716 KdPrint(("\tDirtyVector:")); 00717 DumpDirtyVector(Hive); 00718 } 00719 00720 // 00721 // disable hard error popups, to avoid self deadlock on bogus devices 00722 // 00723 oldFlag = IoSetThreadHardErrorMode(FALSE); 00724 00725 // 00726 // Write a log. 00727 // 00728 if (Hive->Log == TRUE) { 00729 if (HvpWriteLog(Hive) == FALSE) { 00730 IoSetThreadHardErrorMode(oldFlag); 00731 return FALSE; 00732 } 00733 } 00734 00735 // 00736 // Write the primary 00737 // 00738 if (HvpDoWriteHive(Hive, HFILE_TYPE_PRIMARY) == FALSE) { 00739 IoSetThreadHardErrorMode(oldFlag); 00740 return FALSE; 00741 } 00742 00743 // 00744 // Write an alternate 00745 // 00746 if (Hive->Alternate == TRUE) { 00747 if (HvpDoWriteHive(Hive, HFILE_TYPE_ALTERNATE) == FALSE) { 00748 IoSetThreadHardErrorMode(oldFlag); 00749 return FALSE; 00750 } 00751 } 00752 00753 // 00754 // restore hard error popups mode 00755 // 00756 IoSetThreadHardErrorMode(oldFlag); 00757 00758 // 00759 // Hive was successfully written out, discard any bins marked as 00760 // discardable. 00761 // 00762 HvpDiscardBins(Hive); 00763 00764 // 00765 // Clear the dirty map 00766 // 00767 RtlClearAllBits(&(Hive->DirtyVector)); 00768 Hive->DirtyCount = 0; 00769 00770 return TRUE; 00771 }

NTSTATUS HvWriteHive PHHIVE  Hive  ) 
 

Definition at line 1433 of file hivesync.c.

References _HHIVE::Allocate, ASSERT, _HHIVE::BaseBlock, _HHIVE::Cluster, CML_BUGCHECK, CML_MAJOR, CMLOG, CmpDoFileSetSize(), CmpFree(), CmpReleaseGlobalQuota(), CMS_IO, _HHIVE::DirtyVector, FALSE, _HHIVE::Free, HFILE_TYPE_EXTERNAL, HHIVE_SIGNATURE, Hive, HSECTOR_SIZE, HvpDoWriteHive(), HvShutdownComplete, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, _HHIVE::ReadOnly, ROUND_UP, RtlSetAllBits(), _HHIVE::Signature, Stable, and TRUE.

Referenced by CmpInitializeHiveList(), CmSaveKey(), and CmSaveMergedKeys().

01438 : 01439 01440 Write the hive out. Write only to the Primary file, neither 01441 logs nor alternates will be updated. The hive will be written 01442 to the HFILE_TYPE_EXTERNAL handle. 01443 01444 Intended for use in applications like SaveKey. 01445 01446 Only Stable storage will be written (as for any hive.) 01447 01448 Presumption is that layer above has set HFILE_TYPE_EXTERNAL 01449 handle to point to correct place. 01450 01451 Applying this call to an active hive will generally hose integrity 01452 measures. 01453 01454 HOW IT WORKS: 01455 01456 Make a new DirtyVector. Fill it with 1s (all dirty). 01457 Make hive point at it. We now have what looks like 01458 a completely dirty hive. 01459 01460 Call HvpWriteHive, which will write the whole thing to disk. 01461 01462 Put back DirtyVector, and free the extra one we used. 01463 01464 In failure case, force Sequence numbers in Hive and BaseBlock 01465 to match. 01466 01467 Arguments: 01468 01469 Hive - supplies a pointer to the hive control structure for the 01470 hive of interest. 01471 01472 Return Value: 01473 01474 Status. 01475 01476 --*/ 01477 { 01478 PULONG SaveDirtyVector; 01479 ULONG SaveDirtyVectorSize; 01480 PULONG AltDirtyVector; 01481 ULONG AltDirtyVectorSize; 01482 PHBASE_BLOCK SaveBaseBlock; 01483 PHBASE_BLOCK AltBaseBlock; 01484 ULONG Alignment; 01485 01486 NTSTATUS status; 01487 01488 01489 CMLOG(CML_MAJOR, CMS_IO) { 01490 KdPrint(("HvWriteHive: \n")); 01491 KdPrint(("\tHive = %08lx\n")); 01492 } 01493 ASSERT(Hive->Signature == HHIVE_SIGNATURE); 01494 ASSERT(Hive->ReadOnly == FALSE); 01495 01496 01497 // 01498 // Punt if post shutdown 01499 // 01500 if (HvShutdownComplete) { 01501 CMLOG(CML_BUGCHECK, CMS_IO) { 01502 KdPrint(("HvWriteHive: Attempt to write hive AFTER SHUTDOWN\n")); 01503 } 01504 return STATUS_REGISTRY_IO_FAILED; 01505 } 01506 01507 // 01508 // Splice in a duplicate DirtyVector with all bits set. 01509 // 01510 SaveDirtyVector = Hive->DirtyVector.Buffer; 01511 SaveDirtyVectorSize = Hive->DirtyVector.SizeOfBitMap; 01512 SaveBaseBlock = Hive->BaseBlock; 01513 01514 AltDirtyVectorSize = (Hive->Storage[Stable].Length / HSECTOR_SIZE) / 8; 01515 AltDirtyVector = (Hive->Allocate)(ROUND_UP(AltDirtyVectorSize,sizeof(ULONG)), FALSE); 01516 if (AltDirtyVector == NULL) { 01517 status = STATUS_INSUFFICIENT_RESOURCES; 01518 goto Exit1; 01519 } 01520 Hive->DirtyVector.Buffer = AltDirtyVector; 01521 Hive->DirtyVector.SizeOfBitMap = AltDirtyVectorSize * 8; 01522 RtlSetAllBits(&(Hive->DirtyVector)); 01523 01524 // 01525 // Splice in a duplicate BaseBlock 01526 // 01527 AltBaseBlock = (Hive->Allocate)(sizeof(HBASE_BLOCK), TRUE); 01528 if (AltBaseBlock == NULL) { 01529 status = STATUS_INSUFFICIENT_RESOURCES; 01530 goto Exit2; 01531 } 01532 // 01533 // Make sure the buffer we got back is cluster-aligned. If not, try 01534 // harder to get an aligned buffer. 01535 // 01536 Alignment = Hive->Cluster * HSECTOR_SIZE - 1; 01537 if (((ULONG_PTR)AltBaseBlock & Alignment) != 0) { 01538 (Hive->Free)(AltBaseBlock, sizeof(HBASE_BLOCK)); 01539 AltBaseBlock = (PHBASE_BLOCK)((Hive->Allocate)(PAGE_SIZE, TRUE)); 01540 if (AltBaseBlock == NULL) { 01541 status = STATUS_INSUFFICIENT_RESOURCES; 01542 goto Exit2; 01543 } 01544 // 01545 // Return the quota for the extra allocation, as we are not really using 01546 // it and it will not be accounted for later when we free it. 01547 // 01548 CmpReleaseGlobalQuota(PAGE_SIZE - sizeof(HBASE_BLOCK)); 01549 } 01550 01551 RtlMoveMemory(AltBaseBlock, SaveBaseBlock, HSECTOR_SIZE); 01552 Hive->BaseBlock = AltBaseBlock; 01553 01554 // 01555 // Ensure the file can be made big enough, then do the deed 01556 // 01557 status = CmpDoFileSetSize(Hive, 01558 HFILE_TYPE_EXTERNAL, 01559 Hive->Storage[Stable].Length); 01560 01561 if (NT_SUCCESS(status)) { 01562 if (!HvpDoWriteHive(Hive, HFILE_TYPE_EXTERNAL)) { 01563 status = STATUS_REGISTRY_IO_FAILED; 01564 } 01565 } 01566 01567 // 01568 // Clean up, success or failure 01569 // 01570 CmpFree(AltBaseBlock, sizeof(HBASE_BLOCK)); 01571 01572 Exit2: 01573 CmpFree(AltDirtyVector, ROUND_UP(AltDirtyVectorSize,sizeof(ULONG))); 01574 01575 Exit1: 01576 Hive->DirtyVector.Buffer = SaveDirtyVector; 01577 Hive->DirtyVector.SizeOfBitMap = SaveDirtyVectorSize; 01578 Hive->BaseBlock = SaveBaseBlock; 01579 return status; 01580 }


Variable Documentation

BOOLEAN HvShutdownComplete
 

Definition at line 27 of file hivesync.c.

Referenced by CmpLazyFlushWorker(), CmShutdownSystem(), HvSyncHive(), and HvWriteHive().


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