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; }
/*