- 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.

svn path=/trunk/; revision=22756
This commit is contained in:
Alex Ionescu 2006-07-02 01:35:45 +00:00
parent 042e74885b
commit fe8b3cfda1

View file

@ -85,6 +85,60 @@ IopCreateVpb(IN PDEVICE_OBJECT DeviceObject)
return STATUS_SUCCESS; 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 VOID
NTAPI NTAPI
IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject, IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject,
@ -335,73 +389,88 @@ IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
PIO_STACK_LOCATION StackPtr; PIO_STACK_LOCATION StackPtr;
KEVENT Event; KEVENT Event;
PIRP Irp; PIRP Irp;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS, VpbStatus;
PDEVICE_OBJECT DevObject; PDEVICE_OBJECT FileSystemDeviceObject;
PVPB NewVpb; PVPB Vpb, NewVpb;
BOOLEAN WasNotMounted = TRUE;
/* Wait on the device lock */
KeWaitForSingleObject(&DeviceObject->DeviceLock, KeWaitForSingleObject(&DeviceObject->DeviceLock,
Executive, Executive,
KernelMode, KernelMode,
FALSE, FALSE,
NULL); NULL);
if (DeviceObject->Vpb->Flags & VPB_MOUNTED) /* Reference the VPB */
if (IopReferenceVpbForVerify(DeviceObject, &FileSystemDeviceObject, &Vpb))
{ {
/* Issue verify request to the FSD */ /* Initialize the event */
DevObject = DeviceObject->Vpb->DeviceObject;
KeInitializeEvent(&Event, NotificationEvent, FALSE); KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoAllocateIrp(DevObject->StackSize, TRUE); /* Find the actual File System DO */
if (Irp==NULL) WasNotMounted = FALSE;
FileSystemDeviceObject = DeviceObject->Vpb->DeviceObject;
while (FileSystemDeviceObject->AttachedDevice)
{ {
return(STATUS_INSUFFICIENT_RESOURCES); /* 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->UserIosb = &IoStatusBlock;
Irp->UserEvent = &Event; Irp->UserEvent = &Event;
Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 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 = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
StackPtr->MinorFunction = IRP_MN_VERIFY_VOLUME; StackPtr->MinorFunction = IRP_MN_VERIFY_VOLUME;
StackPtr->Flags = 0; StackPtr->Flags = AllowRawMount ? SL_ALLOW_RAW_MOUNT : 0;
StackPtr->Control = 0; StackPtr->Parameters.VerifyVolume.Vpb = Vpb;
StackPtr->DeviceObject = DevObject; StackPtr->Parameters.VerifyVolume.DeviceObject =
StackPtr->FileObject = NULL; DeviceObject->Vpb->DeviceObject;
StackPtr->CompletionRoutine = NULL;
StackPtr->Parameters.VerifyVolume.Vpb = DeviceObject->Vpb; /* Call the driver */
StackPtr->Parameters.VerifyVolume.DeviceObject = DeviceObject; Status = IoCallDriver(FileSystemDeviceObject, Irp);
if (Status == STATUS_PENDING)
Status = IoCallDriver(DevObject, Irp);
if (Status==STATUS_PENDING)
{ {
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL); /* Wait on it */
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status; Status = IoStatusBlock.Status;
} }
if (NT_SUCCESS(Status)) /* Dereference the VPB */
{ IopDereferenceVpb(Vpb);
KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE);
return(STATUS_SUCCESS);
}
} }
if (Status == STATUS_WRONG_VOLUME) /* Check if we had the wrong volume or didn't mount at all */
if ((Status == STATUS_WRONG_VOLUME) || (WasNotMounted))
{ {
/* Clean existing VPB. This unmounts the filesystem. */ /* Create a VPB */
DPRINT("Wrong volume!\n"); VpbStatus = IopCreateVpb(DeviceObject);
if (NT_SUCCESS(VpbStatus))
{
/* Mount it */
VpbStatus = IopMountVolume(DeviceObject,
AllowRawMount,
TRUE,
FALSE,
&NewVpb);
}
DeviceObject->Vpb->DeviceObject = NULL; /* If we failed, remove the verify flag */
DeviceObject->Vpb->Flags &= ~VPB_MOUNTED; if (!NT_SUCCESS(VpbStatus)) DeviceObject->Flags &= ~DO_VERIFY_VOLUME;
} }
/* Start mount sequence */ /* Signal the device lock and return */
Status = IopMountVolume(DeviceObject, AllowRawMount, TRUE, FALSE, &NewVpb);
KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE); KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE);
return(Status); return Status;
} }
/* /*