Author: pschweitzer
Date: Fri Oct 31 11:17:43 2014
New Revision: 65141
URL:
http://svn.reactos.org/svn/reactos?rev=65141&view=rev
Log:
[NTOSKRNL]
Some fixes and missing implementations in RawFS:
- Remove some magic values for VCB state
- Add a local VPB in our VCB. This will allow diverting the IO VPB with ours in case of
dismount (and thus, will fix dismount)
- Implement support for said VPB in both RawCheckForDismount() and RawInitializeVcb()
- Now, dismount is handled in RawCheckForDismount() directly, and not in functions calling
it
- Handle streams in RawClose
- Handle VCB being dismounted in RawCreate()
- Handle dismount also in RawCleanup() (not only in RawClose())
This fixes volume locking and dismounting in RawFS. And thus, allows FS swap in case of
raw volume formating in first stage :-).
More to follow!
Modified:
trunk/reactos/ntoskrnl/io/iomgr/rawfs.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/rawfs.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/rawfs.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/rawfs.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/rawfs.c [iso-8859-1] Fri Oct 31 11:17:43 2014
@@ -20,6 +20,7 @@
USHORT NodeByteSize;
PDEVICE_OBJECT TargetDeviceObject;
PVPB Vpb;
+ PVPB LocalVpb;
ULONG VcbState;
KMUTEX Mutex;
CLONG OpenCount;
@@ -34,19 +35,26 @@
VCB Vcb;
} VOLUME_DEVICE_OBJECT, *PVOLUME_DEVICE_OBJECT;
+#define VCB_STATE_LOCKED 0x00000001
+#define VCB_STATE_DISMOUNTED 0x00000002
+
/* GLOBALS *******************************************************************/
PDEVICE_OBJECT RawDiskDeviceObject, RawCdromDeviceObject, RawTapeDeviceObject;
/* FUNCTIONS *****************************************************************/
-VOID
+NTSTATUS
NTAPI
RawInitializeVcb(IN OUT PVCB Vcb,
IN PDEVICE_OBJECT TargetDeviceObject,
IN PVPB Vpb)
{
- PAGED_CODE();
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ DPRINT("RawInitializeVcb(%p, %p, %p)\n", Vcb, TargetDeviceObject, Vpb);
/* Clear it */
RtlZeroMemory(Vcb, sizeof(VCB));
@@ -57,6 +65,14 @@
/* Initialize the lock */
KeInitializeMutex(&Vcb->Mutex, 0);
+
+ Vcb->LocalVpb = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), ' waR');
+ if (Vcb->LocalVpb == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ return Status;
}
BOOLEAN
@@ -68,6 +84,10 @@
PVPB Vpb;
BOOLEAN Delete;
+ DPRINT("RawCheckForDismount(%p, %lu)\n", Vcb, CreateOperation);
+
+ ASSERT(KeReadStateMutant(&Vcb->Mutex) == 0);
+
/* Lock VPB */
IoAcquireVpbSpinLock(&OldIrql);
@@ -75,6 +95,19 @@
Vpb = Vcb->Vpb;
if (Vcb->Vpb->ReferenceCount != CreateOperation)
{
+ /* Copy the VPB to our local own to prepare later dismount */
+ if (Vcb->LocalVpb != NULL)
+ {
+ RtlZeroMemory(Vcb->LocalVpb, sizeof(VPB));
+ Vcb->LocalVpb->Type = IO_TYPE_VPB;
+ Vcb->LocalVpb->Size = sizeof(VPB);
+ Vcb->LocalVpb->RealDevice = Vcb->Vpb->RealDevice;
+ Vcb->LocalVpb->DeviceObject = NULL;
+ Vcb->LocalVpb->Flags = Vcb->Vpb->Flags & VPB_REMOVE_PENDING;
+ Vcb->Vpb->RealDevice->Vpb = Vcb->LocalVpb;
+ Vcb->LocalVpb = NULL;
+ Vcb->Vpb->Flags |= VPB_PERSISTENT;
+ }
/* Don't do anything */
Delete = FALSE;
}
@@ -93,6 +126,47 @@
/* Release lock and return status */
IoReleaseVpbSpinLock(OldIrql);
+
+ /* If we were to delete, delete volume */
+ if (Delete)
+ {
+ PVPB DelVpb;
+
+ /* Release our Vcb lock to be able delete us */
+ KeReleaseMutex(&Vcb->Mutex, 0);
+
+ /* If we have a local VPB, we'll have to delete it
+ * but we won't dismount us - something went bad before
+ */
+ if (Vcb->LocalVpb)
+ {
+ DelVpb = Vcb->LocalVpb;
+ }
+ /* Otherwise, dismount our device if possible */
+ else
+ {
+ if (Vcb->Vpb->ReferenceCount)
+ {
+ ObfDereferenceObject(Vcb->TargetDeviceObject);
+ IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb,
+ VOLUME_DEVICE_OBJECT,
+ Vcb));
+ return Delete;
+ }
+
+ DelVpb = Vcb->Vpb;
+ }
+
+ /* Delete any of the available VPB and dismount */
+ ExFreePool(DelVpb);
+ ObfDereferenceObject(Vcb->TargetDeviceObject);
+ IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb,
+ VOLUME_DEVICE_OBJECT,
+ Vcb));
+
+ return Delete;
+ }
+
return Delete;
}
@@ -103,6 +177,8 @@
IN PVOID Context)
{
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ DPRINT("RawCompletionRoutine(%p, %p, %p)\n", DeviceObject, Irp, Context);
/* Check if this was a valid sync R/W request */
if (((IoStackLocation->MajorFunction == IRP_MJ_READ) ||
@@ -128,8 +204,17 @@
IN PIO_STACK_LOCATION IoStackLocation)
{
NTSTATUS Status;
- BOOLEAN Deleted = FALSE;
- PAGED_CODE();
+ PAGED_CODE();
+
+ DPRINT("RawClose(%p, %p, %p)\n", Vcb, Irp, IoStackLocation);
+
+ /* If its a stream, not much to do */
+ if (IoStackLocation->FileObject->Flags & FO_STREAM_FILE)
+ {
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ return STATUS_SUCCESS;
+ }
/* Make sure we can clean up */
Status = KeWaitForSingleObject(&Vcb->Mutex,
@@ -141,16 +226,9 @@
/* Decrease the open count and check if this is a dismount */
Vcb->OpenCount--;
- if (!Vcb->OpenCount) Deleted = RawCheckForDismount(Vcb, FALSE);
-
- /* Check if we should delete the device */
- KeReleaseMutex(&Vcb->Mutex, FALSE);
- if (Deleted)
- {
- /* Delete it */
- IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb,
- VOLUME_DEVICE_OBJECT,
- Vcb));
+ if (!Vcb->OpenCount || !RawCheckForDismount(Vcb, FALSE))
+ {
+ KeReleaseMutex(&Vcb->Mutex, FALSE);
}
/* Complete the request */
@@ -166,10 +244,12 @@
IN PIO_STACK_LOCATION IoStackLocation)
{
NTSTATUS Status;
- BOOLEAN Deleted = FALSE;
USHORT ShareAccess;
ACCESS_MASK DesiredAccess;
- PAGED_CODE();
+ BOOLEAN Deleted = FALSE;
+ PAGED_CODE();
+
+ DPRINT("RawCreate(%p, %p, %p)\n", Vcb, Irp, IoStackLocation);
/* Make sure we can clean up */
Status = KeWaitForSingleObject(&Vcb->Mutex,
@@ -186,10 +266,16 @@
(!(IoStackLocation->Parameters.Create.Options & FILE_DIRECTORY_FILE)))
{
/* Make sure the VCB isn't locked */
- if (Vcb->VcbState & 1)
+ if (Vcb->VcbState & VCB_STATE_LOCKED)
{
/* Refuse the operation */
Status = STATUS_ACCESS_DENIED;
+ Irp->IoStatus.Information = 0;
+ }
+ else if (Vcb->VcbState & VCB_STATE_DISMOUNTED)
+ {
+ /* Refuse the operation */
+ Status = STATUS_VOLUME_DISMOUNTED;
Irp->IoStatus.Information = 0;
}
else
@@ -247,23 +333,19 @@
if (!(NT_SUCCESS(Status)) && !(Vcb->OpenCount))
{
/* Check if we can dismount the device */
- Deleted = RawCheckForDismount(Vcb, FALSE);
- }
-
- /* Check if we should delete the device */
- KeReleaseMutex(&Vcb->Mutex, FALSE);
- if (Deleted)
- {
- /* Delete it */
- IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb,
- VOLUME_DEVICE_OBJECT,
- Vcb));
+ Deleted = RawCheckForDismount(Vcb, TRUE);
+ }
+
+ /* In case of deletion, the mutex is already released */
+ if (!Deleted)
+ {
+ KeReleaseMutex(&Vcb->Mutex, FALSE);
}
/* Complete the request */
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
- return STATUS_SUCCESS;
+ return Status;
}
NTSTATUS
@@ -274,6 +356,8 @@
{
NTSTATUS Status;
PAGED_CODE();
+
+ DPRINT("RawReadWriteDeviceControl(%p, %p, %p)\n", Vcb, Irp,
IoStackLocation);
/* Don't do anything if the request was 0 bytes */
if (((IoStackLocation->MajorFunction == IRP_MJ_READ) ||
@@ -314,6 +398,8 @@
PVOLUME_DEVICE_OBJECT Volume;
PFILE_OBJECT FileObject = NULL;
PAGED_CODE();
+
+ DPRINT("RawMountVolume(%p)\n", IoStackLocation);
/* Remember our owner */
DeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject;
@@ -336,9 +422,14 @@
AlignmentRequirement);
/* Setup the VCB */
- RawInitializeVcb(&Volume->Vcb,
- IoStackLocation->Parameters.MountVolume.DeviceObject,
- IoStackLocation->Parameters.MountVolume.Vpb);
+ Status = RawInitializeVcb(&Volume->Vcb,
+ IoStackLocation->Parameters.MountVolume.DeviceObject,
+ IoStackLocation->Parameters.MountVolume.Vpb);
+ if (!NT_SUCCESS(Status))
+ {
+ IoDeleteDevice((PDEVICE_OBJECT)Volume);
+ return Status;
+ }
/* Set dummy label and serial number */
Volume->Vcb.Vpb->SerialNumber = 0xFFFFFFFF;
@@ -390,6 +481,8 @@
{
NTSTATUS Status;
PAGED_CODE();
+
+ DPRINT("RawUserFsCtrl(%p, %p)\n", IoStackLocation, Vcb);
/* Lock the device */
Status = KeWaitForSingleObject(&Vcb->Mutex,
@@ -502,6 +595,8 @@
NTSTATUS Status;
PAGED_CODE();
+ DPRINT("RawFileSystemControl(%p, %p, %p)\n", Vcb, Irp, IoStackLocation);
+
/* Check the kinds of FSCTLs that we support */
switch (IoStackLocation->MinorFunction)
{
@@ -563,6 +658,8 @@
PFILE_POSITION_INFORMATION Buffer;
PAGED_CODE();
+ DPRINT("RawQueryInformation(%p, %p, %p)\n", Vcb, Irp, IoStackLocation);
+
/* Get information from the IRP */
Length = &IoStackLocation->Parameters.QueryFile.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
@@ -608,6 +705,8 @@
PDEVICE_OBJECT DeviceObject;
PAGED_CODE();
+ DPRINT("RawSetInformation(%p, %p, %p)\n", Vcb, Irp, IoStackLocation);
+
/* Get information from the IRP */
Buffer = Irp->AssociatedIrp.SystemBuffer;
@@ -649,6 +748,8 @@
IN OUT PULONG Length)
{
PAGED_CODE();
+
+ DPRINT("RawQueryFsVolumeInfo(%p, %p, %p)\n", Vcb, Buffer, Length);
/* Clear the buffer and stub it out */
RtlZeroMemory( Buffer, sizeof(FILE_FS_VOLUME_INFORMATION));
@@ -676,6 +777,8 @@
PARTITION_INFORMATION PartitionInformation;
BOOLEAN DiskHasPartitions;
PAGED_CODE();
+
+ DPRINT("RawQueryFsSizeInfo(%p, %p, %p)\n", Vcb, Buffer, Length);
/* Validate the buffer */
if (*Length < sizeof(FILE_FS_SIZE_INFORMATION))
@@ -806,6 +909,8 @@
{
PAGED_CODE();
+ DPRINT("RawQueryFsDeviceInfo(%p, %p, %p)\n", Vcb, Buffer, Length);
+
/* Validate buffer */
if (*Length < sizeof(FILE_FS_DEVICE_INFORMATION))
{
@@ -832,6 +937,8 @@
const WCHAR szRawFSName[] = L"RAW";
ULONG ReturnLength;
PAGED_CODE();
+
+ DPRINT("RawQueryFsAttributeInfo(%p, %p, %p)\n", Vcb, Buffer, Length);
/* Check if the buffer is large enough for our name ("RAW") */
ReturnLength = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION,
@@ -859,6 +966,8 @@
ULONG Length;
PVOID Buffer;
PAGED_CODE();
+
+ DPRINT("RawQueryVolumeInformation(%p, %p, %p)\n", Vcb, Irp,
IoStackLocation);
/* Get IRP Data */
Length = IoStackLocation->Parameters.QueryVolume.Length;
@@ -915,6 +1024,8 @@
{
NTSTATUS Status;
PAGED_CODE();
+
+ DPRINT("RawCleanup(%p, %p, %p)\n", Vcb, Irp, IoStackLocation);
/* Make sure we can clean up */
Status = KeWaitForSingleObject(&Vcb->Mutex,
@@ -924,8 +1035,16 @@
NULL);
ASSERT(NT_SUCCESS(Status));
- /* Remove shared access and complete the request */
+ /* Remove shared access */
IoRemoveShareAccess(IoStackLocation->FileObject, &Vcb->ShareAccess);
+
+ /* Check if we're to dismount */
+ if (Vcb->VcbState & VCB_STATE_DISMOUNTED)
+ {
+ ASSERT(Vcb->OpenCount == 1);
+ RawCheckForDismount(Vcb, FALSE);
+ }
+
KeReleaseMutex(&Vcb->Mutex, FALSE);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
@@ -941,6 +1060,8 @@
PIO_STACK_LOCATION IoStackLocation;
PVCB Vcb;
PAGED_CODE();
+
+ DPRINT("RawDispatch(%p, %p)\n", DeviceObject, Irp);
/* Get the stack location */
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);