Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
9.2 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. hivefree.c
  5. Abstract:
  6. Hive free code
  7. Author:
  8. Bryan M. Willman (bryanwi) 30-Mar-92
  9. Environment:
  10. Revision History:
  11. Dragos C. Sambotin (dragoss) 25-Jan-99
  12. Implementation of bin-size chunk loading of hives.
  13. --*/
  14. #include "cmp.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE,HvFreeHive)
  17. #pragma alloc_text(PAGE,HvFreeHivePartial)
  18. #endif
  19. // Dragos: Modified functions
  20. VOID
  21. HvFreeHive(
  22. PHHIVE Hive
  23. )
  24. /*++
  25. Routine Description:
  26. Free all of the pieces of a hive.
  27. Arguments:
  28. Hive - supplies a pointer to hive control structure for hive to free.
  29. this structure itself will NOT be freed, but everything it
  30. points to will.
  31. Return Value:
  32. NONE.
  33. --*/
  34. {
  35. PHMAP_DIRECTORY Dir;
  36. PHMAP_ENTRY Me;
  37. HCELL_INDEX Address;
  38. ULONG Type;
  39. ULONG Length;
  40. PHBIN Bin;
  41. ULONG Tables;
  42. PFREE_HBIN FreeBin;
  43. ASSERT(Hive->Flat == FALSE);
  44. ASSERT(Hive->ReadOnly == FALSE);
  45. ASSERT(Stable == 0);
  46. ASSERT(Volatile == 1);
  47. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvFreeHive(%ws) :\n", Hive->BaseBlock->FileName));
  48. //
  49. // Iterate through both types of storage
  50. //
  51. for (Type = 0; Type <= Volatile; Type++) {
  52. Address = HCELL_TYPE_MASK * Type;
  53. Length = Hive->Storage[Type].Length + (HCELL_TYPE_MASK * Type);
  54. if (Length > (HCELL_TYPE_MASK * Type)) {
  55. //
  56. // Sweep through bin set
  57. //
  58. do {
  59. Me = HvpGetCellMap(Hive, Address);
  60. VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address);
  61. if (Me->BinAddress & HMAP_DISCARDABLE) {
  62. //
  63. // hbin is either discarded or discardable, check the tombstone
  64. //
  65. FreeBin = (PFREE_HBIN)Me->BlockAddress;
  66. Address += FreeBin->Size;
  67. if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) {
  68. CmpFree((PHBIN)HBIN_BASE(Me->BinAddress), FreeBin->Size);
  69. } else if(Me->BinAddress & HMAP_INPAGEDPOOL) {
  70. //
  71. // The bin has been freed, but quota is still charged.
  72. // Since the hive is being freed, the quota must be
  73. // returned here.
  74. //
  75. CmpReleaseGlobalQuota(FreeBin->Size);
  76. }
  77. CmpFree(FreeBin, sizeof(FREE_HBIN));
  78. } else {
  79. if( Me->BinAddress & HMAP_INPAGEDPOOL ) {
  80. ASSERT( Me->BinAddress & HMAP_INPAGEDPOOL );
  81. Bin = (PHBIN)HBIN_BASE(Me->BinAddress);
  82. Address += HvpGetBinMemAlloc(Hive,Bin,Type);
  83. #if 0
  84. //
  85. // Make sure that the next bin in the list is
  86. // actually the start of an alloc before freeing it
  87. //
  88. if (Address < Length) {
  89. TempMe = HvpGetCellMap(Hive, Address);
  90. VALIDATE_CELL_MAP(__LINE__,TempMe,Hive,Address);
  91. ASSERT(TempMe->BinAddress & HMAP_NEWALLOC);
  92. }
  93. #endif
  94. #if DBG
  95. if( Type == Stable ) {
  96. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvFreeHive: BinAddress = 0x%p\t Size = 0x%lx\n", Bin, HvpGetBinMemAlloc(Hive,Bin,Type)));
  97. }
  98. #endif
  99. //
  100. // free the actual bin only if it is allocated from paged pool
  101. //
  102. if(HvpGetBinMemAlloc(Hive,Bin,Type)) {
  103. CmpFree(Bin, HvpGetBinMemAlloc(Hive,Bin,Type));
  104. }
  105. } else {
  106. //
  107. // bin was mapped into view; advance carefully
  108. //
  109. Address += HBLOCK_SIZE;
  110. }
  111. }
  112. } while (Address < Length);
  113. //
  114. // Free map table storage
  115. //
  116. ASSERT(Hive->Storage[Type].Length != (HCELL_TYPE_MASK * Type));
  117. Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE)-1) / HTABLE_SLOTS;
  118. Dir = Hive->Storage[Type].Map;
  119. HvpFreeMap(Hive, Dir, 0, Tables);
  120. if (Tables > 0) {
  121. CmpFree(Hive->Storage[Type].Map, sizeof(HMAP_DIRECTORY)); // free dir if it exists
  122. }
  123. }
  124. Hive->Storage[Type].Length = 0;
  125. }
  126. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"\n"));
  127. //
  128. // Free the base block
  129. //
  130. (Hive->Free)(Hive->BaseBlock,Hive->BaseBlockAlloc);
  131. Hive->BaseBlock = NULL;
  132. //
  133. // Free the dirty vector
  134. //
  135. if (Hive->DirtyVector.Buffer != NULL) {
  136. CmpFree((PVOID)(Hive->DirtyVector.Buffer), Hive->DirtyAlloc);
  137. }
  138. HvpFreeHiveFreeDisplay(Hive);
  139. return;
  140. }
  141. VOID
  142. HvFreeHivePartial(
  143. PHHIVE Hive,
  144. HCELL_INDEX Start,
  145. HSTORAGE_TYPE Type
  146. )
  147. /*++
  148. Routine Description:
  149. Free the memory and associated maps for the end of a hive
  150. starting at Start. The baseblock, hive, etc will not be touched.
  151. Arguments:
  152. Hive - supplies a pointer to hive control structure for hive to
  153. partially free.
  154. Start - HCELL_INDEX of first bin to free, will free from this
  155. bin (inclusive) to the end of the hives stable storage.
  156. Type - Type of storage (Stable or Volatile) to be freed.
  157. Return Value:
  158. NONE.
  159. --*/
  160. {
  161. PHMAP_DIRECTORY Dir;
  162. PHMAP_ENTRY Me;
  163. HCELL_INDEX Address;
  164. ULONG StartTable;
  165. ULONG Length;
  166. PHBIN Bin;
  167. ULONG Tables;
  168. ULONG FirstBit;
  169. ULONG LastBit;
  170. PFREE_HBIN FreeBin;
  171. ASSERT(Hive->Flat == FALSE);
  172. ASSERT(Hive->ReadOnly == FALSE);
  173. Address = Start;
  174. Length = Hive->Storage[Type].Length;
  175. ASSERT(Address <= Length);
  176. if (Address == Length) {
  177. return;
  178. }
  179. //
  180. // Sweep through bin set
  181. //
  182. do {
  183. Me = HvpGetCellMap(Hive, Address + (Type*HCELL_TYPE_MASK));
  184. VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address + (Type*HCELL_TYPE_MASK));
  185. if (Me->BinAddress & HMAP_DISCARDABLE) {
  186. FreeBin = (PFREE_HBIN)Me->BlockAddress;
  187. if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) {
  188. CmpFree((PVOID)HBIN_BASE(Me->BinAddress), FreeBin->Size);
  189. } else {
  190. //
  191. // The bin has been freed, but quota is still charged.
  192. // Since the file will now shrink, the quota must be
  193. // returned here.
  194. //
  195. if( Me->BinAddress & HMAP_INPAGEDPOOL) {
  196. //
  197. // we charge quota only for bins in paged-pool
  198. //
  199. CmpReleaseGlobalQuota(FreeBin->Size);
  200. }
  201. }
  202. RemoveEntryList(&FreeBin->ListEntry);
  203. Address += FreeBin->Size;
  204. CmpFree(FreeBin, sizeof(FREE_HBIN));
  205. } else {
  206. Bin = (PHBIN)HBIN_BASE(Me->BinAddress);
  207. Address += HvpGetBinMemAlloc(Hive,Bin,Type);
  208. if( Me->BinAddress & HMAP_INPAGEDPOOL && HvpGetBinMemAlloc(Hive,Bin,Type) ) {
  209. //
  210. // free the bin only if it is allocated from paged pool
  211. //
  212. CmpFree(Bin, HvpGetBinMemAlloc(Hive,Bin,Type));
  213. }
  214. }
  215. } while (Address < Length);
  216. //
  217. // Free map table storage
  218. //
  219. Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE) - 1) / HTABLE_SLOTS;
  220. Dir = Hive->Storage[Type].Map;
  221. if (Start > 0) {
  222. StartTable = ((Start-1) / HBLOCK_SIZE) / HTABLE_SLOTS;
  223. } else {
  224. StartTable = (ULONG)-1;
  225. }
  226. HvpFreeMap(Hive, Dir, StartTable+1, Tables);
  227. //
  228. // update hysteresis (eventually queue work item)
  229. //
  230. if( Type == Stable) {
  231. CmpUpdateSystemHiveHysteresis(Hive,(Start&(~HCELL_TYPE_MASK)),Hive->Storage[Type].Length);
  232. }
  233. Hive->Storage[Type].Length = (Start&(~HCELL_TYPE_MASK));
  234. if (Type==Stable) {
  235. //
  236. // Clear dirty vector for data past Hive->Storage[Stable].Length
  237. //
  238. FirstBit = Start / HSECTOR_SIZE;
  239. LastBit = Hive->DirtyVector.SizeOfBitMap;
  240. ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector));
  241. RtlClearBits(&Hive->DirtyVector, FirstBit, LastBit-FirstBit);
  242. Hive->DirtyCount = RtlNumberOfSetBits(&Hive->DirtyVector);
  243. }
  244. HvpAdjustHiveFreeDisplay(Hive,Hive->Storage[Type].Length,Type);
  245. return;
  246. }