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.

470 lines
11 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. FspDisp.c
  5. Abstract:
  6. This module implements the main dispatch procedure/thread for the Fat
  7. Fsp
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Gary Kimura [GaryKi] 28-Dec-1989
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "FatProcs.h"
  15. //
  16. // Internal support routine, spinlock wrapper.
  17. //
  18. PVOID
  19. FatRemoveOverflowEntry (
  20. IN PVOLUME_DEVICE_OBJECT VolDo
  21. );
  22. //
  23. // Define our local debug trace level
  24. //
  25. #define Dbg (DEBUG_TRACE_FSP_DISPATCHER)
  26. #ifdef ALLOC_PRAGMA
  27. #pragma alloc_text(PAGE, FatFspDispatch)
  28. #endif
  29. VOID
  30. FatFspDispatch (
  31. IN PVOID Context
  32. )
  33. /*++
  34. Routine Description:
  35. This is the main FSP thread routine that is executed to receive
  36. and dispatch IRP requests. Each FSP thread begins its execution here.
  37. There is one thread created at system initialization time and subsequent
  38. threads created as needed.
  39. Arguments:
  40. Context - Supplies the thread id.
  41. Return Value:
  42. None - This routine never exits
  43. --*/
  44. {
  45. NTSTATUS Status;
  46. PIRP Irp;
  47. PIRP_CONTEXT IrpContext;
  48. PIO_STACK_LOCATION IrpSp;
  49. PVOLUME_DEVICE_OBJECT VolDo;
  50. IrpContext = (PIRP_CONTEXT)Context;
  51. Irp = IrpContext->OriginatingIrp;
  52. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  53. //
  54. // Now because we are the Fsp we will force the IrpContext to
  55. // indicate true on Wait.
  56. //
  57. SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP);
  58. //
  59. // If this request has an associated volume device object, remember it.
  60. //
  61. if ( IrpSp->FileObject != NULL ) {
  62. VolDo = CONTAINING_RECORD( IrpSp->DeviceObject,
  63. VOLUME_DEVICE_OBJECT,
  64. DeviceObject );
  65. } else {
  66. VolDo = NULL;
  67. }
  68. //
  69. // Now case on the function code. For each major function code,
  70. // either call the appropriate FSP routine or case on the minor
  71. // function and then call the FSP routine. The FSP routine that
  72. // we call is responsible for completing the IRP, and not us.
  73. // That way the routine can complete the IRP and then continue
  74. // post processing as required. For example, a read can be
  75. // satisfied right away and then read can be done.
  76. //
  77. // We'll do all of the work within an exception handler that
  78. // will be invoked if ever some underlying operation gets into
  79. // trouble (e.g., if FatReadSectorsSync has trouble).
  80. //
  81. while ( TRUE ) {
  82. DebugTrace(0, Dbg, "FatFspDispatch: Irp = 0x%08lx\n", Irp);
  83. //
  84. // If this Irp was top level, note it in our thread local storage.
  85. //
  86. FsRtlEnterFileSystem();
  87. if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) ) {
  88. IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );
  89. } else {
  90. IoSetTopLevelIrp( Irp );
  91. }
  92. try {
  93. switch ( IrpContext->MajorFunction ) {
  94. //
  95. // For Create Operation,
  96. //
  97. case IRP_MJ_CREATE:
  98. (VOID) FatCommonCreate( IrpContext, Irp );
  99. break;
  100. //
  101. // For close operations. We do a little kludge here in case
  102. // this close causes a volume to go away. It will NULL the
  103. // VolDo local variable so that we will not try to look at
  104. // the overflow queue.
  105. //
  106. case IRP_MJ_CLOSE:
  107. {
  108. PVCB Vcb;
  109. PFCB Fcb;
  110. PCCB Ccb;
  111. TYPE_OF_OPEN TypeOfOpen;
  112. BOOLEAN VolumeTornDown = FALSE;
  113. //
  114. // Extract and decode the file object
  115. //
  116. TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );
  117. //
  118. // Do the close. We have a slightly different format
  119. // for this call because of the async closes.
  120. //
  121. Status = FatCommonClose( Vcb, Fcb, Ccb, TypeOfOpen, TRUE, &VolumeTornDown);
  122. ASSERT(Status == STATUS_SUCCESS);
  123. if (VolumeTornDown) {
  124. VolDo = NULL;
  125. }
  126. FatCompleteRequest( IrpContext, Irp, Status );
  127. break;
  128. }
  129. //
  130. // For read operations
  131. //
  132. case IRP_MJ_READ:
  133. (VOID) FatCommonRead( IrpContext, Irp );
  134. break;
  135. //
  136. // For write operations,
  137. //
  138. case IRP_MJ_WRITE:
  139. (VOID) FatCommonWrite( IrpContext, Irp );
  140. break;
  141. //
  142. // For Query Information operations,
  143. //
  144. case IRP_MJ_QUERY_INFORMATION:
  145. (VOID) FatCommonQueryInformation( IrpContext, Irp );
  146. break;
  147. //
  148. // For Set Information operations,
  149. //
  150. case IRP_MJ_SET_INFORMATION:
  151. (VOID) FatCommonSetInformation( IrpContext, Irp );
  152. break;
  153. //
  154. // For Query EA operations,
  155. //
  156. case IRP_MJ_QUERY_EA:
  157. (VOID) FatCommonQueryEa( IrpContext, Irp );
  158. break;
  159. //
  160. // For Set EA operations,
  161. //
  162. case IRP_MJ_SET_EA:
  163. (VOID) FatCommonSetEa( IrpContext, Irp );
  164. break;
  165. //
  166. // For Flush buffers operations,
  167. //
  168. case IRP_MJ_FLUSH_BUFFERS:
  169. (VOID) FatCommonFlushBuffers( IrpContext, Irp );
  170. break;
  171. //
  172. // For Query Volume Information operations,
  173. //
  174. case IRP_MJ_QUERY_VOLUME_INFORMATION:
  175. (VOID) FatCommonQueryVolumeInfo( IrpContext, Irp );
  176. break;
  177. //
  178. // For Set Volume Information operations,
  179. //
  180. case IRP_MJ_SET_VOLUME_INFORMATION:
  181. (VOID) FatCommonSetVolumeInfo( IrpContext, Irp );
  182. break;
  183. //
  184. // For File Cleanup operations,
  185. //
  186. case IRP_MJ_CLEANUP:
  187. (VOID) FatCommonCleanup( IrpContext, Irp );
  188. break;
  189. //
  190. // For Directory Control operations,
  191. //
  192. case IRP_MJ_DIRECTORY_CONTROL:
  193. (VOID) FatCommonDirectoryControl( IrpContext, Irp );
  194. break;
  195. //
  196. // For File System Control operations,
  197. //
  198. case IRP_MJ_FILE_SYSTEM_CONTROL:
  199. (VOID) FatCommonFileSystemControl( IrpContext, Irp );
  200. break;
  201. //
  202. // For Lock Control operations,
  203. //
  204. case IRP_MJ_LOCK_CONTROL:
  205. (VOID) FatCommonLockControl( IrpContext, Irp );
  206. break;
  207. //
  208. // For Device Control operations,
  209. //
  210. case IRP_MJ_DEVICE_CONTROL:
  211. (VOID) FatCommonDeviceControl( IrpContext, Irp );
  212. break;
  213. //
  214. // For the Shutdown operation,
  215. //
  216. case IRP_MJ_SHUTDOWN:
  217. (VOID) FatCommonShutdown( IrpContext, Irp );
  218. break;
  219. //
  220. // For plug and play operations.
  221. //
  222. case IRP_MJ_PNP:
  223. //
  224. // I don't believe this should ever occur, but allow for the unexpected.
  225. //
  226. (VOID) FatCommonPnp( IrpContext, Irp );
  227. break;
  228. //
  229. // For any other major operations, return an invalid
  230. // request.
  231. //
  232. default:
  233. FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
  234. break;
  235. }
  236. } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
  237. //
  238. // We had some trouble trying to perform the requested
  239. // operation, so we'll abort the I/O request with
  240. // the error status that we get back from the
  241. // execption code.
  242. //
  243. (VOID) FatProcessException( IrpContext, Irp, GetExceptionCode() );
  244. }
  245. IoSetTopLevelIrp( NULL );
  246. FsRtlExitFileSystem();
  247. //
  248. // If there are any entries on this volume's overflow queue, service
  249. // them.
  250. //
  251. if ( VolDo != NULL ) {
  252. PVOID Entry;
  253. //
  254. // We have a volume device object so see if there is any work
  255. // left to do in its overflow queue.
  256. //
  257. Entry = FatRemoveOverflowEntry( VolDo );
  258. //
  259. // There wasn't an entry, break out of the loop and return to
  260. // the Ex Worker thread.
  261. //
  262. if ( Entry == NULL ) {
  263. break;
  264. }
  265. //
  266. // Extract the IrpContext, Irp, and IrpSp, and loop.
  267. //
  268. IrpContext = CONTAINING_RECORD( Entry,
  269. IRP_CONTEXT,
  270. WorkQueueItem.List );
  271. SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP);
  272. Irp = IrpContext->OriginatingIrp;
  273. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  274. continue;
  275. } else {
  276. break;
  277. }
  278. }
  279. //
  280. // Decrement the PostedRequestCount.
  281. //
  282. if ( VolDo ) {
  283. ExInterlockedAddUlong( &VolDo->PostedRequestCount,
  284. 0xffffffff,
  285. &VolDo->OverflowQueueSpinLock );
  286. }
  287. return;
  288. }
  289. //
  290. // Internal support routine, spinlock wrapper.
  291. //
  292. PVOID
  293. FatRemoveOverflowEntry (
  294. IN PVOLUME_DEVICE_OBJECT VolDo
  295. )
  296. {
  297. PVOID Entry;
  298. KIRQL SavedIrql;
  299. KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql );
  300. if (VolDo->OverflowQueueCount > 0) {
  301. //
  302. // There is overflow work to do in this volume so we'll
  303. // decrement the Overflow count, dequeue the IRP, and release
  304. // the Event
  305. //
  306. VolDo->OverflowQueueCount -= 1;
  307. Entry = RemoveHeadList( &VolDo->OverflowQueue );
  308. } else {
  309. Entry = NULL;
  310. }
  311. KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql );
  312. return Entry;
  313. }