Author: ion
Date: Sun Jul 2 05:35:45 2006
New Revision: 22756
URL:
http://svn.reactos.org/svn/reactos?rev=22756&view=rev
Log:
- Implement some functions to handle VPB Referencing/Dereferencing.
- IoVerifyVolume:
- Send the IRP to the base FSD, in case the current FSD is an attachee
- Set correct flags in the IRP to notify that this is a mount operation using PAGING I/O
semantics.
- Don't ignore AllowRawMount parameter.
- We want to mount the File System on *FAILURE*, not on SUCCESS!
- Add reference/dereferencing to the VPB.
Modified:
trunk/reactos/ntoskrnl/io/iomgr/volume.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/volume.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/volume.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/volume.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/volume.c Sun Jul 2 05:35:45 2006
@@ -83,6 +83,60 @@
/* Link it to the Device Object */
DeviceObject->Vpb = Vpb;
return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+IopDereferenceVpb(IN PVPB Vpb)
+{
+ KIRQL OldIrql;
+
+ /* Lock the VPBs and decrease references */
+ IoAcquireVpbSpinLock(&OldIrql);
+ Vpb->ReferenceCount--;
+
+ /* Check if we're out of references */
+ if (!Vpb->ReferenceCount)
+ {
+ /* FIXME: IMPLEMENT CLEANUP! */
+ KEBUGCHECK(0);
+ }
+
+ /* Release VPB lock */
+ IoReleaseVpbSpinLock(OldIrql);
+}
+
+BOOLEAN
+NTAPI
+IopReferenceVpbForVerify(IN PDEVICE_OBJECT DeviceObject,
+ OUT PDEVICE_OBJECT *FileSystemObject,
+ OUT PVPB *Vpb)
+{
+ KIRQL OldIrql;
+ PVPB LocalVpb;
+ BOOLEAN Result = FALSE;
+
+ /* Lock the VPBs and assume failure */
+ IoAcquireVpbSpinLock(&OldIrql);
+ *Vpb = NULL;
+ *FileSystemObject = NULL;
+
+ /* Get the VPB and make sure it's mounted */
+ LocalVpb = DeviceObject->Vpb;
+ if ((LocalVpb) && (LocalVpb->Flags & VPB_MOUNTED))
+ {
+ /* Return it */
+ *Vpb = LocalVpb;
+ *FileSystemObject = LocalVpb->DeviceObject;
+
+ /* Reference it */
+ LocalVpb->ReferenceCount++;
+ Result = TRUE;
+ }
+
+ /* Release the VPB lock and return status */
+ IoReleaseVpbSpinLock(OldIrql);
+ return Result;
}
VOID
@@ -335,73 +389,88 @@
PIO_STACK_LOCATION StackPtr;
KEVENT Event;
PIRP Irp;
- NTSTATUS Status = STATUS_SUCCESS;
- PDEVICE_OBJECT DevObject;
- PVPB NewVpb;
-
+ NTSTATUS Status = STATUS_SUCCESS, VpbStatus;
+ PDEVICE_OBJECT FileSystemDeviceObject;
+ PVPB Vpb, NewVpb;
+ BOOLEAN WasNotMounted = TRUE;
+
+ /* Wait on the device lock */
KeWaitForSingleObject(&DeviceObject->DeviceLock,
Executive,
KernelMode,
FALSE,
NULL);
- if (DeviceObject->Vpb->Flags & VPB_MOUNTED)
- {
- /* Issue verify request to the FSD */
- DevObject = DeviceObject->Vpb->DeviceObject;
-
+ /* Reference the VPB */
+ if (IopReferenceVpbForVerify(DeviceObject, &FileSystemDeviceObject, &Vpb))
+ {
+ /* Initialize the event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoAllocateIrp(DevObject->StackSize, TRUE);
- if (Irp==NULL)
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
-
+ /* Find the actual File System DO */
+ WasNotMounted = FALSE;
+ FileSystemDeviceObject = DeviceObject->Vpb->DeviceObject;
+ while (FileSystemDeviceObject->AttachedDevice)
+ {
+ /* Go to the next one */
+ FileSystemDeviceObject = FileSystemDeviceObject->AttachedDevice;
+ }
+
+ /* Allocate the IRP */
+ Irp = IoAllocateIrp(FileSystemDeviceObject->StackSize, FALSE);
+ if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Set it up */
Irp->UserIosb = &IoStatusBlock;
Irp->UserEvent = &Event;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
+ Irp->Flags = IRP_MOUNT_COMPLETION | IRP_SYNCHRONOUS_PAGING_IO;
+ Irp->RequestorMode = KernelMode;
+
+ /* Get the I/O Stack location and set it */
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
StackPtr->MinorFunction = IRP_MN_VERIFY_VOLUME;
- StackPtr->Flags = 0;
- StackPtr->Control = 0;
- StackPtr->DeviceObject = DevObject;
- StackPtr->FileObject = NULL;
- StackPtr->CompletionRoutine = NULL;
-
- StackPtr->Parameters.VerifyVolume.Vpb = DeviceObject->Vpb;
- StackPtr->Parameters.VerifyVolume.DeviceObject = DeviceObject;
-
- Status = IoCallDriver(DevObject, Irp);
- if (Status==STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
+ StackPtr->Flags = AllowRawMount ? SL_ALLOW_RAW_MOUNT : 0;
+ StackPtr->Parameters.VerifyVolume.Vpb = Vpb;
+ StackPtr->Parameters.VerifyVolume.DeviceObject =
+ DeviceObject->Vpb->DeviceObject;
+
+ /* Call the driver */
+ Status = IoCallDriver(FileSystemDeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait on it */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
- if (NT_SUCCESS(Status))
- {
- KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE);
- return(STATUS_SUCCESS);
- }
- }
-
- if (Status == STATUS_WRONG_VOLUME)
- {
- /* Clean existing VPB. This unmounts the filesystem. */
- DPRINT("Wrong volume!\n");
-
- DeviceObject->Vpb->DeviceObject = NULL;
- DeviceObject->Vpb->Flags &= ~VPB_MOUNTED;
- }
-
- /* Start mount sequence */
- Status = IopMountVolume(DeviceObject, AllowRawMount, TRUE, FALSE, &NewVpb);
-
+ /* Dereference the VPB */
+ IopDereferenceVpb(Vpb);
+ }
+
+ /* Check if we had the wrong volume or didn't mount at all */
+ if ((Status == STATUS_WRONG_VOLUME) || (WasNotMounted))
+ {
+ /* Create a VPB */
+ VpbStatus = IopCreateVpb(DeviceObject);
+ if (NT_SUCCESS(VpbStatus))
+ {
+ /* Mount it */
+ VpbStatus = IopMountVolume(DeviceObject,
+ AllowRawMount,
+ TRUE,
+ FALSE,
+ &NewVpb);
+ }
+
+ /* If we failed, remove the verify flag */
+ if (!NT_SUCCESS(VpbStatus)) DeviceObject->Flags &= ~DO_VERIFY_VOLUME;
+ }
+
+ /* Signal the device lock and return */
KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE);
- return(Status);
+ return Status;
}
/*