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.

210 lines
6.9 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. namcache.h
  5. Abstract:
  6. The NAME_CACHE structure is used to remember the name strings of recent
  7. operations performed at the server so the client can suppress redundant
  8. requests. For example if an open has recently failed with file not found and
  9. the client app tries it again with an upcased string then we can fail it
  10. immediately with STATUS_OBJECT_NAME_NOT_FOUND without hitting the server. In
  11. general the algorithm is to put a time window and SMB operation count limit on
  12. the NAME_CACHE entry. The time window is usually 2 seconds so if NAME_CACHE
  13. entry is more than 2 seconds old the match will fail and the request will go to
  14. the server. If the request fails again at the server the NAME_CACHE is updated
  15. with another 2 second window. If the SMB operation count doesn't match then one
  16. or more SMBs have been sent to the server which could make this NAME_CACHE entry
  17. invalid. So again this operation will get sent to the server.
  18. A NAME_CACHE struct has a mini-rdr portion and an RDBSS portion. The mini-rdr
  19. portion has a context field (see below), an NTSTATUS field for the result of a
  20. prior server operation on this name entry and a context extension pointer for
  21. some additional mini-rdr specific storage that can be co-allocated with the
  22. NAME_CACHE structure. See RxNameCacheInitialize().
  23. The SMB operation count is an example of mini-rdr specific state which could be
  24. saved in the context field of MRX_NAME_CACHE. When the wrapper routine
  25. RxNameCacheCheckEntry() is called it will perform an equality check between the
  26. context field and a supplied parameter as part of finding a match in the name
  27. cache. When a NAME_CACHE entry is created or updated it is the mini-rdr's job
  28. to supply an appropriate value for this field.
  29. The RDBSS portion of the NAME_CACHE struct contains the name (in a UNICODE
  30. STRING) and the expiration time of the entry. The MaximumEntries field is used
  31. to limit the number of NAME_CACHE entries created in case a poorly behaved
  32. program were to generate a large number of opens with bad file names and so
  33. consume large quanities of pool.
  34. The NAME_CACHE_CONTROL struct is used to manage a given name cache. It has
  35. a free list, an active list and a lock used to synchronize updates.
  36. Currently there are name caches for:
  37. 1. OBJECT_NAME_NOT_FOUND - 2 second window, any SMB op sent to the
  38. server will invalidate it. This is because you could have the case
  39. where the client app has a file (foo) open which an app on the server could
  40. use to signal the creation of a file (bar) on the server. When the client
  41. reads file foo and learns that file bar has been created on the
  42. server then a hit in the name cache which matches bar can't return an
  43. error. So this optimization only handles the case of successive file
  44. opens on the same file which does not yet exist. Happens in WORD.
  45. Author:
  46. David Orbits [davidor] 9-Sep-1996
  47. Revision History:
  48. --*/
  49. #ifndef _NAME_CACHE_DEFINED_
  50. #define _NAME_CACHE_DEFINED_
  51. #ifdef __cplusplus
  52. typedef struct _MRX_NAME_CACHE_ : public MRX_NORMAL_NODE_HEADER {
  53. #else // !__cplusplus
  54. typedef struct _MRX_NAME_CACHE_ {
  55. MRX_NORMAL_NODE_HEADER;
  56. #endif // __cplusplus
  57. // !!!! changes above this require realignment with fcb.h
  58. ULONG Context; // Operation Count snapshot when entry made
  59. PVOID ContextExtension; // Pointer to mini-rdr extension area
  60. NTSTATUS PriorStatus; // Saved Status from last attempt at operation
  61. } MRX_NAME_CACHE, *PMRX_NAME_CACHE;
  62. #ifdef __cplusplus
  63. typedef struct _NAME_CACHE : public MRX_NAME_CACHE {
  64. // I didn't find any use of the spacer in the union below,
  65. // and the MRX_NAME_CACHE is by definition larger than
  66. // MRX_NORMAL_NODE_HEADER, so I didn't worry about the union
  67. #else // !__cplusplus
  68. typedef struct _NAME_CACHE {
  69. //
  70. // The portion of NAME_CACHE visible to mini redirectors.
  71. //
  72. union {
  73. MRX_NAME_CACHE;
  74. struct {
  75. MRX_NORMAL_NODE_HEADER spacer;
  76. };
  77. };
  78. #endif // __cplusplus
  79. //
  80. // The portion of NAME_CACHE visible to RDBSS.
  81. //
  82. LARGE_INTEGER ExpireTime; // Time when entry expires
  83. LIST_ENTRY Link; // Entry on free or active list
  84. UNICODE_STRING Name; // Cached name
  85. ULONG HashValue; // Hash value of name
  86. BOOLEAN CaseInsensitive; // Controls name string compare
  87. } NAME_CACHE, *PNAME_CACHE;
  88. typedef struct _NAME_CACHE_CONTROL_ {
  89. FAST_MUTEX NameCacheLock; // Lock to synchronize access to the list
  90. LIST_ENTRY ActiveList; // List of active name cache entries
  91. LIST_ENTRY FreeList; // Free list of NAME_CACHE structs
  92. ULONG EntryCount; // Current number of NAME_CACHE entries allocated
  93. ULONG MaximumEntries; // Max number of entries we will allocate
  94. ULONG MRxNameCacheSize; // Size of Mini-rdr storage area in entry
  95. //
  96. // Stats
  97. //
  98. ULONG NumberActivates; // Number of times cache was updated
  99. ULONG NumberChecks; // Number of times cache was checked
  100. ULONG NumberNameHits; // Number of times a valid match was returned
  101. ULONG NumberNetOpsSaved; // Number of times mini-rdr saved a net op
  102. ULONG Spare[4];
  103. } NAME_CACHE_CONTROL, *PNAME_CACHE_CONTROL;
  104. //
  105. // Return status for RxNameCacheCheckEntry()
  106. //
  107. typedef enum _RX_NC_CHECK_STATUS {
  108. RX_NC_SUCCESS = 0,
  109. RX_NC_TIME_EXPIRED,
  110. RX_NC_MRXCTX_FAIL
  111. } RX_NC_CHECK_STATUS;
  112. //
  113. // Mini-rdr function to count the number of times the cached state avoided
  114. // a trip to the server.
  115. //
  116. #define RxNameCacheOpSaved(_NCC) (_NCC)->NumberNetOpsSaved += 1
  117. VOID
  118. RxNameCacheInitialize(
  119. IN PNAME_CACHE_CONTROL NameCacheCtl,
  120. IN ULONG MRxNameCacheSize,
  121. IN ULONG MaximumEntries
  122. );
  123. PNAME_CACHE
  124. RxNameCacheCreateEntry (
  125. IN PNAME_CACHE_CONTROL NameCacheCtl,
  126. IN PUNICODE_STRING Name,
  127. IN BOOLEAN CaseInsensitive
  128. );
  129. PNAME_CACHE
  130. RxNameCacheFetchEntry (
  131. IN PNAME_CACHE_CONTROL NameCacheCtl,
  132. IN PUNICODE_STRING Name
  133. );
  134. RX_NC_CHECK_STATUS
  135. RxNameCacheCheckEntry (
  136. IN PNAME_CACHE NameCache,
  137. IN ULONG MRxContext
  138. );
  139. VOID
  140. RxNameCacheActivateEntry (
  141. IN PNAME_CACHE_CONTROL NameCacheCtl,
  142. IN PNAME_CACHE NameCache,
  143. IN ULONG LifeTime,
  144. IN ULONG MRxContext
  145. );
  146. VOID
  147. RxNameCacheExpireEntry (
  148. IN PNAME_CACHE_CONTROL NameCacheCtl,
  149. IN PNAME_CACHE NameCache
  150. );
  151. VOID
  152. RxNameCacheExpireEntryWithShortName (
  153. IN PNAME_CACHE_CONTROL NameCacheCtl,
  154. IN PUNICODE_STRING Name
  155. );
  156. VOID
  157. RxNameCacheFreeEntry (
  158. IN PNAME_CACHE_CONTROL NameCacheCtl,
  159. IN PNAME_CACHE NameCache
  160. );
  161. VOID
  162. RxNameCacheFinalize (
  163. IN PNAME_CACHE_CONTROL NameCacheCtl
  164. );
  165. #endif // _NAME_CACHE_DEFINED_
  166.