Source code of Windows XP (NT5)
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.

295 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. cmdelay.c
  5. Abstract:
  6. This module implements the new algorithm (LRU style) for the
  7. Delayed Close KCB table.
  8. Functions in this module are thread safe protected by the kcb lock.
  9. When kcb lock is converted to a resource, we should assert (enforce)
  10. exclusivity of that resource here !!!
  11. Note:
  12. We might want to convert these functions to macros after enough testing
  13. provides that they work well
  14. Author:
  15. Dragos C. Sambotin (dragoss) 09-Aug-1999
  16. Revision History:
  17. --*/
  18. #include "cmp.h"
  19. ULONG CmpDelayedCloseSize = 2048; // !!!! Cannot be bigger that 4094 !!!!!
  20. CM_DELAYED_CLOSE_ENTRY *CmpDelayedCloseTable;
  21. LIST_ENTRY CmpDelayedLRUListHead; // head of the LRU list of Delayed Close Table entries
  22. ULONG
  23. CmpGetDelayedCloseIndex( );
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text(PAGE,CmpInitializeDelayedCloseTable)
  26. #pragma alloc_text(PAGE,CmpRemoveFromDelayedClose)
  27. #pragma alloc_text(PAGE,CmpGetDelayedCloseIndex)
  28. #pragma alloc_text(PAGE,CmpAddToDelayedClose)
  29. #endif
  30. VOID
  31. CmpInitializeDelayedCloseTable()
  32. /*++
  33. Routine Description:
  34. Initialize delayed close table; allocation + LRU list initialization.
  35. Arguments:
  36. Return Value:
  37. NONE.
  38. --*/
  39. {
  40. ULONG i;
  41. PAGED_CODE();
  42. //
  43. // allocate the table from paged pool; it is important that the table
  44. // is contiguous in memory as we compute the index based on this assumption
  45. //
  46. CmpDelayedCloseTable = ExAllocatePoolWithTag(PagedPool,
  47. CmpDelayedCloseSize * sizeof(CM_DELAYED_CLOSE_ENTRY),
  48. CM_DELAYCLOSE_TAG);
  49. if (CmpDelayedCloseTable == NULL) {
  50. CM_BUGCHECK(CONFIG_INITIALIZATION_FAILED,INIT_DELAYED_CLOSE_TABLE,1,0,0);
  51. return;
  52. }
  53. //
  54. // Init LRUlist head.
  55. //
  56. InitializeListHead(&CmpDelayedLRUListHead);
  57. for (i=0; i<CmpDelayedCloseSize; i++) {
  58. //
  59. // mark it as available and add it to the end of the LRU list
  60. //
  61. CmpDelayedCloseTable[i].KeyControlBlock = NULL;
  62. InsertTailList(
  63. &CmpDelayedLRUListHead,
  64. &(CmpDelayedCloseTable[i].DelayedLRUList)
  65. );
  66. }
  67. }
  68. VOID
  69. CmpRemoveFromDelayedClose(
  70. IN PCM_KEY_CONTROL_BLOCK kcb
  71. )
  72. /*++
  73. Routine Description:
  74. Removes a KCB from the delayed close table;
  75. Arguments:
  76. kcb - the kcb in question
  77. Note:
  78. kcb lock/resource should be aquired exclusively when this function is called
  79. Return Value:
  80. NONE.
  81. --*/
  82. {
  83. ULONG i;
  84. PAGED_CODE();
  85. i = kcb->DelayedCloseIndex;
  86. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_FLOW,"[CmpRemoveFromDelayedClose] : Removing kcb = %p from DelayedCloseTable; index = %lu\n",kcb,(ULONG)i));
  87. //
  88. // at this index should be the this kcb and the index should not be bigger
  89. // than the size of the table
  90. //
  91. ASSERT(CmpDelayedCloseTable[i].KeyControlBlock == kcb);
  92. ASSERT( i < CmpDelayedCloseSize );
  93. //
  94. // nobody should hold references on this particular kcb
  95. //
  96. ASSERT( kcb->RefCount == 0 );
  97. //
  98. // mark the entry as available and add it to the end of the LRU list
  99. //
  100. CmpDelayedCloseTable[i].KeyControlBlock = NULL;
  101. CmpRemoveEntryList(&(CmpDelayedCloseTable[i].DelayedLRUList));
  102. InsertTailList(
  103. &CmpDelayedLRUListHead,
  104. &(CmpDelayedCloseTable[i].DelayedLRUList)
  105. );
  106. kcb->DelayedCloseIndex = CmpDelayedCloseSize;
  107. }
  108. ULONG
  109. CmpGetDelayedCloseIndex( )
  110. /*++
  111. Routine Description:
  112. Finds a free entry in the delayed close table and returns it.
  113. If the table is full, the kcb in the last entry (LRU-wise) is
  114. kicked out of the table and its entry is reused.
  115. Arguments:
  116. Note:
  117. kcb lock/resource should be aquired exclusively when this function is called
  118. Return Value:
  119. NONE.
  120. --*/
  121. {
  122. ULONG DelayedIndex;
  123. PCM_DELAYED_CLOSE_ENTRY DelayedEntry;
  124. PAGED_CODE();
  125. //
  126. // get the last entry in the Delayed LRU list
  127. //
  128. DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)CmpDelayedLRUListHead.Blink;
  129. DelayedEntry = CONTAINING_RECORD( DelayedEntry,
  130. CM_DELAYED_CLOSE_ENTRY,
  131. DelayedLRUList);
  132. if( DelayedEntry->KeyControlBlock != NULL ) {
  133. //
  134. // entry is not available; kick the kcb out of cache
  135. //
  136. ASSERT_KCB(DelayedEntry->KeyControlBlock);
  137. ASSERT( DelayedEntry->KeyControlBlock->RefCount == 0 );
  138. //
  139. // lock should be held here !!!
  140. //
  141. CmpCleanUpKcbCacheWithLock(DelayedEntry->KeyControlBlock);
  142. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_FLOW,"[CmpGetDelayedCloseIndex] : no index free; kicking kcb = %p index = %lu out of DelayedCloseTable\n",
  143. DelayedEntry->KeyControlBlock,(ULONG)(((PUCHAR)DelayedEntry - (PUCHAR)CmpDelayedCloseTable) / sizeof( CM_DELAYED_CLOSE_ENTRY ))));
  144. DelayedEntry->KeyControlBlock = NULL;
  145. }
  146. DelayedIndex = (ULONG) (((PUCHAR)DelayedEntry - (PUCHAR)CmpDelayedCloseTable) / sizeof( CM_DELAYED_CLOSE_ENTRY ));
  147. //
  148. // sanity check
  149. //
  150. ASSERT( DelayedIndex < CmpDelayedCloseSize );
  151. #if defined(_WIN64)
  152. //
  153. // somehow DelayedIndex is ok here but it gets corupted upon return from this api
  154. //
  155. if( DelayedIndex >= CmpDelayedCloseSize ) {
  156. DbgPrint("CmpGetDelayedCloseIndex: Bogus index %lx; DelayedEntry = %p; sizeof( CM_DELAYED_CLOSE_ENTRY ) = %lx\n",
  157. DelayedIndex,DelayedEntry,sizeof( CM_DELAYED_CLOSE_ENTRY ) );
  158. DbgBreakPoint();
  159. }
  160. #endif
  161. return DelayedIndex;
  162. }
  163. VOID
  164. CmpAddToDelayedClose(
  165. IN PCM_KEY_CONTROL_BLOCK kcb
  166. )
  167. /*++
  168. Routine Description:
  169. Adds a kcb to the delayed close table
  170. Arguments:
  171. kcb - the kcb in question
  172. Note:
  173. kcb lock/resource should be aquired exclusively when this function is called
  174. Return Value:
  175. NONE.
  176. --*/
  177. {
  178. ULONG DelayedIndex;
  179. PCM_DELAYED_CLOSE_ENTRY DelayedEntry;
  180. PAGED_CODE();
  181. ASSERT_KCB( kcb);
  182. ASSERT( kcb->RefCount == 0 );
  183. //
  184. // get the delayed entry and attach the kcb to it
  185. //
  186. DelayedIndex = CmpGetDelayedCloseIndex();
  187. #if defined(_WIN64)
  188. //
  189. // somehow DelayedIndex is corupted here, but it was ok prior to return from CmpGetDeleyedCloseIndex
  190. //
  191. if( DelayedIndex >= CmpDelayedCloseSize ) {
  192. DbgPrint("CmpAddToDelayedClose: Bogus index %lx; sizeof( CM_DELAYED_CLOSE_ENTRY ) = %lx\n",
  193. DelayedIndex,sizeof( CM_DELAYED_CLOSE_ENTRY ) );
  194. DbgBreakPoint();
  195. }
  196. #endif
  197. DelayedEntry = &(CmpDelayedCloseTable[DelayedIndex]);
  198. ASSERT( DelayedEntry->KeyControlBlock == NULL );
  199. DelayedEntry->KeyControlBlock = kcb;
  200. kcb->DelayedCloseIndex = DelayedIndex;
  201. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_FLOW,"[CmpAddToDelayedClose] : Adding kcb = %p to DelayedCloseTable; index = %lu\n",
  202. kcb,DelayedIndex));
  203. //
  204. // move the entry on top of the LRU list
  205. //
  206. CmpRemoveEntryList(&(DelayedEntry->DelayedLRUList));
  207. InsertHeadList(
  208. &CmpDelayedLRUListHead,
  209. &(DelayedEntry->DelayedLRUList)
  210. );
  211. }