Author: ion Date: Sun Jul 2 06:04:04 2006 New Revision: 22758
URL: http://svn.reactos.org/svn/reactos?rev=22758&view=rev Log: - 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.
Modified: trunk/reactos/ntoskrnl/io/iomgr/volume.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/volume.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/volume.c?... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/volume.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/volume.c Sun Jul 2 06:04:04 2006 @@ -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 @@ 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 @@ 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) - { - /* send IRP_MJ_SHUTDOWN */ + /* Get the first entry and start looping */ + ListEntry = IopDiskFsListHead.Flink; + while (ListEntry != &IopDiskFsListHead) + { + /* 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 @@ 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) - { - if (current->DeviceObject->DeviceType != MatchingDeviceType) - { - continue; - } + /* 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)) + { + /* 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 @@ NTAPI IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject) { - PFILE_SYSTEM_OBJECT Fs; - - Fs = ExAllocatePoolWithTag(NonPagedPool, - sizeof(FILE_SYSTEM_OBJECT), - TAG_FILE_SYSTEM); - ASSERT(Fs!=NULL); - - Fs->DeviceObject = DeviceObject; + PLIST_ENTRY FsList = NULL; + PAGED_CODE(); + + /* 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 @@ 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(); }