[NTOSKRNL]

- renamed Io volumes global to match Windows names (in case of debug)
- renamed IopDereferenceVpb() to IopDereferenceVpbAndFree(), IopReferenceVpbForVerify() to IopReferenceVerifyVpb(), IopInitializeVpbForMount() to IopMountInitializeVpb(), IopLoadFileSystem() to IopLoadFileSystemDriver()
- implemented IopDecrementDeviceObjectHandleCount(), IopInterlockedIncrementUlong(), IopInterlockedDecrementUlong(), IopNotifyAlreadyRegisteredFileSystems() and IoEnumerateRegisteredFiltersList()
- halfplemented IopDecrementDeviceObjectRef()
- implemented check for already registrered notification in IoRegisterFsRegistrationChange()
- implemented sending notifications for already registered drivers to registrant in IoRegisterFsRegistrationChange()
- implemented VPB freeing in IopDereferenceVpbAndFree()
- acquire Io volumes lists once and forever for system shutdown, instead of keeping acquiring and releasing
- reference device object in IopShutdownBaseFileSystems() before sending it the shutdown IRP. To ensure to keep it valid till the end
- added a FS driver registration operations counter
- use this counter to handle failed mounts
- fixed: release locks before calling driver for mounting and reacquire them after
- fixed check for boot partition failure (and associated bugcheck): check we are in boot phase 0 or 1
- simplified lock process by using only one lock (ie removed mutex). Also use only critical region where needed
- fixed: ensure that locks are properly released when quitting a function
- fixed wrong return in IopCreateVpb()
- minor fixes around

svn path=/trunk/; revision=52065
This commit is contained in:
Pierre Schweitzer 2011-06-02 17:43:44 +00:00
parent 33a2b85a57
commit 69764dd21a
5 changed files with 401 additions and 119 deletions

View file

