ReactOS  0.4.13-dev-66-gc714b7f
shutdown.cpp
Go to the documentation of this file.
1 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
6 /*************************************************************************
7 *
8 * File: Shutdown.cpp
9 *
10 * Module: UDF File System Driver (Kernel mode execution only)
11 *
12 * Description:
13 * Contains code to handle the "shutdown notification" dispatch entry point.
14 *
15 *************************************************************************/
16 
17 #include "udffs.h"
18 
19 // define the file specific bug-check id
20 #define UDF_BUG_CHECK_ID UDF_FILE_SHUTDOWN
21 
22 
23 
24 /*************************************************************************
25 *
26 * Function: UDFShutdown()
27 *
28 * Description:
29 * All disk-based FSDs can expect to receive this shutdown notification
30 * request whenever the system is about to be halted gracefully. If you
31 * design and implement a network redirector, you must register explicitly
32 * for shutdown notification by invoking the IoRegisterShutdownNotification()
33 * routine from your driver entry.
34 *
35 * Note that drivers that register to receive shutdown notification get
36 * invoked BEFORE disk-based FSDs are told about the shutdown notification.
37 *
38 * Expected Interrupt Level (for execution) :
39 *
40 * IRQL_PASSIVE_LEVEL
41 *
42 * Return Value: Irrelevant.
43 *
44 *************************************************************************/
46 NTAPI
48  PDEVICE_OBJECT DeviceObject, // the logical volume device object
49  PIRP Irp // I/O Request Packet
50  )
51 {
53  PtrUDFIrpContext PtrIrpContext = NULL;
54  BOOLEAN AreWeTopLevel = FALSE;
55 
56  UDFPrint(("UDFShutDown\n"));
57 // BrutePoint();
58 
61  ASSERT(Irp);
62 
63  // set the top level context
64  AreWeTopLevel = UDFIsIrpTopLevel(Irp);
65  //ASSERT(!UDFIsFSDevObj(DeviceObject));
66 
67  _SEH2_TRY {
68 
69  // get an IRP context structure and issue the request
70  PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
71  if(PtrIrpContext) {
72  RC = UDFCommonShutdown(PtrIrpContext, Irp);
73  } else {
75  Irp->IoStatus.Status = RC;
76  Irp->IoStatus.Information = 0;
77  // complete the IRP
79  }
80 
82 
83  RC = UDFExceptionHandler(PtrIrpContext, Irp);
84 
86  } _SEH2_END;
87 
88  if (AreWeTopLevel) {
90  }
91 
93 
94  return(RC);
95 } // end UDFShutdown()
96 
97 
98 /*************************************************************************
99 *
100 * Function: UDFCommonShutdown()
101 *
102 * Description:
103 * The actual work is performed here. Basically, all we do here is
104 * internally invoke a flush on all mounted logical volumes. This, in
105 * tuen, will result in all open file streams being flushed to disk.
106 *
107 * Expected Interrupt Level (for execution) :
108 *
109 * IRQL_PASSIVE_LEVEL
110 *
111 * Return Value: Irrelevant
112 *
113 *************************************************************************/
114 NTSTATUS
116  PtrUDFIrpContext PtrIrpContext,
117  PIRP Irp
118  )
119 {
122  PVCB Vcb;
126 
127  UDFPrint(("UDFCommonShutdown\n"));
128 
129  _SEH2_TRY {
130  // First, get a pointer to the current I/O stack location
132  ASSERT(IrpSp);
133 
135  if(!Buf)
137 
138  // (a) Block all new "mount volume" requests by acquiring an appropriate
139  // global resource/lock.
140  // (b) Go through your linked list of mounted logical volumes and for
141  // each such volume, do the following:
142  // (i) acquire the volume resource exclusively
143  // (ii) invoke UDFFlushLogicalVolume() (internally) to flush the
144  // open data streams belonging to the volume from the system
145  // cache
146  // (iii) Invoke the physical/virtual/logical target device object
147  // on which the volume is mounted and inform this device
148  // about the shutdown request (Use IoBuildSynchronouFsdRequest()
149  // to create an IRP with MajorFunction = IRP_MJ_SHUTDOWN that you
150  // will then issue to the target device object).
151  // (iv) Wait for the completion of the shutdown processing by the target
152  // device object
153  // (v) Release the VCB resource we will have acquired in (i) above.
154 
155  // Acquire GlobalDataResource
156  UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
157  // Walk through all of the Vcb's attached to the global data.
158  Link = UDFGlobalData.VCBQueue.Flink;
159 
160  while (Link != &(UDFGlobalData.VCBQueue)) {
161  // Get 'next' Vcb
162  Vcb = CONTAINING_RECORD( Link, VCB, NextVCB );
163  // Move to the next link now since the current Vcb may be deleted.
164  Link = Link->Flink;
165  ASSERT(Link != Link->Flink);
166 
167  if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_SHUTDOWN)) {
168 
169 #ifdef UDF_DELAYED_CLOSE
170  UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
171  UDFPrint((" UDFCommonShutdown: set UDF_VCB_FLAGS_NO_DELAYED_CLOSE\n"));
172  Vcb->VCBFlags |= UDF_VCB_FLAGS_NO_DELAYED_CLOSE;
173  UDFReleaseResource(&(Vcb->VCBResource));
174 #endif //UDF_DELAYED_CLOSE
175 
176  // Note: UDFCloseAllDelayed() doesn't acquire DelayedCloseResource if
177  // GlobalDataResource is already acquired. Thus for now we should
178  // release GlobalDataResource and re-acquire it later.
179  UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
180  if(Vcb->RootDirFCB && Vcb->RootDirFCB->FileInfo) {
181  UDFPrint((" UDFCommonShutdown: UDFCloseAllSystemDelayedInDir\n"));
182  RC = UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
183  ASSERT(OS_SUCCESS(RC));
184  }
185 
186 #ifdef UDF_DELAYED_CLOSE
188 // UDFReleaseResource(&(UDFGlobalData.DelayedCloseResource));
189 #endif //UDF_DELAYED_CLOSE
190 
191  // re-acquire GlobalDataResource
192  UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
193 
194  // disable Eject Waiter
196  // Acquire Vcb resource
197  UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
198 
199  ASSERT(!Vcb->OverflowQueueCount);
200 
201  if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_SHUTDOWN)) {
202 
204  if(Vcb->VCBFlags & UDF_VCB_FLAGS_REMOVABLE_MEDIA) {
205  // let drive flush all data before reset
206  delay.QuadPart = -10000000; // 1 sec
208  }
209  Vcb->VCBFlags |= (UDF_VCB_FLAGS_SHUTDOWN |
211  }
212 
213  UDFReleaseResource(&(Vcb->VCBResource));
214  }
215  }
216  // Once we have processed all the mounted logical volumes, we can release
217  // all acquired global resources and leave (in peace :-)
218  UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
219  RC = STATUS_SUCCESS;
220 
221 try_exit: NOTHING;
222 
223  } _SEH2_FINALLY {
224 
225  if(Buf) MyFreePool__(Buf);
227  Irp->IoStatus.Status = RC;
228  Irp->IoStatus.Information = 0;
229  // Free up the Irp Context
230  UDFReleaseIrpContext(PtrIrpContext);
231  // complete the IRP
233  }
234 
235  } _SEH2_END; // end of "__finally" processing
236 
237  return(RC);
238 } // end UDFCommonShutdown()
#define UDFAcquireResourceExclusive(Resource, CanWait)
Definition: env_spec_w32.h:656
VOID UDFReleaseIrpContext(PtrUDFIrpContext PtrIrpContext)
Definition: misc.cpp:1086
PtrUDFIrpContext UDFAllocateIrpContext(PIRP Irp, PDEVICE_OBJECT PtrTargetDeviceObject)
Definition: misc.cpp:985
#define UDFPrint(Args)
Definition: udffs.h:225
#define TRUE
Definition: types.h:120
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define UDFCloseAllSystemDelayedInDir(Vcb, FI)
Definition: protos.h:99
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
VOID UDFLogEvent(NTSTATUS UDFEventLogId, NTSTATUS RC)
Definition: misc.cpp:575
_In_ PIRP Irp
Definition: csq.h:116
#define UDFReleaseResource(Resource)
Definition: env_spec_w32.h:661
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS UDFCommonShutdown(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: shutdown.cpp:115
Definition: cdstruc.h:504
struct _PREVENT_MEDIA_REMOVAL_USER_IN * PPREVENT_MEDIA_REMOVAL_USER_IN
#define UDF_VCB_FLAGS_REMOVABLE_MEDIA
Definition: udf_common.h:468
static int Link(const char **args)
Definition: vfdcmd.c:2414
_SEH2_TRY
Definition: create.c:4250
#define UDF_VCB_FLAGS_VOLUME_READ_ONLY
Definition: udf_common.h:463
#define IO_DISK_INCREMENT
Definition: iotypes.h:567
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
NTSTATUS NTAPI KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval OPTIONAL)
Definition: wait.c:283
VOID UDFStopEjectWaiter(PVCB Vcb)
Definition: phys_eject.cpp:673
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
#define UDF_VCB_FLAGS_SHUTDOWN
Definition: udf_common.h:462
#define IoCompleteRequest
Definition: irp.c:1240
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS UDFExceptionHandler(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: misc.cpp:358
#define MyAllocatePool__(type, size)
Definition: mem_tools.h:149
#define try_return(S)
Definition: cdprocs.h:2189
#define Vcb
Definition: cdprocs.h:1425
#define MyFreePool__(addr)
Definition: mem_tools.h:152
NTSTATUS NTAPI UDFShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: shutdown.cpp:47
BOOLEAN __fastcall UDFIsIrpTopLevel(PIRP Irp)
Definition: misc.cpp:228
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define UDF_VCB_FLAGS_NO_DELAYED_CLOSE
Definition: udf_common.h:480
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
void delay(unsigned msec)
Definition: i386rtl.c:32
UDFData UDFGlobalData
Definition: udfinit.cpp:25
#define OS_SUCCESS(a)
Definition: env_spec_w32.h:56
long UDFExceptionFilter(PtrUDFIrpContext PtrIrpContext, PEXCEPTION_POINTERS PtrExceptionPointers)
Definition: misc.cpp:265
#define NOTHING
Definition: env_spec_w32.h:461
Definition: typedefs.h:117
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define UDF_ERROR_INTERNAL_ERROR
Definition: errmsg.h:71
_SEH2_END
Definition: create.c:4424
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
_SEH2_FINALLY
Definition: create.c:4395
VOID UDFCloseAllDelayed(IN PVCB Vcb)
Definition: close.cpp:754
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
OSSTATUS UDFDoDismountSequence(IN PVCB Vcb, IN PPREVENT_MEDIA_REMOVAL_USER_IN Buf, IN BOOLEAN Eject)
Definition: phys_eject.cpp:704
return STATUS_SUCCESS
Definition: btrfs.c:2725