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.

308 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. Shutdown.c
  5. Abstract:
  6. This module implements the file system shutdown routine for Fat
  7. // @@BEGIN_DDKSPLIT
  8. Author:
  9. Gary Kimura [GaryKi] 19-Aug-1991
  10. Revision History:
  11. // @@END_DDKSPLIT
  12. --*/
  13. #include "FatProcs.h"
  14. //
  15. // Local debug trace level
  16. //
  17. #define Dbg (DEBUG_TRACE_SHUTDOWN)
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE, FatCommonShutdown)
  20. #pragma alloc_text(PAGE, FatFsdShutdown)
  21. #endif
  22. NTSTATUS
  23. FatFsdShutdown (
  24. IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
  25. IN PIRP Irp
  26. )
  27. /*++
  28. Routine Description:
  29. This routine implements the FSD part of shutdown. Note that Shutdown will
  30. never be done asynchronously so we will never need the Fsp counterpart
  31. to shutdown.
  32. This is the shutdown routine for the Fat file system device driver.
  33. This routine locks the global file system lock and then syncs all the
  34. mounted volumes.
  35. Arguments:
  36. VolumeDeviceObject - Supplies the volume device object where the
  37. file exists
  38. Irp - Supplies the Irp being processed
  39. Return Value:
  40. NTSTATUS - Always STATUS_SUCCESS
  41. --*/
  42. {
  43. NTSTATUS Status;
  44. PIRP_CONTEXT IrpContext = NULL;
  45. BOOLEAN TopLevel;
  46. DebugTrace(+1, Dbg, "FatFsdShutdown\n", 0);
  47. //
  48. // Call the common shutdown routine.
  49. //
  50. FsRtlEnterFileSystem();
  51. TopLevel = FatIsIrpTopLevel( Irp );
  52. try {
  53. IrpContext = FatCreateIrpContext( Irp, TRUE );
  54. Status = FatCommonShutdown( IrpContext, Irp );
  55. } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
  56. //
  57. // We had some trouble trying to perform the requested
  58. // operation, so we'll abort the I/O request with
  59. // the error status that we get back from the
  60. // execption code
  61. //
  62. Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
  63. }
  64. if (TopLevel) { IoSetTopLevelIrp( NULL ); }
  65. FsRtlExitFileSystem();
  66. //
  67. // And return to our caller
  68. //
  69. DebugTrace(-1, Dbg, "FatFsdShutdown -> %08lx\n", Status);
  70. UNREFERENCED_PARAMETER( VolumeDeviceObject );
  71. return Status;
  72. }
  73. NTSTATUS
  74. FatCommonShutdown (
  75. IN PIRP_CONTEXT IrpContext,
  76. IN PIRP Irp
  77. )
  78. /*++
  79. Routine Description:
  80. This is the common routine for shutdown called by both the fsd and
  81. fsp threads.
  82. Arguments:
  83. Irp - Supplies the Irp being processed
  84. Return Value:
  85. NTSTATUS - The return status for the operation
  86. --*/
  87. {
  88. PKEVENT Event;
  89. PLIST_ENTRY Links;
  90. PVCB Vcb;
  91. PIRP NewIrp;
  92. IO_STATUS_BLOCK Iosb;
  93. //
  94. // Make sure we don't get any pop-ups, and write everything through.
  95. //
  96. SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS |
  97. IRP_CONTEXT_FLAG_WRITE_THROUGH);
  98. //
  99. // Allocate an initialize an event for doing calls down to
  100. // our target deivce objects
  101. //
  102. Event = FsRtlAllocatePoolWithTag( NonPagedPool,
  103. sizeof(KEVENT),
  104. TAG_EVENT );
  105. KeInitializeEvent( Event, NotificationEvent, FALSE );
  106. //
  107. // Indicate that shutdown has started. This is used in FatFspClose.
  108. //
  109. FatData.ShutdownStarted = TRUE;
  110. //
  111. // Get everyone else out of the way
  112. //
  113. (VOID) FatAcquireExclusiveGlobal( IrpContext );
  114. try {
  115. //
  116. // For every volume that is mounted we will flush the
  117. // volume and then shutdown the target device objects.
  118. //
  119. Links = FatData.VcbQueue.Flink;
  120. while (Links != &FatData.VcbQueue) {
  121. Vcb = CONTAINING_RECORD(Links, VCB, VcbLinks);
  122. Links = Links->Flink;
  123. //
  124. // If we have already been called before for this volume
  125. // (and yes this does happen), skip this volume as no writes
  126. // have been allowed since the first shutdown.
  127. //
  128. if ( FlagOn( Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN) ||
  129. (Vcb->VcbCondition != VcbGood) ) {
  130. continue;
  131. }
  132. FatAcquireExclusiveVolume( IrpContext, Vcb );
  133. try {
  134. (VOID)FatFlushVolume( IrpContext, Vcb, Flush );
  135. //
  136. // The volume is now clean, note it. We purge the
  137. // volume file cache map before marking the volume
  138. // clean incase there is a stale Bpb in the cache.
  139. //
  140. if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
  141. CcPurgeCacheSection( &Vcb->SectionObjectPointers,
  142. NULL,
  143. 0,
  144. FALSE );
  145. FatMarkVolume( IrpContext, Vcb, VolumeClean );
  146. }
  147. } except( EXCEPTION_EXECUTE_HANDLER ) {
  148. FatResetExceptionState( IrpContext );
  149. }
  150. //
  151. // Sometimes we take an excepion while flushing the volume, such
  152. // as when autoconv has converted the volume and is rebooting.
  153. // Even in that case we want to send the shutdown irp to the
  154. // target device so it can know to flush its cache, if it has one.
  155. //
  156. try {
  157. NewIrp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN,
  158. Vcb->TargetDeviceObject,
  159. NULL,
  160. 0,
  161. NULL,
  162. Event,
  163. &Iosb );
  164. if (NewIrp != NULL) {
  165. if (NT_SUCCESS(IoCallDriver( Vcb->TargetDeviceObject, NewIrp ))) {
  166. (VOID) KeWaitForSingleObject( Event,
  167. Executive,
  168. KernelMode,
  169. FALSE,
  170. NULL );
  171. KeClearEvent( Event );
  172. }
  173. }
  174. } except( EXCEPTION_EXECUTE_HANDLER ) {
  175. FatResetExceptionState( IrpContext );
  176. }
  177. SetFlag( Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN );
  178. FatReleaseVolume( IrpContext, Vcb );
  179. //
  180. // Attempt to punch the volume down.
  181. //
  182. if (!FatCheckForDismount( IrpContext, Vcb, FALSE )) {
  183. FatFspClose( NULL );
  184. }
  185. }
  186. } finally {
  187. ExFreePool( Event );
  188. FatReleaseGlobal( IrpContext );
  189. //
  190. // Unregister the file system.
  191. //
  192. IoUnregisterFileSystem( FatDiskFileSystemDeviceObject);
  193. IoUnregisterFileSystem( FatCdromFileSystemDeviceObject);
  194. IoDeleteDevice( FatDiskFileSystemDeviceObject);
  195. IoDeleteDevice( FatCdromFileSystemDeviceObject);
  196. FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
  197. }
  198. //
  199. // And return to our caller
  200. //
  201. DebugTrace(-1, Dbg, "FatFsdShutdown -> STATUS_SUCCESS\n", 0);
  202. return STATUS_SUCCESS;
  203. }