@ -838,7 +838,7 @@ IopCreateVpb(
VOID VOID
NTAPI NTAPI
IopDereferenceVpb( IopDereferenceVpbAndFree(
IN PVPB Vpb IN PVPB Vpb
); );
@ -869,8 +869,15 @@ IopDereferenceDeviceObject(
NTSTATUS NTSTATUS
NTAPI NTAPI
IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject, IoGetRelatedTargetDevice(
OUT PDEVICE_OBJECT *DeviceObject IN PFILE_OBJECT FileObject,
OUT PDEVICE_OBJECT *DeviceObject
);
VOID
NTAPI
IopUnloadDevice(
IN PDEVICE_OBJECT DeviceObject
); );
// //

View file

@ -19,9 +19,10 @@
ULONG IopDeviceObjectNumber = 0; ULONG IopDeviceObjectNumber = 0;
LIST_ENTRY ShutdownListHead, LastChanceShutdownListHead; LIST_ENTRY ShutdownListHead, LastChanceShutdownListHead;
KSPIN_LOCK ShutdownListLock; KSPIN_LOCK ShutdownListLock;
extern LIST_ENTRY IopDiskFsListHead; extern LIST_ENTRY IopDiskFileSystemQueueHead;
extern LIST_ENTRY IopCdRomFsListHead; extern LIST_ENTRY IopCdRomFileSystemQueueHead;
extern LIST_ENTRY IopTapeFsListHead; extern LIST_ENTRY IopTapeFileSystemQueueHead;
extern ERESOURCE IopDatabaseResource;
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
@ -187,14 +188,17 @@ IoShutdownSystem(IN ULONG Phase)
} }
else if (Phase == 1) else if (Phase == 1)
{ {
/* Acquire resource forever */
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
/* Shutdown disk file systems */ /* Shutdown disk file systems */
IopShutdownBaseFileSystems(&IopDiskFsListHead); IopShutdownBaseFileSystems(&IopDiskFileSystemQueueHead);
/* Shutdown cdrom file systems */ /* Shutdown cdrom file systems */
IopShutdownBaseFileSystems(&IopCdRomFsListHead); IopShutdownBaseFileSystems(&IopCdRomFileSystemQueueHead);
/* Shutdown tape filesystems */ /* Shutdown tape filesystems */
IopShutdownBaseFileSystems(&IopTapeFsListHead); IopShutdownBaseFileSystems(&IopTapeFileSystemQueueHead);
/* Loop last-chance shutdown notifications */ /* Loop last-chance shutdown notifications */
ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead, ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead,

View file

@ -479,7 +479,7 @@ IopParseDevice(IN PVOID ParseObject,
{ {
/* Dereference the device and VPB, then fail */ /* Dereference the device and VPB, then fail */
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
if (Vpb) IopDereferenceVpb(Vpb); if (Vpb) IopDereferenceVpbAndFree(Vpb);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
@ -577,7 +577,7 @@ IopParseDevice(IN PVOID ParseObject,
/* Dereference the device and VPB */ /* Dereference the device and VPB */
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
if (Vpb) IopDereferenceVpb(Vpb); if (Vpb) IopDereferenceVpbAndFree(Vpb);
/* We failed, return status */ /* We failed, return status */
OpenPacket->FinalStatus = Status; OpenPacket->FinalStatus = Status;
@ -687,7 +687,7 @@ IopParseDevice(IN PVOID ParseObject,
/* Dereference the device object and VPB */ /* Dereference the device object and VPB */
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
if (Vpb) IopDereferenceVpb(Vpb); if (Vpb) IopDereferenceVpbAndFree(Vpb);
/* Clear the FO and dereference it */ /* Clear the FO and dereference it */
FileObject->DeviceObject = NULL; FileObject->DeviceObject = NULL;
@ -783,7 +783,7 @@ IopParseDevice(IN PVOID ParseObject,
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
/* Unless the driver cancelled the open, dereference the VPB */ /* Unless the driver cancelled the open, dereference the VPB */
if (!(OpenCancelled) && (Vpb)) IopDereferenceVpb(Vpb); if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb);
/* Set the status and return */ /* Set the status and return */
OpenPacket->FinalStatus = Status; OpenPacket->FinalStatus = Status;
@ -806,7 +806,7 @@ IopParseDevice(IN PVOID ParseObject,
if (OwnerDevice != DeviceObject) if (OwnerDevice != DeviceObject)
{ {
/* We have to de-reference the VPB we had associated */ /* We have to de-reference the VPB we had associated */
if (Vpb) IopDereferenceVpb(Vpb); if (Vpb) IopDereferenceVpbAndFree(Vpb);
/* And re-associate with the actual one */ /* And re-associate with the actual one */
Vpb = FileObject->Vpb; Vpb = FileObject->Vpb;

View file

@ -52,19 +52,17 @@ extern LIST_ENTRY ShutdownListHead;
extern LIST_ENTRY LastChanceShutdownListHead; extern LIST_ENTRY LastChanceShutdownListHead;
extern KSPIN_LOCK ShutdownListLock; extern KSPIN_LOCK ShutdownListLock;
extern POBJECT_TYPE IoAdapterObjectType; extern POBJECT_TYPE IoAdapterObjectType;
ERESOURCE IopDatabaseResource; extern ERESOURCE IopDatabaseResource;
extern ERESOURCE FileSystemListLock;
ERESOURCE IopSecurityResource; ERESOURCE IopSecurityResource;
extern KGUARDED_MUTEX FsChangeNotifyListLock;
extern KGUARDED_MUTEX PnpNotifyListLock; extern KGUARDED_MUTEX PnpNotifyListLock;
extern LIST_ENTRY IopDiskFsListHead; extern LIST_ENTRY IopDiskFileSystemQueueHead;
extern LIST_ENTRY IopCdRomFsListHead; extern LIST_ENTRY IopCdRomFileSystemQueueHead;
extern LIST_ENTRY IopTapeFsListHead; extern LIST_ENTRY IopTapeFileSystemQueueHead;
extern LIST_ENTRY IopNetworkFsListHead; extern LIST_ENTRY IopNetworkFileSystemQueueHead;
extern LIST_ENTRY DriverBootReinitListHead; extern LIST_ENTRY DriverBootReinitListHead;
extern LIST_ENTRY DriverReinitListHead; extern LIST_ENTRY DriverReinitListHead;
extern LIST_ENTRY PnpNotifyListHead; extern LIST_ENTRY PnpNotifyListHead;
extern LIST_ENTRY FsChangeNotifyListHead; extern LIST_ENTRY IopFsNotifyChangeQueueHead;
extern LIST_ENTRY IopErrorLogListHead; extern LIST_ENTRY IopErrorLogListHead;
extern LIST_ENTRY IopTimerQueueHead; extern LIST_ENTRY IopTimerQueueHead;
extern KDPC IopTimerDpc; extern KDPC IopTimerDpc;
@ -450,20 +448,18 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
/* Initialize all locks and lists */ /* Initialize all locks and lists */
ExInitializeResource(&IopDatabaseResource); ExInitializeResource(&IopDatabaseResource);
ExInitializeResource(&FileSystemListLock);
ExInitializeResource(&IopSecurityResource); ExInitializeResource(&IopSecurityResource);
KeInitializeGuardedMutex(&FsChangeNotifyListLock);
KeInitializeGuardedMutex(&PnpNotifyListLock); KeInitializeGuardedMutex(&PnpNotifyListLock);
InitializeListHead(&IopDiskFsListHead); InitializeListHead(&IopDiskFileSystemQueueHead);
InitializeListHead(&IopCdRomFsListHead); InitializeListHead(&IopCdRomFileSystemQueueHead);
InitializeListHead(&IopTapeFsListHead); InitializeListHead(&IopTapeFileSystemQueueHead);
InitializeListHead(&IopNetworkFsListHead); InitializeListHead(&IopNetworkFileSystemQueueHead);
InitializeListHead(&DriverBootReinitListHead); InitializeListHead(&DriverBootReinitListHead);
InitializeListHead(&DriverReinitListHead); InitializeListHead(&DriverReinitListHead);
InitializeListHead(&PnpNotifyListHead); InitializeListHead(&PnpNotifyListHead);
InitializeListHead(&ShutdownListHead); InitializeListHead(&ShutdownListHead);
InitializeListHead(&LastChanceShutdownListHead); InitializeListHead(&LastChanceShutdownListHead);
InitializeListHead(&FsChangeNotifyListHead); InitializeListHead(&IopFsNotifyChangeQueueHead);
InitializeListHead(&IopErrorLogListHead); InitializeListHead(&IopErrorLogListHead);
KeInitializeSpinLock(&IoStatisticsLock); KeInitializeSpinLock(&IoStatisticsLock);
KeInitializeSpinLock(&DriverReinitListLock); KeInitializeSpinLock(&DriverReinitListLock);

View file

@ -6,6 +6,7 @@
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Hervé Poussineau (hpoussin@reactos.org) * Hervé Poussineau (hpoussin@reactos.org)
* Eric Kohl * Eric Kohl
* Pierre Schweitzer (pierre.schweitzer@reactos.org)
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -21,14 +22,60 @@
/* GLOBALS ******************************************************************/ /* GLOBALS ******************************************************************/
ERESOURCE FileSystemListLock; ERESOURCE IopDatabaseResource;
LIST_ENTRY IopDiskFsListHead, IopNetworkFsListHead; LIST_ENTRY IopDiskFileSystemQueueHead, IopNetworkFileSystemQueueHead;
LIST_ENTRY IopCdRomFsListHead, IopTapeFsListHead; LIST_ENTRY IopCdRomFileSystemQueueHead, IopTapeFileSystemQueueHead;
KGUARDED_MUTEX FsChangeNotifyListLock; LIST_ENTRY IopFsNotifyChangeQueueHead;
LIST_ENTRY FsChangeNotifyListHead; ULONG IopFsRegistrationOps;
/* PRIVATE FUNCTIONS *********************************************************/ /* PRIVATE FUNCTIONS *********************************************************/
/*
* @halfplemented
*/
VOID
NTAPI
IopDecrementDeviceObjectRef(IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN UnloadIfUnused)
{
KIRQL OldIrql;
/* Acquire lock */
OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock);
ASSERT(DeviceObject->ReferenceCount > 0);
if (--DeviceObject->ReferenceCount > 0)
{
KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql);
return;
}
/* Here, DO is not referenced any longer, check if we have to unload it */
if (UnloadIfUnused || IoGetDevObjExtension(DeviceObject)->ExtensionFlags &
(DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING))
{
/* Unload the driver */
IopUnloadDevice(DeviceObject);
}
/* Release lock */
KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql);
}
/*
* @implemented
*/
VOID
NTAPI
IopDecrementDeviceObjectHandleCount(IN PDEVICE_OBJECT DeviceObject)
{
/* Just decrease reference count */
IopDecrementDeviceObjectRef(DeviceObject, FALSE);
}
/*
* @implemented
*/
PVPB PVPB
NTAPI NTAPI
IopCheckVpbMounted(IN POPEN_PACKET OpenPacket, IopCheckVpbMounted(IN POPEN_PACKET OpenPacket,
@ -100,6 +147,9 @@ IopCheckVpbMounted(IN POPEN_PACKET OpenPacket,
return Vpb; return Vpb;
} }
/*
* @implemented
*/
NTSTATUS NTSTATUS
NTAPI NTAPI
IopCreateVpb(IN PDEVICE_OBJECT DeviceObject) IopCreateVpb(IN PDEVICE_OBJECT DeviceObject)
@ -110,7 +160,7 @@ IopCreateVpb(IN PDEVICE_OBJECT DeviceObject)
Vpb = ExAllocatePoolWithTag(NonPagedPool, Vpb = ExAllocatePoolWithTag(NonPagedPool,
sizeof(VPB), sizeof(VPB),
TAG_VPB); TAG_VPB);
if (!Vpb) return STATUS_UNSUCCESSFUL; if (!Vpb) return STATUS_INSUFFICIENT_RESOURCES;
/* Clear it so we don't waste time manually */ /* Clear it so we don't waste time manually */
RtlZeroMemory(Vpb, sizeof(VPB)); RtlZeroMemory(Vpb, sizeof(VPB));
@ -125,9 +175,12 @@ IopCreateVpb(IN PDEVICE_OBJECT DeviceObject)
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/*
* @implemented
*/
VOID VOID
NTAPI NTAPI
IopDereferenceVpb(IN PVPB Vpb) IopDereferenceVpbAndFree(IN PVPB Vpb)
{ {
KIRQL OldIrql; KIRQL OldIrql;
@ -136,21 +189,30 @@ IopDereferenceVpb(IN PVPB Vpb)
Vpb->ReferenceCount--; Vpb->ReferenceCount--;
/* Check if we're out of references */ /* Check if we're out of references */
if (!Vpb->ReferenceCount) if (!Vpb->ReferenceCount && Vpb->RealDevice->Vpb == Vpb &&
!(Vpb->Flags & VPB_PERSISTENT))
{ {
/* FIXME: IMPLEMENT CLEANUP! */ /* Release VPB lock */
ASSERT(FALSE); IoReleaseVpbSpinLock(OldIrql);
}
/* Release VPB lock */ /* And free VPB */
IoReleaseVpbSpinLock(OldIrql); ExFreePoolWithTag(Vpb, TAG_VPB);
}
else
{
/* Release VPB lock */
IoReleaseVpbSpinLock(OldIrql);
}
} }
/*
* @implemented
*/
BOOLEAN BOOLEAN
NTAPI NTAPI
IopReferenceVpbForVerify(IN PDEVICE_OBJECT DeviceObject, IopReferenceVerifyVpb(IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_OBJECT *FileSystemObject, OUT PDEVICE_OBJECT *FileSystemObject,
OUT PVPB *Vpb) OUT PVPB *Vpb)
{ {
KIRQL OldIrql; KIRQL OldIrql;
PVPB LocalVpb; PVPB LocalVpb;
@ -181,9 +243,9 @@ IopReferenceVpbForVerify(IN PDEVICE_OBJECT DeviceObject,
PVPB PVPB
NTAPI NTAPI
IopInitializeVpbForMount(IN PDEVICE_OBJECT DeviceObject, IopMountInitializeVpb(IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT AttachedDeviceObject, IN PDEVICE_OBJECT AttachedDeviceObject,
IN BOOLEAN Raw) IN BOOLEAN Raw)
{ {
KIRQL OldIrql; KIRQL OldIrql;
PVPB Vpb; PVPB Vpb;
@ -212,20 +274,20 @@ IopInitializeVpbForMount(IN PDEVICE_OBJECT DeviceObject,
return Vpb; return Vpb;
} }
/*
* @implemented
*/
VOID VOID
NTAPI FORCEINLINE
IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject, IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN DriverActive) IN BOOLEAN DriverActive)
{ {
PFS_CHANGE_NOTIFY_ENTRY ChangeEntry; PFS_CHANGE_NOTIFY_ENTRY ChangeEntry;
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
/* Acquire the notification lock */
KeAcquireGuardedMutex(&FsChangeNotifyListLock);
/* Loop the list */ /* Loop the list */
ListEntry = FsChangeNotifyListHead.Flink; ListEntry = IopFsNotifyChangeQueueHead.Flink;
while (ListEntry != &FsChangeNotifyListHead) while (ListEntry != &IopFsNotifyChangeQueueHead)
{ {
/* Get the entry */ /* Get the entry */
ChangeEntry = CONTAINING_RECORD(ListEntry, ChangeEntry = CONTAINING_RECORD(ListEntry,
@ -238,11 +300,47 @@ IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject,
/* Go to the next entry */ /* Go to the next entry */
ListEntry = ListEntry->Flink; ListEntry = ListEntry->Flink;
} }
/* Release the lock */
KeReleaseGuardedMutex(&FsChangeNotifyListLock);
} }
/*
* @implemented
*/
ULONG
FASTCALL
IopInterlockedIncrementUlong(IN KSPIN_LOCK_QUEUE_NUMBER Queue,
IN PULONG Ulong)
{
KIRQL Irql;
ULONG OldValue;
Irql = KeAcquireQueuedSpinLock(Queue);
OldValue = (*Ulong)++;
KeReleaseQueuedSpinLock(Queue, Irql);
return OldValue;
}
/*
* @implemented
*/
ULONG
FASTCALL
IopInterlockedDecrementUlong(IN KSPIN_LOCK_QUEUE_NUMBER Queue,
IN PULONG Ulong)
{
KIRQL Irql;
ULONG OldValue;
Irql = KeAcquireQueuedSpinLock(Queue);
OldValue = (*Ulong)--;
KeReleaseQueuedSpinLock(Queue, Irql);
return OldValue;
}
/*
* @implemented
*/
VOID VOID
NTAPI NTAPI
IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead) IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
@ -254,9 +352,6 @@ IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
KEVENT Event; KEVENT Event;
NTSTATUS Status; NTSTATUS Status;
/* Lock the FS List and initialize an event to wait on */
KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
KeInitializeEvent(&Event, NotificationEvent, FALSE); KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Get the first entry and start looping */ /* Get the first entry and start looping */
@ -268,6 +363,9 @@ IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
DEVICE_OBJECT, DEVICE_OBJECT,
Queue.ListEntry); Queue.ListEntry);
ObReferenceObject(DeviceObject);
IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
/* Check if we're attached */ /* Check if we're attached */
if (DeviceObject->AttachedDevice) if (DeviceObject->AttachedDevice)
{ {
@ -293,18 +391,20 @@ IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
/* Reset the event */ /* Reset the event */
KeClearEvent(&Event); KeClearEvent(&Event);
IopDecrementDeviceObjectRef(DeviceObject, FALSE);
ObDereferenceObject(DeviceObject);
/* Go to the next entry */ /* Go to the next entry */
ListEntry = ListEntry->Flink; ListEntry = ListEntry->Flink;
} }
/* Release the lock */
ExReleaseResourceLite(&FileSystemListLock);
KeLeaveCriticalRegion();
} }
/*
* @implemented
*/
VOID VOID
NTAPI NTAPI
IopLoadFileSystem(IN PDEVICE_OBJECT DeviceObject) IopLoadFileSystemDriver(IN PDEVICE_OBJECT DeviceObject)
{ {
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
PIO_STACK_LOCATION StackPtr; PIO_STACK_LOCATION StackPtr;
@ -347,8 +447,14 @@ IopLoadFileSystem(IN PDEVICE_OBJECT DeviceObject)
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
} }
} }
/* Dereference DO - FsRec? */
IopDecrementDeviceObjectRef(AttachedDeviceObject, TRUE);
} }
/*
* @implemented
*/
NTSTATUS NTSTATUS
NTAPI NTAPI
IopMountVolume(IN PDEVICE_OBJECT DeviceObject, IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
@ -366,7 +472,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
LIST_ENTRY LocalList; LIST_ENTRY LocalList;
PDEVICE_OBJECT AttachedDeviceObject = DeviceObject; PDEVICE_OBJECT AttachedDeviceObject = DeviceObject;
PDEVICE_OBJECT FileSystemDeviceObject, ParentFsDeviceObject; PDEVICE_OBJECT FileSystemDeviceObject, ParentFsDeviceObject;
ULONG FsStackOverhead; ULONG FsStackOverhead, RegistrationOps;
PAGED_CODE(); PAGED_CODE();
/* Check if the device isn't already locked */ /* Check if the device isn't already locked */
@ -387,7 +493,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
/* Acquire the FS Lock*/ /* Acquire the FS Lock*/
KeEnterCriticalRegion(); KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&FileSystemListLock, TRUE); ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
/* Make sure we weren't already mounted */ /* Make sure we weren't already mounted */
if (!(DeviceObject->Vpb->Flags & (VPB_MOUNTED | VPB_REMOVE_PENDING))) if (!(DeviceObject->Vpb->Flags & (VPB_MOUNTED | VPB_REMOVE_PENDING)))
@ -411,17 +517,17 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
(DeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK)) (DeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK))
{ {
/* Use the disk list */ /* Use the disk list */
FsList = &IopDiskFsListHead; FsList = &IopDiskFileSystemQueueHead;
} }
else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM) else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM)
{ {
/* Use the CD-ROM list */ /* Use the CD-ROM list */
FsList = &IopCdRomFsListHead; FsList = &IopCdRomFileSystemQueueHead;
} }
else else
{ {
/* It's gotta be a tape... */ /* It's gotta be a tape... */
FsList = &IopTapeFsListHead; FsList = &IopTapeFileSystemQueueHead;
} }
/* Now loop the fs list until one of the file systems accepts us */ /* Now loop the fs list until one of the file systems accepts us */
@ -502,6 +608,13 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
StackPtr->Parameters.MountVolume.DeviceObject = StackPtr->Parameters.MountVolume.DeviceObject =
AttachedDeviceObject; AttachedDeviceObject;
/* Save registration operations */
RegistrationOps = IopFsRegistrationOps;
/* Release locks */
IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
ExReleaseResourceLite(&IopDatabaseResource);
/* Call the driver */ /* Call the driver */
Status = IoCallDriver(FileSystemDeviceObject, Irp); Status = IoCallDriver(FileSystemDeviceObject, Irp);
if (Status == STATUS_PENDING) if (Status == STATUS_PENDING)
@ -515,14 +628,17 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
Status = IoStatusBlock.Status; Status = IoStatusBlock.Status;
} }
ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
IopInterlockedDecrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
/* Check if mounting was successful */ /* Check if mounting was successful */
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Mount the VPB */ /* Mount the VPB */
*Vpb = IopInitializeVpbForMount(DeviceObject, *Vpb = IopMountInitializeVpb(DeviceObject,
AttachedDeviceObject, AttachedDeviceObject,
(DeviceObject->Vpb->Flags & (DeviceObject->Vpb->Flags &
VPB_RAW_MOUNT)); VPB_RAW_MOUNT));
} }
else else
{ {
@ -534,11 +650,22 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
break; break;
} }
/* If there were registration operations in the meanwhile */
if (RegistrationOps != IopFsRegistrationOps)
{
/* We need to setup a local list to pickup where we left */
LocalList.Flink = FsList->Flink;
ListEntry = &LocalList;
Status = STATUS_UNRECOGNIZED_VOLUME;
}
/* Otherwise, check if we need to load the FS driver */ /* Otherwise, check if we need to load the FS driver */
if (Status == STATUS_FS_DRIVER_REQUIRED) if (Status == STATUS_FS_DRIVER_REQUIRED)
{ {
/* We need to release the lock */ /* We need to release the lock */
ExReleaseResourceLite(&FileSystemListLock); IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
ExReleaseResourceLite(&IopDatabaseResource);
/* Release the device lock if we're holding it */ /* Release the device lock if we're holding it */
if (!DeviceIsLocked) if (!DeviceIsLocked)
@ -546,8 +673,11 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE); KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE);
} }
/* Leave critical section */
KeLeaveCriticalRegion();
/* Load the FS */ /* Load the FS */
IopLoadFileSystem(ParentFsDeviceObject); IopLoadFileSystemDriver(ParentFsDeviceObject);
/* Check if the device isn't already locked */ /* Check if the device isn't already locked */
if (!DeviceIsLocked) if (!DeviceIsLocked)
@ -569,7 +699,8 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
} }
/* Reacquire the lock */ /* Reacquire the lock */
ExAcquireResourceSharedLite(&FileSystemListLock, TRUE); KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
/* When we released the lock, make sure nobody beat us */ /* When we released the lock, make sure nobody beat us */
if (DeviceObject->Vpb->Flags & VPB_MOUNTED) if (DeviceObject->Vpb->Flags & VPB_MOUNTED)
@ -620,7 +751,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
} }
/* Release the FS lock */ /* Release the FS lock */
ExReleaseResourceLite(&FileSystemListLock); ExReleaseResourceLite(&IopDatabaseResource);
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
/* Release the device lock if we're holding it */ /* Release the device lock if we're holding it */
@ -628,7 +759,8 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
/* Check if we failed to mount the boot partition */ /* Check if we failed to mount the boot partition */
if ((!NT_SUCCESS(Status)) && if ((!NT_SUCCESS(Status)) &&
(DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION)) (DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION) &&
ExpInitializationPhase < 2)
{ {
/* Bugcheck the system */ /* Bugcheck the system */
KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE, KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE,
@ -642,19 +774,102 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
return Status; return Status;
} }
/*
* @implemented
*/
VOID
NTAPI
IopNotifyAlreadyRegisteredFileSystems(IN PLIST_ENTRY ListHead,
IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine,
BOOLEAN SkipLast)
{
PLIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject;
/* Browse the whole list */
ListEntry = ListHead->Flink;
while (ListEntry != ListHead)
{
/* Check if we reached end and if we have to skip it */
if (ListEntry->Flink == ListHead && SkipLast)
{
return;
}
/* Otherwise, get DO and notify */
DeviceObject = CONTAINING_RECORD(ListEntry,
DEVICE_OBJECT,
Queue.ListEntry);
DriverNotificationRoutine(DeviceObject, TRUE);
/* Go to the next entry */
ListEntry = ListEntry->Flink;
}
}
/* PUBLIC FUNCTIONS **********************************************************/ /* PUBLIC FUNCTIONS **********************************************************/
/* /*
* @unimplemented * @implemented
*/ */
NTSTATUS NTSTATUS
NTAPI NTAPI
IoEnumerateRegisteredFiltersList(IN PDRIVER_OBJECT *DriverObjectList, IoEnumerateRegisteredFiltersList(OUT PDRIVER_OBJECT *DriverObjectList,
IN ULONG DriverObjectListSize, IN ULONG DriverObjectListSize,
OUT PULONG ActualNumberDriverObjects) OUT PULONG ActualNumberDriverObjects)
{ {
UNIMPLEMENTED; USHORT Index = 0;
return STATUS_UNSUCCESSFUL; ULONG ListSize = 0;
PLIST_ENTRY ListEntry;
NTSTATUS Status = STATUS_SUCCESS;
PFS_CHANGE_NOTIFY_ENTRY ChangeEntry;
/* Acquire the FS lock */
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
/* First of all, count number of driver objects */
ListEntry = IopFsNotifyChangeQueueHead.Flink;
while (ListEntry != &IopFsNotifyChangeQueueHead)
{
ListSize++;
/* Go to the next entry */
ListEntry = ListEntry->Flink;
}
/* Return this size */
*ActualNumberDriverObjects = ListSize;
/* Then, check if given buffer is big enough to contain list */
if (ListSize > DriverObjectListSize / sizeof(PDRIVER_OBJECT))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
/* Rebrowse the whole list */
ListEntry = IopFsNotifyChangeQueueHead.Flink;
while (ListEntry != &IopFsNotifyChangeQueueHead)
{
ChangeEntry = CONTAINING_RECORD(ListEntry,
FS_CHANGE_NOTIFY_ENTRY,
FsChangeNotifyList);
/* Reference the driver object */
ObReferenceObject(ChangeEntry->DriverObject);
/* And pass it to the caller */
DriverObjectList[Index++] = ChangeEntry->DriverObject;
/* Go to the next entry */
ListEntry = ListEntry->Flink;
}
}
/* Release the FS lock */
ExReleaseResourceLite(&IopDatabaseResource);
return Status;
} }
/* /*
@ -669,20 +884,21 @@ 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, VpbStatus; NTSTATUS Status, VpbStatus;
PDEVICE_OBJECT FileSystemDeviceObject; PDEVICE_OBJECT FileSystemDeviceObject;
PVPB Vpb, NewVpb; PVPB Vpb, NewVpb;
BOOLEAN WasNotMounted = TRUE; BOOLEAN WasNotMounted = TRUE;
/* Wait on the device lock */ /* Wait on the device lock */
KeWaitForSingleObject(&DeviceObject->DeviceLock, Status = KeWaitForSingleObject(&DeviceObject->DeviceLock,
Executive, Executive,
KernelMode, KernelMode,
FALSE, FALSE,
NULL); NULL);
ASSERT(Status == STATUS_SUCCESS);
/* Reference the VPB */ /* Reference the VPB */
if (IopReferenceVpbForVerify(DeviceObject, &FileSystemDeviceObject, &Vpb)) if (IopReferenceVerifyVpb(DeviceObject, &FileSystemDeviceObject, &Vpb))
{ {
/* Initialize the event */ /* Initialize the event */
KeInitializeEvent(&Event, NotificationEvent, FALSE); KeInitializeEvent(&Event, NotificationEvent, FALSE);
@ -698,7 +914,11 @@ IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
/* Allocate the IRP */ /* Allocate the IRP */
Irp = IoAllocateIrp(FileSystemDeviceObject->StackSize, FALSE); Irp = IoAllocateIrp(FileSystemDeviceObject->StackSize, FALSE);
if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; if (!Irp)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Release;
}
/* Set it up */ /* Set it up */
Irp->UserIosb = &IoStatusBlock; Irp->UserIosb = &IoStatusBlock;
@ -726,28 +946,37 @@ IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
} }
/* Dereference the VPB */ /* Dereference the VPB */
IopDereferenceVpb(Vpb); IopDereferenceVpbAndFree(Vpb);
} }
/* Check if we had the wrong volume or didn't mount at all */ /* Check if we had the wrong volume or didn't mount at all */
if ((Status == STATUS_WRONG_VOLUME) || (WasNotMounted)) if (Status == STATUS_WRONG_VOLUME)
{ {
/* Create a VPB */ /* Create a VPB */
VpbStatus = IopCreateVpb(DeviceObject); VpbStatus = IopCreateVpb(DeviceObject);
if (NT_SUCCESS(VpbStatus)) if (NT_SUCCESS(VpbStatus))
{ {
PoVolumeDevice(DeviceObject);
/* Mount it */ /* Mount it */
VpbStatus = IopMountVolume(DeviceObject, VpbStatus = IopMountVolume(DeviceObject,
AllowRawMount, AllowRawMount,
TRUE, TRUE,
FALSE, FALSE,
&NewVpb); &NewVpb);
/* If we got a new VPB, dereference it */
if (NewVpb)
{
IopInterlockedDecrementUlong(LockQueueIoVpbLock, &NewVpb->ReferenceCount);
}
} }
/* If we failed, remove the verify flag */ /* If we failed, remove the verify flag */
if (!NT_SUCCESS(VpbStatus)) DeviceObject->Flags &= ~DO_VERIFY_VOLUME; if (!NT_SUCCESS(VpbStatus)) DeviceObject->Flags &= ~DO_VERIFY_VOLUME;
} }
Release:
/* Signal the device lock and return */ /* Signal the device lock and return */
KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE); KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE);
return Status; return Status;
@ -764,29 +993,28 @@ IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
PAGED_CODE(); PAGED_CODE();
/* Acquire the FS lock */ /* Acquire the FS lock */
KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE);
/* Check what kind of FS this is */ /* Check what kind of FS this is */
if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM)
{ {
/* Use the disk list */ /* Use the disk list */
FsList = &IopDiskFsListHead; FsList = &IopDiskFileSystemQueueHead;
} }
else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
{ {
/* Use the network device list */ /* Use the network device list */
FsList = &IopNetworkFsListHead; FsList = &IopNetworkFileSystemQueueHead;
} }
else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
{ {
/* Use the CD-ROM list */ /* Use the CD-ROM list */
FsList = &IopCdRomFsListHead; FsList = &IopCdRomFileSystemQueueHead;
} }
else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM)
{ {
/* Use the tape list */ /* Use the tape list */
FsList = &IopTapeFsListHead; FsList = &IopTapeFileSystemQueueHead;
} }
/* Make sure that we have a valid list */ /* Make sure that we have a valid list */
@ -805,15 +1033,20 @@ IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
} }
} }
/* Update operations counter */
IopFsRegistrationOps++;
/* Clear the initializing flag */ /* Clear the initializing flag */
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
/* Release the FS Lock */
ExReleaseResourceLite(&FileSystemListLock);
KeLeaveCriticalRegion();
/* Notify file systems of the addition */ /* Notify file systems of the addition */
IopNotifyFileSystemChange(DeviceObject, TRUE); IopNotifyFileSystemChange(DeviceObject, TRUE);
/* Release the FS Lock */
ExReleaseResourceLite(&IopDatabaseResource);
/* Ensure driver won't be unloaded */
IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
} }
/* /*
@ -826,18 +1059,25 @@ IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
PAGED_CODE(); PAGED_CODE();
/* Acquire the FS lock */ /* Acquire the FS lock */
KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE);
/* Simply remove the entry */ /* Simply remove the entry - if queued */
RemoveEntryList(&DeviceObject->Queue.ListEntry); if (DeviceObject->Queue.ListEntry.Flink)
{
RemoveEntryList(&DeviceObject->Queue.ListEntry);
}
/* And notify all registered file systems */ /* And notify all registered file systems */
IopNotifyFileSystemChange(DeviceObject, FALSE); IopNotifyFileSystemChange(DeviceObject, FALSE);
/* Update operations counter */
IopFsRegistrationOps++;
/* Then release the lock */ /* Then release the lock */
ExReleaseResourceLite(&FileSystemListLock); ExReleaseResourceLite(&IopDatabaseResource);
KeLeaveCriticalRegion();
/* Decrease reference count to allow unload */
IopInterlockedDecrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
} }
/* /*
@ -846,25 +1086,60 @@ IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
NTSTATUS NTSTATUS
NTAPI NTAPI
IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject, IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
IN PDRIVER_FS_NOTIFICATION FSDNotificationProc) IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine)
{ {
PFS_CHANGE_NOTIFY_ENTRY Entry; PFS_CHANGE_NOTIFY_ENTRY Entry;
PAGED_CODE(); PAGED_CODE();
/* Acquire the list lock */
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
/* Check if that driver is already registered (successive calls)
* See MSDN note: http://msdn.microsoft.com/en-us/library/ff548499%28v=vs.85%29.aspx
*/
if (!IsListEmpty(&IopFsNotifyChangeQueueHead))
{
Entry = CONTAINING_RECORD(IopFsNotifyChangeQueueHead.Blink,
FS_CHANGE_NOTIFY_ENTRY,
FsChangeNotifyList);
if (Entry->DriverObject == DriverObject &&
Entry->FSDNotificationProc == DriverNotificationRoutine)
{
/* Release the lock */
ExReleaseResourceLite(&IopDatabaseResource);
return STATUS_DEVICE_ALREADY_ATTACHED;
}
}
/* Allocate a notification entry */ /* Allocate a notification entry */
Entry = ExAllocatePoolWithTag(PagedPool, Entry = ExAllocatePoolWithTag(PagedPool,
sizeof(FS_CHANGE_NOTIFY_ENTRY), sizeof(FS_CHANGE_NOTIFY_ENTRY),
TAG_FS_CHANGE_NOTIFY); TAG_FS_CHANGE_NOTIFY);
if (!Entry) return(STATUS_INSUFFICIENT_RESOURCES); if (!Entry)
{
/* Release the lock */
ExReleaseResourceLite(&IopDatabaseResource);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Save the driver object and notification routine */ /* Save the driver object and notification routine */
Entry->DriverObject = DriverObject; Entry->DriverObject = DriverObject;
Entry->FSDNotificationProc = FSDNotificationProc; Entry->FSDNotificationProc = DriverNotificationRoutine;
/* Insert it into the notification list */ /* Insert it into the notification list */
KeAcquireGuardedMutex(&FsChangeNotifyListLock); InsertTailList(&IopFsNotifyChangeQueueHead, &Entry->FsChangeNotifyList);
InsertTailList(&FsChangeNotifyListHead, &Entry->FsChangeNotifyList);
KeReleaseGuardedMutex(&FsChangeNotifyListLock); /* Start notifying all already present FS */
IopNotifyAlreadyRegisteredFileSystems(&IopNetworkFileSystemQueueHead, DriverNotificationRoutine, FALSE);
IopNotifyAlreadyRegisteredFileSystems(&IopCdRomFileSystemQueueHead, DriverNotificationRoutine, TRUE);
IopNotifyAlreadyRegisteredFileSystems(&IopDiskFileSystemQueueHead, DriverNotificationRoutine, TRUE);
IopNotifyAlreadyRegisteredFileSystems(&IopTapeFileSystemQueueHead, DriverNotificationRoutine, TRUE);
/* Release the lock */
ExReleaseResourceLite(&IopDatabaseResource);
/* Reference the driver */ /* Reference the driver */
ObReferenceObject(DriverObject); ObReferenceObject(DriverObject);
@ -884,11 +1159,11 @@ IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
PAGED_CODE(); PAGED_CODE();
/* Acquire the list lock */ /* Acquire the list lock */
KeAcquireGuardedMutex(&FsChangeNotifyListLock); ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
/* Loop the list */ /* Loop the list */
NextEntry = FsChangeNotifyListHead.Flink; NextEntry = IopFsNotifyChangeQueueHead.Flink;
while (NextEntry != &FsChangeNotifyListHead) while (NextEntry != &IopFsNotifyChangeQueueHead)
{ {
/* Get the entry */ /* Get the entry */
ChangeEntry = CONTAINING_RECORD(NextEntry, ChangeEntry = CONTAINING_RECORD(NextEntry,
@ -910,7 +1185,7 @@ IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
} }
/* Release the lock and dereference the driver */ /* Release the lock and dereference the driver */
KeReleaseGuardedMutex(&FsChangeNotifyListLock); ExReleaseResourceLite(&IopDatabaseResource);
ObDereferenceObject(DriverObject); ObDereferenceObject(DriverObject);
} }