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.

362 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. vfpacket.c
  5. Abstract:
  6. This module contains functions used to manage the verifier packet data
  7. that tracks IRPs.
  8. Author:
  9. Adrian J. Oney (adriao) 20-Apr-1998
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. AdriaO 05/02/2000 - Seperated out from ntos\io\hashirp.c
  14. --*/
  15. #include "vfdef.h"
  16. #include "vfipacket.h"
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGEVRFY, VfPacketCreateAndLock)
  19. #pragma alloc_text(PAGEVRFY, VfPacketFindAndLock)
  20. #pragma alloc_text(PAGEVRFY, VfPacketAcquireLock)
  21. #pragma alloc_text(PAGEVRFY, VfPacketReleaseLock)
  22. #pragma alloc_text(PAGEVRFY, VfPacketReference)
  23. #pragma alloc_text(PAGEVRFY, VfPacketDereference)
  24. #pragma alloc_text(PAGEVRFY, VfpPacketFree)
  25. #pragma alloc_text(PAGEVRFY, VfpPacketNotificationCallback)
  26. #pragma alloc_text(PAGEVRFY, VfPacketGetCurrentSessionData)
  27. #pragma alloc_text(PAGEVRFY, VfPacketLogEntry)
  28. #endif
  29. #define POOL_TAG_TRACKING_DATA 'tprI'
  30. PIOV_REQUEST_PACKET
  31. FASTCALL
  32. VfPacketCreateAndLock(
  33. IN PIRP Irp
  34. )
  35. /*++
  36. Description:
  37. This routine creates a tracking packet for a new IRP. The IRP does not get
  38. an initial reference count however. VfPacketReleaseLock must be called to
  39. drop the lock.
  40. Arguments:
  41. Irp - Irp to begin tracking.
  42. Return Value:
  43. iovPacket block, NULL if no memory.
  44. --*/
  45. {
  46. PIOV_REQUEST_PACKET iovPacket;
  47. ULONG allocSize;
  48. BOOLEAN successfullyInserted;
  49. allocSize = sizeof(IOV_REQUEST_PACKET) + VfSettingsGetSnapshotSize();
  50. iovPacket = ExAllocatePoolWithTag(
  51. NonPagedPool,
  52. allocSize,
  53. POOL_TAG_TRACKING_DATA
  54. );
  55. if (!iovPacket) {
  56. return NULL;
  57. }
  58. //
  59. // From top to bottom, initialize the fields. Note that there is not a
  60. // "surrogateHead". If any code needs to find out the first entry in the
  61. // circularly linked list of IRPs (the first is the only non-surrogate IRP),
  62. // then HeadPacket should be used. Note that the link to the session is
  63. // stored by the headPacket, more on this later.
  64. //
  65. iovPacket->Flags = 0;
  66. InitializeListHead(&iovPacket->SessionHead);
  67. iovPacket->StackCount = Irp->StackCount;
  68. iovPacket->RealIrpCompletionRoutine = NULL;
  69. iovPacket->RealIrpControl = 0;
  70. iovPacket->RealIrpContext = NULL;
  71. iovPacket->TopStackLocation = 0;
  72. iovPacket->PriorityBoost = 0;
  73. iovPacket->LastLocation = 0;
  74. iovPacket->RefTrackingCount = 0;
  75. iovPacket->VerifierSettings = (PVERIFIER_SETTINGS_SNAPSHOT) (iovPacket+1);
  76. iovPacket->pIovSessionData = NULL;
  77. iovPacket->QuotaCharge = 0;
  78. iovPacket->QuotaProcess = NULL;
  79. iovPacket->SystemDestVA = NULL;
  80. #if DBG
  81. iovPacket->LogEntryHead = 0;
  82. iovPacket->LogEntryTail = 0;
  83. RtlZeroMemory(iovPacket->LogEntries, sizeof(IOV_LOG_ENTRY)*IRP_LOG_ENTRIES);
  84. #endif
  85. VfSettingsCreateSnapshot(iovPacket->VerifierSettings);
  86. successfullyInserted = VfIrpDatabaseEntryInsertAndLock(
  87. Irp,
  88. VfpPacketNotificationCallback,
  89. (PIOV_DATABASE_HEADER) iovPacket
  90. );
  91. return successfullyInserted ? iovPacket : NULL;
  92. }
  93. PIOV_REQUEST_PACKET
  94. FASTCALL
  95. VfPacketFindAndLock(
  96. IN PIRP Irp
  97. )
  98. /*++
  99. Description:
  100. This routine will return the tracking data for an IRP that is
  101. being tracked without a surrogate or the tracking data for with
  102. a surrogate if the surrogate IRP is what was passed in.
  103. Arguments:
  104. Irp - Irp to find.
  105. Return Value:
  106. IovPacket block, iff above conditions are satified.
  107. --*/
  108. {
  109. return (PIOV_REQUEST_PACKET) VfIrpDatabaseEntryFindAndLock(Irp);
  110. }
  111. VOID
  112. FASTCALL
  113. VfPacketAcquireLock(
  114. IN PIOV_REQUEST_PACKET IovPacket OPTIONAL
  115. )
  116. /*++
  117. Description:
  118. This routine is called by to acquire the IRPs tracking data lock.
  119. Incoming IRQL must be the same as the callers (IoCallDriver, IoCompleteRequest)
  120. We may be at DPC level when we return. Callers *must* follow up with
  121. VfPacketReleaseLock.
  122. Arguments:
  123. IovPacket - Pointer to the IRP tracking data (or NULL, in which
  124. case this routine does nothing).
  125. Return Value:
  126. None.
  127. --*/
  128. {
  129. VfIrpDatabaseEntryAcquireLock((PIOV_DATABASE_HEADER) IovPacket);
  130. }
  131. VOID
  132. FASTCALL
  133. VfPacketReleaseLock(
  134. IN PIOV_REQUEST_PACKET IovPacket
  135. )
  136. /*++
  137. Description:
  138. This routine releases the IRPs tracking data lock and adjusts the ref count
  139. as appropriate. If the reference count drops to zero, the tracking data is
  140. freed.
  141. Arguments:
  142. IovPacket - Pointer to the IRP tracking data.
  143. Return Value:
  144. None.
  145. --*/
  146. {
  147. VfIrpDatabaseEntryReleaseLock((PIOV_DATABASE_HEADER) IovPacket);
  148. }
  149. VOID
  150. FASTCALL
  151. VfPacketReference(
  152. IN PIOV_REQUEST_PACKET IovPacket,
  153. IN IOV_REFERENCE_TYPE IovRefType
  154. )
  155. {
  156. VfIrpDatabaseEntryReference((PIOV_DATABASE_HEADER) IovPacket, IovRefType);
  157. }
  158. VOID
  159. FASTCALL
  160. VfPacketDereference(
  161. IN PIOV_REQUEST_PACKET IovPacket,
  162. IN IOV_REFERENCE_TYPE IovRefType
  163. )
  164. {
  165. VfIrpDatabaseEntryDereference((PIOV_DATABASE_HEADER) IovPacket, IovRefType);
  166. }
  167. VOID
  168. FASTCALL
  169. VfpPacketFree(
  170. IN PIOV_REQUEST_PACKET IovPacket
  171. )
  172. /*++
  173. Description:
  174. This routine free's the tracking data. The tracking data should already
  175. have been removed from the table by a call to VfPacketReleaseLock with the
  176. ReferenceCount at 0.
  177. Arguments:
  178. IovPacket - Tracking data to free.
  179. Return Value:
  180. Nope.
  181. --*/
  182. {
  183. ExFreePool(IovPacket);
  184. }
  185. VOID
  186. VfpPacketNotificationCallback(
  187. IN PIOV_DATABASE_HEADER IovHeader,
  188. IN PIRP TrackedIrp OPTIONAL,
  189. IN IRP_DATABASE_EVENT Event
  190. )
  191. {
  192. switch(Event) {
  193. case IRPDBEVENT_POINTER_COUNT_ZERO:
  194. TrackedIrp->Flags &= ~IRPFLAG_EXAMINE_MASK;
  195. break;
  196. case IRPDBEVENT_REFERENCE_COUNT_ZERO:
  197. ASSERT((((PIOV_REQUEST_PACKET) IovHeader)->pIovSessionData == NULL) ||
  198. (IovHeader != IovHeader->ChainHead));
  199. VfpPacketFree((PIOV_REQUEST_PACKET) IovHeader);
  200. break;
  201. default:
  202. break;
  203. }
  204. }
  205. PIOV_SESSION_DATA
  206. FASTCALL
  207. VfPacketGetCurrentSessionData(
  208. IN PIOV_REQUEST_PACKET IovPacket
  209. )
  210. {
  211. PIOV_REQUEST_PACKET headPacket;
  212. headPacket = (PIOV_REQUEST_PACKET) IovPacket->ChainHead;
  213. ASSERT_SPINLOCK_HELD(&IovPacket->IrpLock);
  214. ASSERT_SPINLOCK_HELD(&IovPacket->HeadPacket->IrpLock);
  215. ASSERT((headPacket->pIovSessionData == NULL)||
  216. (IovPacket->Flags&TRACKFLAG_ACTIVE)) ;
  217. return headPacket->pIovSessionData;
  218. }
  219. VOID
  220. FASTCALL
  221. VfPacketLogEntry(
  222. IN PIOV_REQUEST_PACKET IovPacket,
  223. IN IOV_LOG_EVENT IovLogEvent,
  224. IN PVOID Address,
  225. IN ULONG_PTR Data
  226. )
  227. /*++
  228. Description:
  229. This routine logs an event in the IRP request packet data.
  230. Arguments:
  231. IovPacket - Tracking data to write log entry into.
  232. IovLogEvent - Log Event
  233. Address - Address to associate log with
  234. Data - A chunk of data to go with the address
  235. Return Value:
  236. Nope.
  237. --*/
  238. {
  239. #if DBG
  240. PIOV_LOG_ENTRY logEntry;
  241. ASSERT_SPINLOCK_HELD(&IovPacket->IrpLock);
  242. logEntry = IovPacket->LogEntries + IovPacket->LogEntryHead;
  243. KeQueryTickCount(&logEntry->TimeStamp);
  244. logEntry->Thread = PsGetCurrentThread();
  245. logEntry->Event = IovLogEvent;
  246. logEntry->Address = Address;
  247. logEntry->Data = Data;
  248. IovPacket->LogEntryHead = ((IovPacket->LogEntryHead + 1) % IRP_LOG_ENTRIES);
  249. if (IovPacket->LogEntryHead == IovPacket->LogEntryTail) {
  250. IovPacket->LogEntryTail = ((IovPacket->LogEntryTail + 1) % IRP_LOG_ENTRIES);
  251. }
  252. #else
  253. UNREFERENCED_PARAMETER(IovPacket);
  254. UNREFERENCED_PARAMETER(IovLogEvent);
  255. UNREFERENCED_PARAMETER(Address);
  256. UNREFERENCED_PARAMETER(Data);
  257. #endif
  258. }