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.

522 lines
12 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. fspdisp.c
  5. Abstract:
  6. This file provides the main FSP dispatch routine for the NT browser.
  7. It mostly provides a switch statement that calls the appropriate BowserFsp
  8. routine and returns that status to the caller.
  9. Notes:
  10. There are two classes of browser FSP worker threads. The first
  11. are what are called FSP worker threads. These threads are responsible
  12. for processing NT Irp's passed onto the browser's main work thread.
  13. In addition to this pool of threads, there is a small pool of "generic"
  14. worker threads whose sole purpose is to process generic request
  15. operations. These are used for processing such operations as close
  16. behind, etc.
  17. Author:
  18. Larry Osterman (LarryO) 31-May-1990
  19. Revision History:
  20. 31-May-1990 LarryO
  21. Created
  22. --*/
  23. #include "precomp.h"
  24. #pragma hdrstop
  25. //
  26. // This defines the granularity of the scavenger timer. If it is set
  27. // to 30 (for example), the scavenger thread will fire every 30 seconds.
  28. //
  29. #define SCAVENGER_TIMER_GRANULARITY 30
  30. #define UNEXPECTED_TIMER_GRANULARITY (60 * 60 / SCAVENGER_TIMER_GRANULARITY)
  31. //
  32. // This counter is used to control kicking the scavenger thread.
  33. //
  34. ULONG
  35. BowserTimerCounter = SCAVENGER_TIMER_GRANULARITY;
  36. KSPIN_LOCK
  37. BowserTimeSpinLock = {0};
  38. VOID
  39. BowserFspDispatch (
  40. IN PVOID WorkHeader
  41. );
  42. VOID
  43. BowserScavenger (
  44. IN PVOID WorkHeader
  45. );
  46. VOID
  47. BowserLogUnexpectedEvents(
  48. VOID
  49. );
  50. #ifdef ALLOC_PRAGMA
  51. #pragma alloc_text(PAGE, BowserFsdPostToFsp)
  52. #pragma alloc_text(PAGE, BowserFspDispatch)
  53. #pragma alloc_text(PAGE, BowserLogUnexpectedEvents)
  54. #pragma alloc_text(PAGE, BowserScavenger)
  55. #pragma alloc_text(PAGE, BowserpUninitializeFsp)
  56. #pragma alloc_text(INIT, BowserpInitializeFsp)
  57. #endif
  58. NTSTATUS
  59. BowserFsdPostToFsp(
  60. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  61. IN PIRP Irp
  62. )
  63. /*++
  64. Routine Description:
  65. This routine passes the IRP specified onto the FSP work queue, and kicks
  66. an FSP thread. This routine accepts an I/O Request Packet (IRP) and a
  67. work queue and passes the request to the appropriate request queue.
  68. Arguments:
  69. DeviceObject - Pointer to the device object for this driver.
  70. Irp - Pointer to the request packet representing the I/O request.
  71. Return Value:
  72. The function value is the status of the operation.
  73. --*/
  74. {
  75. PIRP_CONTEXT IrpContext;
  76. PAGED_CODE();
  77. IrpContext = BowserAllocateIrpContext();
  78. if ( IrpContext == NULL ) {
  79. return STATUS_INSUFFICIENT_RESOURCES;
  80. }
  81. //
  82. // Mark this I/O request as being pending.
  83. //
  84. IoMarkIrpPending(Irp);
  85. //
  86. // Queue the request to a generic worker thread.
  87. //
  88. IrpContext->Irp = Irp;
  89. IrpContext->DeviceObject = DeviceObject;
  90. ExInitializeWorkItem(&IrpContext->WorkHeader, BowserFspDispatch, IrpContext);
  91. ExQueueWorkItem(&IrpContext->WorkHeader, DelayedWorkQueue);
  92. return STATUS_PENDING;
  93. }
  94. VOID
  95. BowserFspDispatch (
  96. IN PVOID WorkHeader
  97. )
  98. /*++
  99. Routine Description:
  100. BowserFspDispatch is the main dispatch routine for the NT browser's
  101. FSP. It will process worker requests as queued.
  102. Arguments:
  103. DeviceObject - A pointer to the browser DeviceObject
  104. Return Value:
  105. None.
  106. --*/
  107. {
  108. PIRP_CONTEXT IrpContext = WorkHeader;
  109. PIRP Irp = IrpContext->Irp;
  110. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  111. NTSTATUS Status;
  112. PBOWSER_FS_DEVICE_OBJECT DeviceObject = IrpContext->DeviceObject;
  113. PAGED_CODE();
  114. //
  115. // We no longer need the IRP context, free it as soon as possible.
  116. //
  117. BowserFreeIrpContext(IrpContext);
  118. dlog(DPRT_FSPDISP, ("BowserFspDispatch: Got request, Irp = %08lx, "
  119. "Function = %d Aux buffer = %08lx\n", Irp, IrpSp->MajorFunction,
  120. Irp->Tail.Overlay.AuxiliaryBuffer));
  121. switch (IrpSp->MajorFunction) {
  122. case IRP_MJ_DEVICE_CONTROL:
  123. Status = BowserFspDeviceIoControlFile (DeviceObject, Irp);
  124. break;
  125. case IRP_MJ_QUERY_INFORMATION:
  126. Status = BowserFspQueryInformationFile (DeviceObject, Irp);
  127. break;
  128. case IRP_MJ_QUERY_VOLUME_INFORMATION:
  129. Status = BowserFspQueryVolumeInformationFile (DeviceObject, Irp);
  130. break;
  131. case IRP_MJ_FILE_SYSTEM_CONTROL:
  132. case IRP_MJ_CREATE:
  133. case IRP_MJ_CLEANUP:
  134. case IRP_MJ_READ:
  135. case IRP_MJ_WRITE:
  136. case IRP_MJ_DIRECTORY_CONTROL:
  137. case IRP_MJ_SET_INFORMATION:
  138. case IRP_MJ_LOCK_CONTROL:
  139. case IRP_MJ_FLUSH_BUFFERS:
  140. case IRP_MJ_QUERY_EA:
  141. case IRP_MJ_CREATE_NAMED_PIPE:
  142. case IRP_MJ_CLOSE:
  143. Status = STATUS_INVALID_DEVICE_REQUEST;
  144. BowserCompleteRequest(Irp, Status);
  145. break;
  146. default:
  147. InternalError(("Unimplemented function %d\n", IrpSp->MajorFunction));
  148. Status = STATUS_NOT_IMPLEMENTED;
  149. BowserCompleteRequest(Irp, Status);
  150. break;
  151. }
  152. return;
  153. }
  154. VOID
  155. BowserIdleTimer (
  156. IN PDEVICE_OBJECT DeviceObject,
  157. IN PVOID Context
  158. )
  159. /*++
  160. Routine Description:
  161. This routine implements the NT redirector's scavenger thread timer.
  162. It basically waits for the timer granularity and kicks the scavenger
  163. thread.
  164. Arguments:
  165. IN PDEVICE_OBJECT DeviceObject - Supplies the device object for the timer
  166. IN PVOID Context - Ignored in this routine.
  167. Return Value:
  168. None.
  169. --*/
  170. {
  171. KIRQL OldIrql;
  172. ACQUIRE_SPIN_LOCK(&BowserTimeSpinLock, &OldIrql);
  173. //
  174. // Bump the current time counter.
  175. //
  176. BowserCurrentTime++;
  177. if (BowserEventLogResetFrequency != -1) {
  178. BowserEventLogResetFrequency -= 1;
  179. if (BowserEventLogResetFrequency < 0) {
  180. BowserEventLogResetFrequency = BowserData.EventLogResetFrequency;
  181. BowserIllegalDatagramCount = BowserData.IllegalDatagramThreshold;
  182. BowserIllegalDatagramThreshold = FALSE;
  183. BowserIllegalNameCount = BowserData.IllegalDatagramThreshold;
  184. BowserIllegalNameThreshold = FALSE;
  185. }
  186. }
  187. //
  188. // We use the redirector's time spinlock as a convenient spinlock here.
  189. //
  190. if (BowserTimerCounter != 0) {
  191. BowserTimerCounter -= 1;
  192. if (BowserTimerCounter == 0) {
  193. PWORK_QUEUE_ITEM WorkHeader;
  194. RELEASE_SPIN_LOCK(&BowserTimeSpinLock, OldIrql);
  195. WorkHeader = ALLOCATE_POOL(NonPagedPool, sizeof(WORK_QUEUE_ITEM), POOL_WORKITEM);
  196. //
  197. // If the allocation of pool fails, we simply don't queue this
  198. // request to the scavenger. The scavenger is low priority,
  199. // thus it isn't a big deal to fail this request.
  200. //
  201. if (WorkHeader != NULL) {
  202. ExInitializeWorkItem(WorkHeader, BowserScavenger, WorkHeader);
  203. //
  204. // Due to bug 245645 we need to queue in delayed worker queue rather then execute timed tasks.
  205. // OLD WAY: ExQueueWorkItem(WorkHeader, DelayedWorkQueue);
  206. //
  207. BowserQueueDelayedWorkItem( WorkHeader );
  208. }
  209. //
  210. // Re-acquire the spin lock to make the exit path cleaner.
  211. //
  212. ACQUIRE_SPIN_LOCK(&BowserTimeSpinLock, &OldIrql);
  213. }
  214. }
  215. RELEASE_SPIN_LOCK(&BowserTimeSpinLock, OldIrql);
  216. return;
  217. UNREFERENCED_PARAMETER(DeviceObject);
  218. UNREFERENCED_PARAMETER(Context);
  219. }
  220. LONG
  221. UnexpectedEventTimer = UNEXPECTED_TIMER_GRANULARITY;
  222. VOID
  223. BowserLogUnexpectedEvents(
  224. VOID
  225. )
  226. {
  227. LONG TimerSign;
  228. PAGED_CODE();
  229. TimerSign = InterlockedDecrement( &UnexpectedEventTimer );
  230. if ( TimerSign == 0) {
  231. if (BowserNumberOfMissedMailslotDatagrams > BowserMailslotDatagramThreshold) {
  232. BowserWriteErrorLogEntry(EVENT_BOWSER_MAILSLOT_DATAGRAM_THRESHOLD_EXCEEDED, STATUS_INSUFFICIENT_RESOURCES, NULL, 0, 0);
  233. BowserNumberOfMissedMailslotDatagrams = 0;
  234. }
  235. if (BowserNumberOfMissedGetBrowserServerListRequests > BowserGetBrowserListThreshold) {
  236. BowserWriteErrorLogEntry(EVENT_BOWSER_GETBROWSERLIST_THRESHOLD_EXCEEDED, STATUS_INSUFFICIENT_RESOURCES, NULL, 0, 0);
  237. BowserNumberOfMissedGetBrowserServerListRequests = 0;
  238. }
  239. InterlockedExchangeAdd(&UnexpectedEventTimer, UNEXPECTED_TIMER_GRANULARITY );
  240. }
  241. }
  242. VOID
  243. BowserScavenger (
  244. IN PVOID Context
  245. )
  246. /*++
  247. Routine Description:
  248. This function implements the NT browsers's scavenger thread. It
  249. performs all idle time operations such as closing out dormant connections
  250. etc.
  251. Arguments:
  252. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject - Supplies the device object associated
  253. with this request.
  254. Return Value:
  255. None.
  256. --*/
  257. {
  258. PAGED_CODE();
  259. dlog(DPRT_SCAVTHRD, ("BowserScavenger\n"));
  260. //
  261. // Deallocate the pool used for the work context header - we're done with
  262. // it.
  263. //
  264. FREE_POOL(Context);
  265. //
  266. // Remove old entries from the announcetable.
  267. //
  268. BowserAgeServerAnnouncements();
  269. //
  270. // Log if any of our thresholds have been exceeded.
  271. //
  272. BowserLogUnexpectedEvents();
  273. //
  274. // Time out any outstanding find master requests if they have taken too
  275. // long.
  276. //
  277. BowserTimeoutFindMasterRequests();
  278. //
  279. // Reset the timer counter back to the appropriate value
  280. // once we have finished processing these requests.
  281. //
  282. ExInterlockedAddUlong(&BowserTimerCounter, SCAVENGER_TIMER_GRANULARITY, &BowserTimeSpinLock);
  283. }
  284. NTSTATUS
  285. BowserpInitializeFsp (
  286. PDRIVER_OBJECT BowserDriverObject
  287. )
  288. /*++
  289. Routine Description:
  290. This routine initializes the FSP specific components and dispatch
  291. routines.
  292. Arguments:
  293. None.
  294. Return Value:
  295. None.
  296. --*/
  297. {
  298. #if 0
  299. USHORT i;
  300. //
  301. // Initialize the driver object with this driver's entry points.
  302. //
  303. // By default, pass all requests to the FSD.
  304. //
  305. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  306. BowserDriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)BowserFsdPostToFsp;
  307. }
  308. //
  309. // Initialize those request that are to be performed in the FSD, not
  310. // in the FSP.
  311. //
  312. BowserDriverObject->MajorFunction[IRP_MJ_CREATE] =
  313. (PDRIVER_DISPATCH )BowserFsdCreate;
  314. BowserDriverObject->MajorFunction[IRP_MJ_CLOSE] =
  315. (PDRIVER_DISPATCH )BowserFsdClose;
  316. BowserDriverObject->MajorFunction[IRP_MJ_CLEANUP] =
  317. (PDRIVER_DISPATCH )BowserFsdCleanup;
  318. BowserDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
  319. (PDRIVER_DISPATCH )BowserFsdQueryInformationFile;
  320. BowserDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
  321. (PDRIVER_DISPATCH )BowserFsdDeviceIoControlFile;
  322. #endif
  323. BowserInitializeIrpContext();
  324. KeInitializeSpinLock(&BowserTimeSpinLock);
  325. return STATUS_SUCCESS;
  326. }
  327. VOID
  328. BowserpUninitializeFsp (
  329. VOID
  330. )
  331. /*++
  332. Routine Description:
  333. This routine initializes the FSP specific components and dispatch
  334. routines.
  335. Arguments:
  336. None.
  337. Return Value:
  338. None.
  339. --*/
  340. {
  341. PAGED_CODE();
  342. BowserpUninitializeIrpContext();
  343. return;
  344. }