- Implement IopInitailizeVpbForMount for the purpose of setting up the VPB for a...
authorAlex Ionescu <aionescu@gmail.com>
Sun, 2 Jul 2006 06:11:19 +0000 (06:11 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sun, 2 Jul 2006 06:11:19 +0000 (06:11 +0000)
- Fix a bug which was causing us to incorrectly unlock the device if it was already locked by the caller isntead of by IopMountVolume.
- When loading the file system, make sure to unlock the device object if we had locked it in IopMountVolume, as well as to re-lock it afterwards. Also handle a potential race condition due to this unloacking, in which the VPB might've become mounted behind our back, and simply return success if this happened.

svn path=/trunk/; revision=22764

reactos/ntoskrnl/io/iomgr/volume.c

index bad945b..a555d0a 100644 (file)
@@ -132,6 +132,39 @@ IopReferenceVpbForVerify(IN PDEVICE_OBJECT DeviceObject,
     return Result;
 }
 
+PVPB
+NTAPI
+IopInitializeVpbForMount(IN PDEVICE_OBJECT DeviceObject,
+                         IN PDEVICE_OBJECT AttachedDeviceObject,
+                         IN BOOLEAN Raw)
+{
+    KIRQL OldIrql;
+    PVPB Vpb;
+
+    /* Lock the VPBs */
+    IoAcquireVpbSpinLock(&OldIrql);
+    Vpb = DeviceObject->Vpb;
+
+    /* Set the VPB as mounted and possibly raw */
+    Vpb->Flags |= VPB_MOUNTED | Raw ? VPB_RAW_MOUNT : 0;
+
+    /* Set the stack size */
+    Vpb->DeviceObject->StackSize = AttachedDeviceObject->StackSize;
+
+    /* Add one for the FS Driver */
+    Vpb->DeviceObject->StackSize++;
+
+    /* Set the VPB in the device extension */
+    IoGetDevObjExtension(Vpb->DeviceObject)->Vpb = Vpb;
+
+    /* Reference it */
+    Vpb->ReferenceCount++;
+
+    /* Release the VPB lock and return it */
+    IoReleaseVpbSpinLock(OldIrql);
+    return Vpb;
+}
+
 VOID
 NTAPI
 IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject,
@@ -283,7 +316,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
     PIRP Irp;
     PIO_STACK_LOCATION StackPtr;
     PLIST_ENTRY FsList, ListEntry;
-    PDEVICE_OBJECT DevObject;
+    PDEVICE_OBJECT ParentFsDeviceObject;
     PDEVICE_OBJECT AttachedDeviceObject = DeviceObject;
     PDEVICE_OBJECT FileSystemDeviceObject;
     LIST_ENTRY LocalList;
@@ -376,6 +409,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
             FileSystemDeviceObject = CONTAINING_RECORD(ListEntry,
                                                        DEVICE_OBJECT,
                                                        Queue.ListEntry);
+            ParentFsDeviceObject = FileSystemDeviceObject;
 
             /*
              * If this file system device is attached to some other device,
@@ -434,26 +468,69 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
                 Status = IoStatusBlock.Status;
             }
 
-            switch (Status)
+            /* Check if mounting was successful */
+            if (NT_SUCCESS(Status))
+            {
+                /* Mount the VPB */
+                *Vpb = IopInitializeVpbForMount(DeviceObject,
+                                                AttachedDeviceObject,
+                                                (DeviceObject->Vpb->Flags &
+                                                 VPB_RAW_MOUNT));
+            }
+            else
             {
-                case STATUS_FS_DRIVER_REQUIRED:
-                    DevObject = FileSystemDeviceObject;
+                if (Status == STATUS_FS_DRIVER_REQUIRED)
+                {
+                    /* We need to release the lock */
                     ExReleaseResourceLite(&FileSystemListLock);
-                    IopLoadFileSystem(DevObject);
-                    ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
+
+                    /* Release the device lock if we're holding it */
+                    if (!DeviceIsLocked)
+                    {
+                        KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE);
+                    }
+
+                    /* Load the FS */
+                    IopLoadFileSystem(ParentFsDeviceObject);
+
+                    /* Check if the device isn't already locked */
+                    if (!DeviceIsLocked)
+                    {
+                        /* Lock it ourselves */
+                        DPRINT1("Waiting\n");
+                        Status = KeWaitForSingleObject(&DeviceObject->
+                                                       DeviceLock,
+                                                       Executive,
+                                                       KeGetPreviousMode(),
+                                                       Alertable,
+                                                       NULL);
+                        if ((Status == STATUS_ALERTED) ||
+                            (Status == STATUS_USER_APC))
+                        {
+                            /* Don't mount if we were interrupted */
+                            ObDereferenceObject(AttachedDeviceObject);
+                            return Status;
+                        }
+                    }
+
+                    /* Reacquire the lock */
+                    ExAcquireResourceSharedLite(&FileSystemListLock, TRUE);
+
+                    /* When we released the lock, make sure nobody beat us */
+                    if (DeviceObject->Vpb->Flags & VPB_MOUNTED)
+                    {
+                        /* Someone did, break out */
+                        Status = STATUS_SUCCESS;
+                        break;
+                    }
+
+                    /* Start over by setting a failure */
+                    Status = STATUS_UNRECOGNIZED_VOLUME;
+
                     /* We need to setup a local list to pickup where we left */
                     LocalList.Flink = FsList->Flink;
                     ListEntry = &LocalList;
-                    break;
-
-                case STATUS_SUCCESS:
-                    DeviceObject->Vpb->Flags = DeviceObject->Vpb->Flags |
-                                               VPB_MOUNTED;
-
-                case STATUS_UNRECOGNIZED_VOLUME:
-                default:
-                    /* do nothing */
-                    break;
+                }
             }
 
             /* Go to the next FS entry */
@@ -479,7 +556,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
     KeLeaveCriticalRegion();
 
     /* Release the device lock if we're holding it */
-    if (DeviceIsLocked) KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE);
+    if (!DeviceIsLocked) KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE);
 
     /* Check if we failed to mount the boot partition */
     if ((!NT_SUCCESS(Status)) &&