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.

328 lines
8.4 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. // If not on delayed close, don't try to remove
  87. if (i == CmpDelayedCloseSize) {
  88. return;
  89. }
  90. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_FLOW,"[CmpRemoveFromDelayedClose] : Removing kcb = %p from DelayedCloseTable; index = %lu\n",kcb,(ULONG)i));
  91. //
  92. // at this index should be the this kcb and the index should not be bigger
  93. // than the size of the table
  94. //
  95. ASSERT(CmpDelayedCloseTable[i].KeyControlBlock == kcb);
  96. ASSERT( i < CmpDelayedCloseSize );
  97. //
  98. // nobody should hold references on this particular kcb
  99. //
  100. ASSERT_KCB_LOCK_OWNED_EXCLUSIVE();
  101. //
  102. // mark the entry as available and add it to the end of the LRU list
  103. //
  104. CmpDelayedCloseTable[i].KeyControlBlock = NULL;
  105. CmpRemoveEntryList(&(CmpDelayedCloseTable[i].DelayedLRUList));
  106. InsertTailList(
  107. &CmpDelayedLRUListHead,
  108. &(CmpDelayedCloseTable[i].DelayedLRUList)
  109. );
  110. kcb->DelayedCloseIndex = CmpDelayedCloseSize;
  111. }
  112. ULONG
  113. CmpGetDelayedCloseIndex( )
  114. /*++
  115. Routine Description:
  116. Finds a free entry in the delayed close table and returns it.
  117. If the table is full, the kcb in the last entry (LRU-wise) is
  118. kicked out of the table and its entry is reused.
  119. Arguments:
  120. Note:
  121. kcb lock/resource should be aquired exclusively when this function is called
  122. Return Value:
  123. NONE.
  124. --*/
  125. {
  126. ULONG DelayedIndex;
  127. PCM_DELAYED_CLOSE_ENTRY DelayedEntry;
  128. PAGED_CODE();
  129. //
  130. // get the last entry in the Delayed LRU list
  131. //
  132. DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)CmpDelayedLRUListHead.Blink;
  133. Retry:
  134. DelayedEntry = CONTAINING_RECORD( DelayedEntry,
  135. CM_DELAYED_CLOSE_ENTRY,
  136. DelayedLRUList);
  137. if( DelayedEntry->KeyControlBlock != NULL ) {
  138. //
  139. // entry is not available; kick the kcb out of cache
  140. //
  141. ASSERT_KCB(DelayedEntry->KeyControlBlock);
  142. //ASSERT( DelayedEntry->KeyControlBlock->RefCount == 0 );
  143. //
  144. // lock should be held here !!!
  145. //
  146. if(DelayedEntry->KeyControlBlock->RefCount == 0) {
  147. CmpCleanUpKcbCacheWithLock(DelayedEntry->KeyControlBlock);
  148. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_FLOW,"[CmpGetDelayedCloseIndex] : no index free; kicking kcb = %p index = %lu out of DelayedCloseTable\n",
  149. DelayedEntry->KeyControlBlock,(ULONG)(((PUCHAR)DelayedEntry - (PUCHAR)CmpDelayedCloseTable) / sizeof( CM_DELAYED_CLOSE_ENTRY ))));
  150. } else {
  151. //
  152. // somebody else is partying on this kcb; go to the next entry (in reverse order).
  153. //
  154. if( DelayedEntry->DelayedLRUList.Blink == CmpDelayedLRUListHead.Flink ) {
  155. //
  156. // we cannot go up anymore; we need to yank this one.
  157. //
  158. DelayedEntry->KeyControlBlock->DelayedCloseIndex = CmpDelayedCloseSize;
  159. } else {
  160. //
  161. // go back one spot and retry
  162. //
  163. DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(DelayedEntry->DelayedLRUList.Blink);
  164. goto Retry;
  165. }
  166. }
  167. DelayedEntry->KeyControlBlock = NULL;
  168. }
  169. DelayedIndex = (ULONG) (((PUCHAR)DelayedEntry - (PUCHAR)CmpDelayedCloseTable) / sizeof( CM_DELAYED_CLOSE_ENTRY ));
  170. //
  171. // sanity check
  172. //
  173. ASSERT( DelayedIndex < CmpDelayedCloseSize );
  174. #if defined(_WIN64)
  175. //
  176. // somehow DelayedIndex is ok here but it gets corupted upon return from this api
  177. //
  178. if( DelayedIndex >= CmpDelayedCloseSize ) {
  179. DbgPrint("CmpGetDelayedCloseIndex: Bogus index %lx; DelayedEntry = %p; sizeof( CM_DELAYED_CLOSE_ENTRY ) = %lx\n",
  180. DelayedIndex,DelayedEntry,sizeof( CM_DELAYED_CLOSE_ENTRY ) );
  181. DbgBreakPoint();
  182. }
  183. #endif
  184. return DelayedIndex;
  185. }
  186. VOID
  187. CmpAddToDelayedClose(
  188. IN PCM_KEY_CONTROL_BLOCK kcb
  189. )
  190. /*++
  191. Routine Description:
  192. Adds a kcb to the delayed close table
  193. Arguments:
  194. kcb - the kcb in question
  195. Note:
  196. kcb lock/resource should be aquired exclusively when this function is called
  197. Return Value:
  198. NONE.
  199. --*/
  200. {
  201. ULONG DelayedIndex;
  202. PCM_DELAYED_CLOSE_ENTRY DelayedEntry;
  203. PAGED_CODE();
  204. ASSERT_KCB( kcb);
  205. ASSERT( kcb->RefCount == 0 );
  206. ASSERT_KCB_LOCK_OWNED_EXCLUSIVE();
  207. // Already on delayed close, don't try to put on again
  208. if (kcb->DelayedCloseIndex != CmpDelayedCloseSize) {
  209. return;
  210. }
  211. //
  212. // get the delayed entry and attach the kcb to it
  213. //
  214. DelayedIndex = CmpGetDelayedCloseIndex();
  215. #if defined(_WIN64)
  216. //
  217. // somehow DelayedIndex is corupted here, but it was ok prior to return from CmpGetDeleyedCloseIndex
  218. //
  219. if( DelayedIndex >= CmpDelayedCloseSize ) {
  220. DbgPrint("CmpAddToDelayedClose: Bogus index %lx; sizeof( CM_DELAYED_CLOSE_ENTRY ) = %lx\n",
  221. DelayedIndex,sizeof( CM_DELAYED_CLOSE_ENTRY ) );
  222. DbgBreakPoint();
  223. }
  224. #endif
  225. DelayedEntry = &(CmpDelayedCloseTable[DelayedIndex]);
  226. ASSERT( DelayedEntry->KeyControlBlock == NULL );
  227. DelayedEntry->KeyControlBlock = kcb;
  228. kcb->DelayedCloseIndex = DelayedIndex;
  229. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_FLOW,"[CmpAddToDelayedClose] : Adding kcb = %p to DelayedCloseTable; index = %lu\n",
  230. kcb,DelayedIndex));
  231. //
  232. // move the entry on top of the LRU list
  233. //
  234. CmpRemoveEntryList(&(DelayedEntry->DelayedLRUList));
  235. InsertHeadList(
  236. &CmpDelayedLRUListHead,
  237. &(DelayedEntry->DelayedLRUList)
  238. );
  239. }