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.

383 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. rxdebug.c
  5. Abstract:
  6. This module implements functions supporting read/write tracking for help in
  7. tracking down data corruption problems.
  8. Currently it is only implemented for files that are created of drive
  9. letter X:. For each file that is created there are three additional bitmaps
  10. are created. The first one marks the ranges of fileoffset, length for which
  11. write were submitted to rdbss. The second bitmap marks the ranges of the
  12. file for which write requests were passed onto the mini redirector
  13. (initiation of Lowio). The third bitmap marks the ranges for which the I/O
  14. was successfully completed.
  15. Each bit map kas 8k bits long enough to accomodate files upto ( 8K * PAGE_SIZE)
  16. bytes. The FCB contains a pointer to this data structure. The data structure
  17. is independent of FCB's and a new one is created everytime a new FCB instance
  18. is created.
  19. Author:
  20. Balan Sethu Raman --
  21. --*/
  22. #include "precomp.h"
  23. #pragma hdrstop
  24. #include <ntddnfs2.h>
  25. #include <ntddmup.h>
  26. #ifdef RDBSSLOG
  27. #include <stdio.h>
  28. #endif
  29. VOID
  30. RxInitializeDebugSupport()
  31. {
  32. #ifdef RX_WJ_DBG_SUPPORT
  33. RxdInitializeWriteJournalSupport();
  34. #endif
  35. }
  36. VOID
  37. RxTearDownDebugSupport()
  38. {
  39. #ifdef RX_WJ_DBG_SUPPORT
  40. RxdTearDownWriteJournalSupport();
  41. #endif
  42. }
  43. #ifdef RX_WJ_DBG_SUPPORT
  44. #ifdef ALLOC_PRAGMA
  45. #pragma alloc_text(PAGE, RxdInitializeWriteJournalSupport)
  46. #pragma alloc_text(PAGE, RxdTearDownWriteJournalSupport)
  47. #pragma alloc_text(PAGE, RxdInitializeFcbWriteJournalDebugSupport)
  48. #pragma alloc_text(PAGE, RxdTearDownFcbWriteJournalDebugSupport)
  49. #pragma alloc_text(PAGE, RxdUpdateJournalOnWriteInitiation)
  50. #pragma alloc_text(PAGE, RxdUpdateJournalOnLowIoWriteInitiation)
  51. #pragma alloc_text(PAGE, RxdUpdateJournalOnLowIoWriteCompletion)
  52. #pragma alloc_text(PAGE, RxdFindWriteJournal)
  53. #pragma alloc_text(PAGE, UpdateBitmap)
  54. #endif
  55. LIST_ENTRY OldWriteJournals;
  56. LIST_ENTRY ActiveWriteJournals;
  57. ERESOURCE WriteJournalsResource;
  58. extern VOID
  59. UpdateBitmap(
  60. PBYTE pBitmap,
  61. LARGE_INTEGER Offset,
  62. ULONG Length);
  63. extern PFCB_WRITE_JOURNAL
  64. RxdFindWriteJournal(
  65. PFCB pFcb);
  66. VOID
  67. RxdInitializeWriteJournalSupport()
  68. {
  69. PAGED_CODE();
  70. InitializeListHead(&ActiveWriteJournals);
  71. InitializeListHead(&OldWriteJournals);
  72. ExInitializeResource(&WriteJournalsResource);
  73. }
  74. VOID
  75. RxdTearDownWriteJournalSupport()
  76. {
  77. PLIST_ENTRY pJournalEntry;
  78. PFCB_WRITE_JOURNAL pJournal;
  79. PAGED_CODE();
  80. ExAcquireResourceExclusive(&WriteJournalsResource,TRUE);
  81. while (ActiveWriteJournals.Flink != &ActiveWriteJournals) {
  82. pJournalEntry = RemoveHeadList(&ActiveWriteJournals);
  83. pJournal = (PFCB_WRITE_JOURNAL)
  84. CONTAINING_RECORD(
  85. pJournalEntry,
  86. FCB_WRITE_JOURNAL,
  87. JournalsList);
  88. RxFreePool(pJournal);
  89. }
  90. while (OldWriteJournals.Flink != &OldWriteJournals) {
  91. pJournalEntry = RemoveHeadList(&OldWriteJournals);
  92. pJournal = (PFCB_WRITE_JOURNAL)
  93. CONTAINING_RECORD(
  94. pJournalEntry,
  95. FCB_WRITE_JOURNAL,
  96. JournalsList);
  97. RxFreePool(pJournal);
  98. }
  99. ExReleaseResource(&WriteJournalsResource);
  100. ExDeleteResource(&WriteJournalsResource);
  101. }
  102. VOID
  103. RxdInitializeFcbWriteJournalDebugSupport(
  104. PFCB pFcb)
  105. {
  106. PFCB_WRITE_JOURNAL pJournal;
  107. PAGED_CODE();
  108. if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
  109. pJournal = RxAllocatePoolWithTag(
  110. PagedPool | POOL_COLD_ALLOCATION,
  111. sizeof(FCB_WRITE_JOURNAL),
  112. RX_MISC_POOLTAG);
  113. if (pJournal != NULL) {
  114. ULONG PathLength;
  115. RtlZeroMemory(
  116. pJournal,
  117. sizeof(FCB_WRITE_JOURNAL));
  118. pJournal->pName = &pJournal->Path[0];
  119. if (pFcb->AlreadyPrefixedName.Length > (MAX_PATH * sizeof(WCHAR))) {
  120. PathLength = MAX_PATH * sizeof(WCHAR);
  121. } else {
  122. PathLength = pFcb->AlreadyPrefixedName.Length;
  123. }
  124. RtlCopyMemory(
  125. pJournal->pName,
  126. pFcb->AlreadyPrefixedName.Buffer,
  127. PathLength);
  128. pJournal->pFcb = pFcb;
  129. pJournal->pWriteInitiationBitmap = pJournal->WriteInitiationBitmap;
  130. pJournal->pLowIoWriteInitiationBitmap = pJournal->LowIoWriteInitiationBitmap;
  131. pJournal->pLowIoWriteCompletionBitmap = pJournal->LowIoWriteCompletionBitmap;
  132. ExAcquireResourceExclusive(&WriteJournalsResource,TRUE);
  133. InsertHeadList(
  134. &ActiveWriteJournals,
  135. &pJournal->JournalsList);
  136. ExReleaseResource(&WriteJournalsResource);
  137. }
  138. }
  139. }
  140. VOID
  141. RxdTearDownFcbWriteJournalDebugSupport(
  142. PFCB pFcb)
  143. {
  144. PAGED_CODE();
  145. if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
  146. PFCB_WRITE_JOURNAL pJournal;
  147. PLIST_ENTRY pJournalEntry;
  148. ExAcquireResourceExclusive(&WriteJournalsResource,TRUE);
  149. pJournal = RxdFindWriteJournal(pFcb);
  150. if (pJournal != NULL) {
  151. RemoveEntryList(&pJournal->JournalsList);
  152. // InsertHeadList(
  153. // &OldWriteJournals,
  154. // &pJournal->JournalsList);
  155. RxFreePool(pJournal);
  156. }
  157. ExReleaseResource(&WriteJournalsResource);
  158. }
  159. }
  160. VOID
  161. RxdUpdateJournalOnWriteInitiation(
  162. IN OUT PFCB pFcb,
  163. IN LARGE_INTEGER Offset,
  164. IN ULONG Length)
  165. {
  166. PAGED_CODE();
  167. if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
  168. PFCB_WRITE_JOURNAL pJournal;
  169. PLIST_ENTRY pJournalEntry;
  170. ExAcquireResourceExclusive(&WriteJournalsResource, TRUE);
  171. pJournal = RxdFindWriteJournal(pFcb);
  172. if (pJournal != NULL) {
  173. UpdateBitmap(
  174. pJournal->WriteInitiationBitmap,
  175. Offset,
  176. Length);
  177. pJournal->WritesInitiated++;
  178. }
  179. ExReleaseResource(&WriteJournalsResource);
  180. }
  181. }
  182. VOID
  183. RxdUpdateJournalOnLowIoWriteInitiation(
  184. IN OUT PFCB pFcb,
  185. IN LARGE_INTEGER Offset,
  186. IN ULONG Length)
  187. {
  188. PAGED_CODE();
  189. if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
  190. PFCB_WRITE_JOURNAL pJournal;
  191. PLIST_ENTRY pJournalEntry;
  192. ExAcquireResourceExclusive(&WriteJournalsResource, TRUE);
  193. pJournal = RxdFindWriteJournal(pFcb);
  194. if (pJournal != NULL) {
  195. UpdateBitmap(
  196. pJournal->LowIoWriteInitiationBitmap,
  197. Offset,
  198. Length);
  199. pJournal->LowIoWritesInitiated++;
  200. }
  201. ExReleaseResource(&WriteJournalsResource);
  202. }
  203. }
  204. VOID
  205. RxdUpdateJournalOnLowIoWriteCompletion(
  206. IN OUT PFCB pFcb,
  207. IN LARGE_INTEGER Offset,
  208. IN ULONG Length)
  209. {
  210. PAGED_CODE();
  211. if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
  212. PFCB_WRITE_JOURNAL pJournal;
  213. PLIST_ENTRY pJournalEntry;
  214. ExAcquireResourceExclusive(&WriteJournalsResource, TRUE);
  215. pJournal = RxdFindWriteJournal(pFcb);
  216. if (pJournal != NULL) {
  217. UpdateBitmap(
  218. pJournal->LowIoWriteCompletionBitmap,
  219. Offset,
  220. Length);
  221. pJournal->LowIoWritesCompleted++;
  222. }
  223. ExReleaseResource(&WriteJournalsResource);
  224. }
  225. }
  226. PFCB_WRITE_JOURNAL
  227. RxdFindWriteJournal(
  228. PFCB pFcb)
  229. {
  230. PFCB_WRITE_JOURNAL pJournal;
  231. PLIST_ENTRY pJournalEntry;
  232. PAGED_CODE();
  233. pJournalEntry = ActiveWriteJournals.Flink;
  234. while (pJournalEntry != &ActiveWriteJournals) {
  235. pJournal = (PFCB_WRITE_JOURNAL)
  236. CONTAINING_RECORD(
  237. pJournalEntry,
  238. FCB_WRITE_JOURNAL,
  239. JournalsList);
  240. if (pJournal->pFcb == pFcb) {
  241. break;
  242. } else {
  243. pJournalEntry = pJournalEntry->Flink;
  244. }
  245. }
  246. if (pJournalEntry == &ActiveWriteJournals) {
  247. pJournal = NULL;
  248. }
  249. return pJournal;
  250. }
  251. CHAR PageMask[8] = { 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
  252. VOID
  253. UpdateBitmap(
  254. PBYTE pBitmap,
  255. LARGE_INTEGER Offset,
  256. ULONG Length)
  257. {
  258. LONG OffsetIn4kChunks;
  259. LONG OffsetIn32kChunks;
  260. LONG NumberOf4kChunks,Starting4kChunk;
  261. PAGED_CODE();
  262. // Each byte in the bit map represents a 32k region since each bit represents
  263. // a 4k region in the file.
  264. // we ignore the offset's high part for now because the bitmap's max size is
  265. // far less than what can be accomodated in the low part.
  266. OffsetIn4kChunks = Offset.LowPart / (0x1000);
  267. OffsetIn32kChunks = Offset.LowPart / (0x8000);
  268. Starting4kChunk = ((Offset.LowPart & ~0xfff) - (Offset.LowPart & ~0x7fff)) / 0x1000;
  269. NumberOf4kChunks = Length / 0x1000;
  270. if (NumberOf4kChunks > (8 - Starting4kChunk)) {
  271. pBitmap[OffsetIn32kChunks++] |= (PageMask[7] & ~PageMask[Starting4kChunk]);
  272. Length -= (8 - Starting4kChunk) * 0x1000;
  273. }
  274. if (Length > 0x8000) {
  275. while (Length > (0x8000)) {
  276. pBitmap[OffsetIn32kChunks++] = PageMask[7];
  277. Length -= (0x8000);
  278. }
  279. Starting4kChunk = 0;
  280. }
  281. // The final chunk is less then 32k. The byte in the bitmao needs to be
  282. // updated accordingly.
  283. if (Length > 0) {
  284. NumberOf4kChunks = Length / (0x1000);
  285. pBitmap[OffsetIn32kChunks] |= PageMask[NumberOf4kChunks + Starting4kChunk];
  286. }
  287. }
  288. #endif
  289.