ReactOS 0.4.15-dev-7998-gdb93cb1
povolume.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/po/povolume.c
5 * PURPOSE: Power Manager DOPE and Volume Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* GLOBALS *******************************************************************/
16
17typedef struct _POP_FLUSH_VOLUME
18{
23
25
29
30/* PRIVATE FUNCTIONS *********************************************************/
31
35{
36 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
39 PAGED_CODE();
40
41 /* If the device already has the dope, return it */
42 DeviceExtension = IoGetDevObjExtension(DeviceObject);
43 if (DeviceExtension->Dope) goto Return;
44
45 /* Allocate some dope for the device */
49 if (!Dope) goto Return;
50
51 /* Initialize the initial contents of the dope */
56
57 /* Make sure only one caller can assign dope to a device */
59
60 /* Make sure the device still has no dope */
61 if (!DeviceExtension->Dope)
62 {
63 /* Give the local dope to this device, and remember we won the race */
64 DeviceExtension->Dope = (PVOID)Dope;
65 Dope = NULL;
66 }
67
68 /* Allow other dope transactions now */
70
71 /* Check if someone other than us already assigned the dope, so free ours */
72 if (Dope) ExFreePoolWithTag(Dope, TAG_PO_DOPE);
73
74 /* Return the dope to the caller */
75Return:
76 return (PDEVICE_OBJECT_POWER_EXTENSION)DeviceExtension->Dope;
77}
78
79VOID
82{
84 PAGED_CODE();
85
86 /* Get dope from the device (if the device has no dope, it will receive some) */
88 if (Dope)
89 {
90 /* Make sure we can flush safely */
92
93 /* Add this volume into the list of power-manager volumes */
95
96 /* Allow flushes to go through */
98 }
99}
100
101VOID
102NTAPI
104{
106 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
108 PAGED_CODE();
109
110 /* If the device already has the dope, return it */
111 DeviceExtension = IoGetDevObjExtension(DeviceObject);
112 if (!DeviceExtension->Dope)
113 {
114 /* no dope */
115 return;
116 }
117
118 /* Make sure we can flush safely */
120
121 /* Get dope from device */
122 Dope = (PDEVICE_OBJECT_POWER_EXTENSION)DeviceExtension->Dope;
123
124 if (Dope->Volume.Flink)
125 {
126 /* Remove from volume from list */
127 RemoveEntryList(&Dope->Volume);
128 }
129
130 /* Allow flushes to go through */
132
133 /* Now remove dope from device object */
135
136 /* remove from dev obj */
137 DeviceExtension->Dope = NULL;
138
139 /* Release lock */
141
142 /* Free dope */
144}
145
146VOID
147NTAPI
149{
152 PLIST_ENTRY NextEntry;
154 UCHAR Buffer[sizeof(OBJECT_NAME_INFORMATION) + 512];
160
161 /* Acquire the flush lock since we're messing with the list */
163
164 /* Loop the flush list */
165 while (!IsListEmpty(&FlushContext->List))
166 {
167 /* Grab the next (ie: current) entry and remove it */
168 NextEntry = FlushContext->List.Flink;
169 RemoveEntryList(NextEntry);
170
171 /* Add it back on the volume list */
172 InsertTailList(&PopVolumeDevices, NextEntry);
173
174 /* Done touching the volume list */
176
177 /* Get the dope from the volume link */
179
180 /* Get the name */
182 NameInfo,
183 sizeof(Buffer),
184 &Length);
185 if ((NT_SUCCESS(Status)) && (NameInfo->Name.Buffer))
186 {
187 /* Open the volume */
188 DPRINT("Opening: %wZ\n", &NameInfo->Name);
190 &NameInfo->Name,
192 0,
193 0);
194 Status = ZwCreateFile(&VolumeHandle,
198 NULL,
201 FILE_OPEN,
202 0,
203 NULL,
204 0);
205 if (NT_SUCCESS(Status))
206 {
207 /* Flush it and close it */
208 DPRINT("Sending flush to: %p\n", VolumeHandle);
211 }
212 }
213
214 /* Acquire the flush lock again since we'll touch the list */
216 }
217
218 /* One more flush completed... if it was the last, signal the caller */
219 if (!--FlushContext->Count) KeSetEvent(&FlushContext->Wait, IO_NO_INCREMENT, FALSE);
220
221 /* Serialize with flushers */
223}
224
225VOID
226NTAPI
228{
229 POP_FLUSH_VOLUME FlushContext = {{0}};
230 ULONG FlushPolicy;
231 UNICODE_STRING RegistryName = RTL_CONSTANT_STRING(L"\\Registry");
233 HANDLE RegistryHandle;
234 PLIST_ENTRY NextEntry;
236 ULONG VolumeCount = 0;
238 HANDLE ThreadHandle;
239 ULONG ThreadCount;
240
241 /* Setup the flush context */
242 InitializeListHead(&FlushContext.List);
244
245 /* What to flush */
246 FlushPolicy = ShuttingDown ? 1 | 2 : PopFlushPolicy;
247 if ((FlushPolicy & 1))
248 {
249 /* Registry flush requested, so open it */
250 DPRINT("Opening registry\n");
252 &RegistryName,
254 NULL,
255 NULL);
256 Status = ZwOpenKey(&RegistryHandle, KEY_READ, &ObjectAttributes);
257 if (NT_SUCCESS(Status))
258 {
259 /* Flush the registry */
260 DPRINT("Flushing registry\n");
261 ZwFlushKey(RegistryHandle);
262 ZwClose(RegistryHandle);
263 }
264 }
265
266 /* Serialize with other flushes */
268
269 /* Scan the volume list */
270 NextEntry = PopVolumeDevices.Flink;
271 while (NextEntry != &PopVolumeDevices)
272 {
273 /* Get the dope from the link */
275
276 /* Grab the next entry now, since we'll be modifying the list */
277 NextEntry = NextEntry->Flink;
278
279 /* Make sure the object is mounted, writable, exists, and is not a floppy */
280 if (!(Dope->DeviceObject->Vpb->Flags & VPB_MOUNTED) ||
281 (Dope->DeviceObject->Characteristics & FILE_FLOPPY_DISKETTE) ||
282 (Dope->DeviceObject->Characteristics & FILE_READ_ONLY_DEVICE) ||
283 ((Dope->DeviceObject->Vpb->RealDevice) &&
284 (Dope->DeviceObject->Vpb->RealDevice->Characteristics & FILE_FLOPPY_DISKETTE)))
285 {
286 /* Not flushable */
287 continue;
288 }
289
290 /* Remove it from the dope and add it to the flush context list */
291 RemoveEntryList(&Dope->Volume);
292 InsertTailList(&FlushContext.List, &Dope->Volume);
293
294 /* Next */
295 VolumeCount++;
296 }
297
298 /* Check if we should skip non-removable devices */
299 if (!(FlushPolicy & 2))
300 {
301 /* ReactOS only implements this routine for shutdown, which requires it */
303 }
304
305 /* Check if there were no volumes at all */
306 if (!VolumeCount)
307 {
308 /* Nothing to do */
310 return;
311 }
312
313 /* Allocate up to 8 flusher threads */
314 ThreadCount = min(VolumeCount, 8);
316 NULL,
318 NULL,
319 NULL);
320
321 /* We will ourselves become a flusher thread */
322 FlushContext.Count = 1;
323 ThreadCount--;
324
325 /* Look for any extra ones we might need */
326 while (ThreadCount > 0)
327 {
328 /* Create a new one */
329 ThreadCount--;
330 DPRINT("Creating flush thread\n");
331 Status = PsCreateSystemThread(&ThreadHandle,
334 0L,
335 NULL,
337 &FlushContext);
338 if (NT_SUCCESS(Status))
339 {
340 /* One more created... */
341 FlushContext.Count++;
342 ZwClose(ThreadHandle);
343 }
344 }
345
346 /* Allow flushes to go through */
348
349 /* Enter the flush work */
350 DPRINT("Local flush\n");
351 PopFlushVolumeWorker(&FlushContext);
352
353 /* Wait for all flushes to be over */
354 DPRINT("Waiting for flushes\n");
356 DPRINT("Flushes have completed\n");
357}
358
359VOID
360NTAPI
362{
363 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension = (PVOID)DeviceObjectExtension;
364 PAGED_CODE();
365
366 /* Initialize the power flags */
367 DeviceExtension->PowerFlags = PowerSystemUnspecified & 0xF;
368 DeviceExtension->PowerFlags |= ((PowerDeviceUnspecified << 4) & 0xF0);
369
370 /* The device object is not on drugs yet */
371 DeviceExtension->Dope = NULL;
372}
373
374/* PUBLIC FUNCTIONS **********************************************************/
375
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define UNIMPLEMENTED
Definition: debug.h:115
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GENERIC_READ
Definition: compat.h:135
#define FILE_SHARE_READ
Definition: compat.h:136
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_Must_inspect_result_ _Out_ PHANDLE VolumeHandle
Definition: fltkernel.h:2283
#define FILE_OPEN
Definition: from_kernel.h:54
Status
Definition: gdiplustypes.h:25
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
if(dx< 0)
Definition: linetemp.h:194
UNICODE_STRING Volume
Definition: fltkernel.h:1172
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
#define KEY_READ
Definition: nt_native.h:1023
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
#define FILE_READ_ONLY_DEVICE
Definition: nt_native.h:808
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
#define GENERIC_WRITE
Definition: nt_native.h:90
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
#define IoGetDevObjExtension(DeviceObject)
Definition: io.h:129
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
@ PowerSystemUnspecified
Definition: ntpoapi.h:35
@ PowerDeviceUnspecified
Definition: ntpoapi.h:48
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
long LONG
Definition: pedump.c:60
struct _DEVICE_OBJECT_POWER_EXTENSION * PDEVICE_OBJECT_POWER_EXTENSION
VOID NTAPI PoInitializeDeviceObject(IN OUT PDEVOBJ_EXTENSION DeviceObjectExtension)
Definition: povolume.c:361
LIST_ENTRY PopVolumeDevices
Definition: povolume.c:27
struct _POP_FLUSH_VOLUME * PPOP_FLUSH_VOLUME
VOID NTAPI PoVolumeDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: povolume.c:81
ULONG PopFlushPolicy
Definition: povolume.c:24
KSPIN_LOCK PopDopeGlobalLock
Definition: povolume.c:28
struct _POP_FLUSH_VOLUME POP_FLUSH_VOLUME
VOID NTAPI PopFlushVolumeWorker(IN PVOID Context)
Definition: povolume.c:148
VOID NTAPI PopFlushVolumes(IN BOOLEAN ShuttingDown)
Definition: povolume.c:227
KGUARDED_MUTEX PopVolumeLock
Definition: povolume.c:26
VOID NTAPI PoRemoveVolumeDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: povolume.c:103
PDEVICE_OBJECT_POWER_EXTENSION NTAPI PopGetDope(IN PDEVICE_OBJECT DeviceObject)
Definition: povolume.c:34
#define DPRINT
Definition: sndvol32.h:71
DEVICE_POWER_STATE State
Definition: po.h:264
PDEVICE_OBJECT DeviceObject
Definition: po.h:262
struct _DEVICE_OBJECT_POWER_EXTENSION * Dope
Definition: iotypes.h:970
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY List
Definition: povolume.c:19
#define TAG_PO_DOPE
Definition: tag.h:129
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:415
unsigned char UCHAR
Definition: xmlstorage.h:181
NTSYSAPI NTSTATUS NTAPI ZwFlushBuffersFile(_In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock)