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.

251 lines
7.5 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation.
  4. //
  5. // File: fcbsup.c
  6. //
  7. // Contents: Support routines for associating DFS_FCB records with
  8. // file objects, and looking them up again.
  9. //
  10. // Functions: DfsInitFcbs - Initialize the hash table for DFS_FCB lookup
  11. // DfsLookupFcb - Lookup an DFS_FCB associated with a file object
  12. // DfsAttachFcb - Associate an DFS_FCB with a file object
  13. // DfsDetachFcb - Remove the Association between an DFS_FCB and
  14. // a file object
  15. //
  16. // History: 20 Feb 1993 Alanw Created
  17. //
  18. // TODO: the FcbHashTable and Fcbs are currently allocated
  19. // out of non-paged pool; these should probably be
  20. // paged. This would require using some other
  21. // synchronization method on the hash bucket chains
  22. //
  23. //--------------------------------------------------------------------------
  24. #include "dfsprocs.h"
  25. #include "fcbsup.h"
  26. #define Dbg 0x1000
  27. #define HASH(k,m) (((ULONG)((ULONG_PTR)(k))>>12^(ULONG)((ULONG_PTR)(k))>>2) & m)
  28. #define DEFAULT_HASH_SIZE 16 // default size of hash table
  29. NTSTATUS
  30. DfsInitFcbHashTable(
  31. IN ULONG cHash,
  32. OUT PFCB_HASH_TABLE *ppHashTable);
  33. #ifdef ALLOC_PRAGMA
  34. #pragma alloc_text(INIT, DfsInitFcbs)
  35. #pragma alloc_text(INIT, DfsInitFcbHashTable)
  36. #pragma alloc_text(PAGE, DfsUninitFcbs)
  37. //
  38. // The following routines are not pageable because they acquire spinlocks.
  39. //
  40. // DfsLookupFcb
  41. // DfsAttachFcb
  42. // DfsDetachFcb
  43. //
  44. #endif
  45. //+-------------------------------------------------------------------------
  46. //
  47. // Function: DfsInitFcbs - Initialize the DFS_FCB lookup hash table
  48. //
  49. // Synopsis: This function initializes data structures which are
  50. // used for looking up an DFS_FCB associated with some open
  51. // file object.
  52. //
  53. // Arguments: [cHash] -- Size of the hash table to be allocated. Must be
  54. // a power of two. If zero, a default size is used.
  55. //
  56. // Returns: NTSTATUS -- STATUS_SUCCESS, unless memory allocation
  57. // fails.
  58. //
  59. // Note: The hash buckets are initialized to zero, then later
  60. // initialized to a list head when used. This is a debugging
  61. // aid to determine if some hash buckets are never used.
  62. //
  63. //--------------------------------------------------------------------------
  64. NTSTATUS
  65. DfsInitFcbHashTable(
  66. IN ULONG cHash,
  67. OUT PFCB_HASH_TABLE *ppHashTable)
  68. {
  69. PFCB_HASH_TABLE pHashTable;
  70. ULONG cbHashTable;
  71. if (cHash == 0) {
  72. cHash = DEFAULT_HASH_SIZE;
  73. }
  74. ASSERT ((cHash & (cHash-1)) == 0); // Assure cHash is a power of two
  75. cbHashTable = sizeof (FCB_HASH_TABLE) + (cHash-1)*sizeof (LIST_ENTRY);
  76. pHashTable = ExAllocatePoolWithTag(NonPagedPool, cbHashTable, ' puM');
  77. if (pHashTable == NULL) {
  78. return STATUS_NO_MEMORY;
  79. }
  80. pHashTable->NodeTypeCode = DSFS_NTC_FCB_HASH;
  81. pHashTable->NodeByteSize = (NODE_BYTE_SIZE) cbHashTable;
  82. pHashTable->HashMask = (cHash-1);
  83. KeInitializeSpinLock( &pHashTable->HashListSpinLock );
  84. RtlZeroMemory(&pHashTable->HashBuckets[0], cHash * sizeof (LIST_ENTRY));
  85. *ppHashTable = pHashTable;
  86. return(STATUS_SUCCESS);
  87. }
  88. NTSTATUS
  89. DfsInitFcbs(
  90. IN ULONG cHash
  91. ) {
  92. NTSTATUS status;
  93. status = DfsInitFcbHashTable( cHash, &DfsData.FcbHashTable );
  94. return status;
  95. }
  96. VOID
  97. DfsUninitFcbs(
  98. VOID)
  99. {
  100. ExFreePool (DfsData.FcbHashTable);
  101. }
  102. //+-------------------------------------------------------------------------
  103. //
  104. // Function: DfsLookupFcb - Lookup an DFS_FCB in the hash table
  105. //
  106. // Synopsis: This function will lookup the DFS_FCB associated with
  107. // a particular file object.
  108. //
  109. // Arguments: [pFile] -- Pointer to file object for which the DFS_FCB is
  110. // being looked up.
  111. //
  112. // Returns: PVOID -- pointer to the DFS_FCB found, or NULL if none
  113. //
  114. // Algorithm: Knuth would call it hashing with conflict resoulution
  115. // by chaining.
  116. //
  117. // History: 20 Feb 1993 Alanw Created
  118. //
  119. //--------------------------------------------------------------------------
  120. PDFS_FCB
  121. DfsLookupFcb(
  122. IN PFILE_OBJECT pFile
  123. ) {
  124. PLIST_ENTRY pListHead, pLink;
  125. PDFS_FCB pFCB;
  126. KIRQL SavedIrql;
  127. PFCB_HASH_TABLE pHashTable = DfsData.FcbHashTable;
  128. KeAcquireSpinLock( &pHashTable->HashListSpinLock, &SavedIrql );
  129. pListHead = &pHashTable->HashBuckets[ HASH(pFile, pHashTable->HashMask) ];
  130. if ((pListHead->Flink == NULL) || // list not initialized
  131. (pListHead->Flink == pListHead)) { // list empty
  132. KeReleaseSpinLock( &pHashTable->HashListSpinLock, SavedIrql );
  133. return NULL;
  134. }
  135. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
  136. pFCB = CONTAINING_RECORD(pLink, DFS_FCB, HashChain);
  137. if (pFCB->FileObject == pFile) {
  138. KeReleaseSpinLock( &pHashTable->HashListSpinLock, SavedIrql );
  139. return pFCB;
  140. }
  141. }
  142. KeReleaseSpinLock( &pHashTable->HashListSpinLock, SavedIrql );
  143. return NULL;
  144. }
  145. //+-------------------------------------------------------------------------
  146. //
  147. // Function: DfsAttachFcb - Inserts an DFS_FCB into the hash table
  148. //
  149. // Synopsis: This function associates an DFS_FCB to a file object. This
  150. // involves inserting it into the hash table.
  151. //
  152. // Arguments: [pFCB] -- Pointer to the DFS_FCB to be inserted.
  153. // [pFileObj] -- Pointer to the corresponding file object, used
  154. // as the hash key.
  155. //
  156. // Returns: -nothing-
  157. //
  158. //--------------------------------------------------------------------------
  159. VOID
  160. DfsAttachFcb(
  161. IN PFILE_OBJECT pFileObj,
  162. IN PDFS_FCB pFCB
  163. ) {
  164. PFCB_HASH_TABLE pHashTable = (PFCB_HASH_TABLE) DfsData.FcbHashTable;
  165. PLIST_ENTRY pListHead;
  166. KIRQL SavedIrql;
  167. KeAcquireSpinLock( &pHashTable->HashListSpinLock, &SavedIrql );
  168. pListHead = &pHashTable->HashBuckets[ HASH(pFileObj, pHashTable->HashMask) ];
  169. if (pListHead->Flink == NULL) {
  170. InitializeListHead(pListHead);
  171. }
  172. InsertHeadList(pListHead, &pFCB->HashChain);
  173. KeReleaseSpinLock( &pHashTable->HashListSpinLock, SavedIrql );
  174. DfsDbgTrace(0, Dbg, "Attached Fcb %08lx ", pFCB);
  175. DfsDbgTrace(0, Dbg, "For Fileobject %08lx ", pFileObj);
  176. }
  177. //+-------------------------------------------------------------------------
  178. //
  179. // Function: DfsDetachFcb - Detach an DFS_FCB from the lookup hash table
  180. //
  181. // Synopsis: This function detaches an DFS_FCB from the hash table. This
  182. // involves just deleting it from the hash bucket chain.
  183. //
  184. // Arguments: [pFCB] -- Pointer to the DFS_FCB to be detached.
  185. // [pFileObj] -- Pointer to the corresponding file object, used
  186. // for debugging only.
  187. //
  188. // Returns: -nothing-
  189. //
  190. //--------------------------------------------------------------------------
  191. VOID
  192. DfsDetachFcb(
  193. IN PFILE_OBJECT pFileObj,
  194. IN PDFS_FCB pFCB
  195. ) {
  196. PFCB_HASH_TABLE pHashTable = (PFCB_HASH_TABLE) DfsData.FcbHashTable;
  197. KIRQL SavedIrql;
  198. ASSERT(pFCB->FileObject == pFileObj);
  199. ASSERT(DfsLookupFcb(pFCB->FileObject) == pFCB);
  200. KeAcquireSpinLock( &pHashTable->HashListSpinLock, &SavedIrql );
  201. RemoveEntryList(&pFCB->HashChain);
  202. pFCB->FileObject = NULL;
  203. KeReleaseSpinLock( &pHashTable->HashListSpinLock, SavedIrql );
  204. DfsDbgTrace(0, Dbg, "Detached Fcb %08lx ", pFCB);
  205. DfsDbgTrace(0, Dbg, "For Fileobject %08lx ", pFileObj);
  206. }