mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
- 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:
parent
23e06403c7
commit
8da2913330
1 changed files with 126 additions and 92 deletions
|
@ -16,24 +16,14 @@
|
|||
|
||||
#if defined (ALLOC_PRAGMA)
|
||||
#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)
|
||||
#endif
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
ERESOURCE FileSystemListLock;
|
||||
LIST_ENTRY FileSystemListHead;
|
||||
LIST_ENTRY IopDiskFsListHead, IopNetworkFsListHead;
|
||||
LIST_ENTRY IopCdRomFsListHead, IopTapeFsListHead;
|
||||
KGUARDED_MUTEX FsChangeNotifyListLock;
|
||||
LIST_ENTRY FsChangeNotifyListHead;
|
||||
KSPIN_LOCK IoVpbLock;
|
||||
|
@ -53,11 +43,14 @@ INIT_FUNCTION
|
|||
NTAPI
|
||||
IoInitFileSystemImplementation(VOID)
|
||||
{
|
||||
InitializeListHead(&FileSystemListHead);
|
||||
ExInitializeResourceLite(&FileSystemListLock);
|
||||
|
||||
InitializeListHead(&FsChangeNotifyListHead);
|
||||
KeInitializeGuardedMutex(&FsChangeNotifyListLock);
|
||||
/* Initialize the FS Lists and Locks */
|
||||
InitializeListHead(&IopDiskFsListHead);
|
||||
InitializeListHead(&IopNetworkFsListHead);
|
||||
InitializeListHead(&IopCdRomFsListHead);
|
||||
InitializeListHead(&IopTapeFsListHead);
|
||||
ExInitializeResourceLite(&FileSystemListLock);
|
||||
InitializeListHead(&FsChangeNotifyListHead);
|
||||
KeInitializeGuardedMutex(&FsChangeNotifyListLock);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -174,38 +167,57 @@ VOID
|
|||
NTAPI
|
||||
IoShutdownRegisteredFileSystems(VOID)
|
||||
{
|
||||
FILE_SYSTEM_OBJECT* current;
|
||||
PLIST_ENTRY ListEntry;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
IO_STATUS_BLOCK StatusBlock;
|
||||
PIRP Irp;
|
||||
KEVENT Event;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Lock the FS List and initialize an event to wait on */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
|
||||
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,
|
||||
current->DeviceObject,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
|
||||
Status = IoCallDriver(current->DeviceObject,Irp);
|
||||
&StatusBlock);
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
/* Wait on the driver */
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
/* Reset the event */
|
||||
KeClearEvent(&Event);
|
||||
|
||||
/* Go to the next entry */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
KeLeaveCriticalRegion();
|
||||
}
|
||||
|
@ -311,63 +323,58 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
IN BOOLEAN Alertable,
|
||||
OUT PVPB *Vpb)
|
||||
{
|
||||
PFILE_SYSTEM_OBJECT current;
|
||||
NTSTATUS Status;
|
||||
DEVICE_TYPE MatchingDeviceType;
|
||||
PLIST_ENTRY FsList, ListEntry;
|
||||
PDEVICE_OBJECT DevObject;
|
||||
PDEVICE_OBJECT FileSystemDeviceObject;
|
||||
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();
|
||||
ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
|
||||
|
||||
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)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Use the disk list */
|
||||
FsList = &IopDiskFsListHead;
|
||||
}
|
||||
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
|
||||
then don't try this */
|
||||
if (!AllowRawMount && RawFsIsRawFileSystemDeviceObject(current->DeviceObject))
|
||||
if (!AllowRawMount && RawFsIsRawFileSystemDeviceObject(FileSystemDeviceObject))
|
||||
{
|
||||
Status = STATUS_UNRECOGNIZED_VOLUME;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = IopMountFileSystem(current->DeviceObject, DeviceObject);
|
||||
Status = IopMountFileSystem(FileSystemDeviceObject, DeviceObject);
|
||||
}
|
||||
|
||||
switch (Status)
|
||||
{
|
||||
case STATUS_FS_DRIVER_REQUIRED:
|
||||
DevObject = current->DeviceObject;
|
||||
DevObject = FileSystemDeviceObject;
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
IopLoadFileSystem(DevObject);
|
||||
ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
|
||||
|
@ -497,27 +504,59 @@ VOID
|
|||
NTAPI
|
||||
IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PFILE_SYSTEM_OBJECT Fs;
|
||||
PLIST_ENTRY FsList = NULL;
|
||||
PAGED_CODE();
|
||||
|
||||
Fs = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(FILE_SYSTEM_OBJECT),
|
||||
TAG_FILE_SYSTEM);
|
||||
ASSERT(Fs!=NULL);
|
||||
|
||||
Fs->DeviceObject = DeviceObject;
|
||||
/* Acquire the FS lock */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE);
|
||||
|
||||
/* The RAW filesystem device objects must be last in the list so the
|
||||
raw filesystem driver is the last filesystem driver asked to mount
|
||||
a volume. It is always the first filesystem driver registered so
|
||||
we use InsertHeadList() here as opposed to the other alternative
|
||||
InsertTailList(). */
|
||||
InsertHeadList(&FileSystemListHead, &Fs->Entry);
|
||||
/* Check what kind of FS this is */
|
||||
if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM)
|
||||
{
|
||||
/* Use the disk list */
|
||||
FsList = &IopDiskFsListHead;
|
||||
}
|
||||
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);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Notify file systems of the addition */
|
||||
IopNotifyFileSystemChange(DeviceObject, TRUE);
|
||||
}
|
||||
|
||||
|
@ -528,24 +567,19 @@ VOID
|
|||
NTAPI
|
||||
IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PFILE_SYSTEM_OBJECT current;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Acquire the FS lock */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE);
|
||||
|
||||
LIST_FOR_EACH(current,&FileSystemListHead, FILE_SYSTEM_OBJECT,Entry)
|
||||
{
|
||||
if (current->DeviceObject == DeviceObject)
|
||||
{
|
||||
RemoveEntryList(¤t->Entry);
|
||||
ExFreePoolWithTag(current, TAG_FILE_SYSTEM);
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
KeLeaveCriticalRegion();
|
||||
IopNotifyFileSystemChange(DeviceObject, FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Simply remove the entry */
|
||||
RemoveEntryList(&DeviceObject->Queue.ListEntry);
|
||||
|
||||
/* And notify all registered file systems */
|
||||
IopNotifyFileSystemChange(DeviceObject, FALSE);
|
||||
|
||||
/* Then release the lock */
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
KeLeaveCriticalRegion();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue