- Simplify/modularize FS registration by using distinct lists for each type of FS (Tape/Disk/Network/Cdrom).

- Optimize by using directly the device queue instead of allocating a structure for each FS registered.
- Hack IopMountVolume to manage this new model. Improved version coming in next patch to deal with some bugs.

svn path=/trunk/; revision=22758
This commit is contained in:
Alex Ionescu 2006-07-02 02:04:04 +00:00
parent 23e06403c7
commit 8da2913330

View file

@ -16,24 +16,14 @@
#if defined (ALLOC_PRAGMA) #if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, IoInitFileSystemImplementation) #pragma alloc_text(INIT, IoInitFileSystemImplementation)
#endif
/* TYPES *******************************************************************/
typedef struct _FILE_SYSTEM_OBJECT
{
PDEVICE_OBJECT DeviceObject;
LIST_ENTRY Entry;
} FILE_SYSTEM_OBJECT, *PFILE_SYSTEM_OBJECT;
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, IoInitVpbImplementation) #pragma alloc_text(INIT, IoInitVpbImplementation)
#endif #endif
/* GLOBALS ******************************************************************/ /* GLOBALS ******************************************************************/
ERESOURCE FileSystemListLock; ERESOURCE FileSystemListLock;
LIST_ENTRY FileSystemListHead; LIST_ENTRY IopDiskFsListHead, IopNetworkFsListHead;
LIST_ENTRY IopCdRomFsListHead, IopTapeFsListHead;
KGUARDED_MUTEX FsChangeNotifyListLock; KGUARDED_MUTEX FsChangeNotifyListLock;
LIST_ENTRY FsChangeNotifyListHead; LIST_ENTRY FsChangeNotifyListHead;
KSPIN_LOCK IoVpbLock; KSPIN_LOCK IoVpbLock;
@ -53,11 +43,14 @@ INIT_FUNCTION
NTAPI NTAPI
IoInitFileSystemImplementation(VOID) IoInitFileSystemImplementation(VOID)
{ {
InitializeListHead(&FileSystemListHead); /* Initialize the FS Lists and Locks */
ExInitializeResourceLite(&FileSystemListLock); InitializeListHead(&IopDiskFsListHead);
InitializeListHead(&IopNetworkFsListHead);
InitializeListHead(&FsChangeNotifyListHead); InitializeListHead(&IopCdRomFsListHead);
KeInitializeGuardedMutex(&FsChangeNotifyListLock); InitializeListHead(&IopTapeFsListHead);
ExInitializeResourceLite(&FileSystemListLock);
InitializeListHead(&FsChangeNotifyListHead);
KeInitializeGuardedMutex(&FsChangeNotifyListLock);
} }
NTSTATUS NTSTATUS
@ -174,38 +167,57 @@ VOID
NTAPI NTAPI
IoShutdownRegisteredFileSystems(VOID) IoShutdownRegisteredFileSystems(VOID)
{ {
FILE_SYSTEM_OBJECT* current; PLIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK StatusBlock;
PIRP Irp; PIRP Irp;
KEVENT Event; KEVENT Event;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status; NTSTATUS Status;
/* Lock the FS List and initialize an event to wait on */
KeEnterCriticalRegion(); KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&FileSystemListLock,TRUE); ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
KeInitializeEvent(&Event, NotificationEvent, FALSE); KeInitializeEvent(&Event, NotificationEvent, FALSE);
LIST_FOR_EACH(current, &FileSystemListHead, FILE_SYSTEM_OBJECT,Entry) /* Get the first entry and start looping */
ListEntry = IopDiskFsListHead.Flink;
while (ListEntry != &IopDiskFsListHead)
{ {
/* send IRP_MJ_SHUTDOWN */ /* Get the device object */
DeviceObject = CONTAINING_RECORD(ListEntry,
DEVICE_OBJECT,
Queue.ListEntry);
/* Check if we're attached */
if (DeviceObject->AttachedDevice)
{
/* Get the attached device */
DeviceObject = IoGetAttachedDevice(DeviceObject);
}
/* Build the shutdown IRP and call the driver */
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
current->DeviceObject, DeviceObject,
NULL, NULL,
0, 0,
0, NULL,
&Event, &Event,
&IoStatusBlock); &StatusBlock);
Status = IoCallDriver(DeviceObject, Irp);
Status = IoCallDriver(current->DeviceObject,Irp);
if (Status == STATUS_PENDING) if (Status == STATUS_PENDING)
{ {
KeWaitForSingleObject(&Event, /* Wait on the driver */
Executive, KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
KernelMode,
FALSE,
NULL);
} }
/* Reset the event */
KeClearEvent(&Event);
/* Go to the next entry */
ListEntry = ListEntry->Flink;
} }
/* Release the lock */
ExReleaseResourceLite(&FileSystemListLock); ExReleaseResourceLite(&FileSystemListLock);
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
} }
@ -311,63 +323,58 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
OUT PVPB *Vpb) OUT PVPB *Vpb)
{ {
PFILE_SYSTEM_OBJECT current;
NTSTATUS Status; NTSTATUS Status;
DEVICE_TYPE MatchingDeviceType; PLIST_ENTRY FsList, ListEntry;
PDEVICE_OBJECT DevObject; PDEVICE_OBJECT DevObject;
PDEVICE_OBJECT FileSystemDeviceObject;
ASSERT_IRQL(PASSIVE_LEVEL); ASSERT_IRQL(PASSIVE_LEVEL);
switch (DeviceObject->DeviceType)
{
case FILE_DEVICE_DISK:
case FILE_DEVICE_VIRTUAL_DISK: /* ?? */
MatchingDeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
break;
case FILE_DEVICE_CD_ROM:
MatchingDeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
break;
case FILE_DEVICE_NETWORK:
MatchingDeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
break;
case FILE_DEVICE_TAPE:
MatchingDeviceType = FILE_DEVICE_TAPE_FILE_SYSTEM;
break;
default:
CPRINT("No matching file system type found for device type: %x\n",
DeviceObject->DeviceType);
return(STATUS_UNRECOGNIZED_VOLUME);
}
KeEnterCriticalRegion(); KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&FileSystemListLock,TRUE); ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
restart: restart:
LIST_FOR_EACH(current,&FileSystemListHead, FILE_SYSTEM_OBJECT, Entry) /* For a mount operation, this can only be a Disk, CD-ROM or tape */
if ((DeviceObject->DeviceType == FILE_DEVICE_DISK) ||
(DeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK))
{ {
if (current->DeviceObject->DeviceType != MatchingDeviceType) /* Use the disk list */
{ FsList = &IopDiskFsListHead;
continue; }
} else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM)
{
/* Use the CD-ROM list */
FsList = &IopCdRomFsListHead;
}
else
{
/* It's gotta be a tape... */
FsList = &IopTapeFsListHead;
}
/* Now loop the fs list until one of the file systems accepts us */
ListEntry = FsList->Flink;
while (ListEntry != FsList)
{
/* Get the Device Object for this FS */
FileSystemDeviceObject = CONTAINING_RECORD(ListEntry,
DEVICE_OBJECT,
Queue.ListEntry);
/* If we are not allowed to mount this volume as a raw filesystem volume /* If we are not allowed to mount this volume as a raw filesystem volume
then don't try this */ then don't try this */
if (!AllowRawMount && RawFsIsRawFileSystemDeviceObject(current->DeviceObject)) if (!AllowRawMount && RawFsIsRawFileSystemDeviceObject(FileSystemDeviceObject))
{ {
Status = STATUS_UNRECOGNIZED_VOLUME; Status = STATUS_UNRECOGNIZED_VOLUME;
} }
else else
{ {
Status = IopMountFileSystem(current->DeviceObject, DeviceObject); Status = IopMountFileSystem(FileSystemDeviceObject, DeviceObject);
} }
switch (Status) switch (Status)
{ {
case STATUS_FS_DRIVER_REQUIRED: case STATUS_FS_DRIVER_REQUIRED:
DevObject = current->DeviceObject; DevObject = FileSystemDeviceObject;
ExReleaseResourceLite(&FileSystemListLock); ExReleaseResourceLite(&FileSystemListLock);
IopLoadFileSystem(DevObject); IopLoadFileSystem(DevObject);
ExAcquireResourceSharedLite(&FileSystemListLock,TRUE); ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
@ -497,27 +504,59 @@ VOID
NTAPI NTAPI
IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject) IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
{ {
PFILE_SYSTEM_OBJECT Fs; PLIST_ENTRY FsList = NULL;
PAGED_CODE();
Fs = ExAllocatePoolWithTag(NonPagedPool, /* Acquire the FS lock */
sizeof(FILE_SYSTEM_OBJECT),
TAG_FILE_SYSTEM);
ASSERT(Fs!=NULL);
Fs->DeviceObject = DeviceObject;
KeEnterCriticalRegion(); KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE); ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE);
/* The RAW filesystem device objects must be last in the list so the /* Check what kind of FS this is */
raw filesystem driver is the last filesystem driver asked to mount if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM)
a volume. It is always the first filesystem driver registered so {
we use InsertHeadList() here as opposed to the other alternative /* Use the disk list */
InsertTailList(). */ FsList = &IopDiskFsListHead;
InsertHeadList(&FileSystemListHead, &Fs->Entry); }
else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
{
/* Use the network device list */
FsList = &IopNetworkFsListHead;
}
else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
{
/* Use the CD-ROM list */
FsList = &IopCdRomFsListHead;
}
else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM)
{
/* Use the tape list */
FsList = &IopTapeFsListHead;
}
/* Make sure that we have a valid list */
if (FsList)
{
/* Check if we should insert it at the top or bottom of the list */
if (DeviceObject->Flags & DO_LOW_PRIORITY_FILESYSTEM)
{
/* At the bottom */
InsertTailList(FsList->Blink, &DeviceObject->Queue.ListEntry);
}
else
{
/* On top */
InsertHeadList(FsList, &DeviceObject->Queue.ListEntry);
}
}
/* Clear the initializing flag */
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
/* Release the FS Lock */
ExReleaseResourceLite(&FileSystemListLock); ExReleaseResourceLite(&FileSystemListLock);
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
/* Notify file systems of the addition */
IopNotifyFileSystemChange(DeviceObject, TRUE); IopNotifyFileSystemChange(DeviceObject, TRUE);
} }
@ -528,24 +567,19 @@ VOID
NTAPI NTAPI
IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject) IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
{ {
PFILE_SYSTEM_OBJECT current; PAGED_CODE();
/* Acquire the FS lock */
KeEnterCriticalRegion(); KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE); ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE);
LIST_FOR_EACH(current,&FileSystemListHead, FILE_SYSTEM_OBJECT,Entry) /* Simply remove the entry */
{ RemoveEntryList(&DeviceObject->Queue.ListEntry);
if (current->DeviceObject == DeviceObject)
{
RemoveEntryList(&current->Entry);
ExFreePoolWithTag(current, TAG_FILE_SYSTEM);
ExReleaseResourceLite(&FileSystemListLock);
KeLeaveCriticalRegion();
IopNotifyFileSystemChange(DeviceObject, FALSE);
return;
}
}
/* And notify all registered file systems */
IopNotifyFileSystemChange(DeviceObject, FALSE);
/* Then release the lock */
ExReleaseResourceLite(&FileSystemListLock); ExReleaseResourceLite(&FileSystemListLock);
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
} }