diff --git a/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h b/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h index 015971d188..110080dda5 100644 --- a/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h +++ b/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h @@ -98,10 +98,16 @@ public: status_t StartMonitoring(); private: + struct DeviceMap; + struct DiskSystemMap; + struct PartitionMap; + struct PartitionSet; + class DeviceWatcher; + static status_t _CheckMediaStatusDaemon(void* self); status_t _CheckMediaStatus(); - status_t _RescanDiskSystems(bool fileSystems); + status_t _RescanDiskSystems(DiskSystemMap& addedSystems, bool fileSystems); status_t _AddPartitioningSystem(const char *name); status_t _AddFileSystem(const char *name); @@ -111,19 +117,14 @@ private: bool _RemoveDevice(KDiskDevice *device); status_t _Scan(const char *path); - status_t _ScanPartition(KPartition *partition, bool async); + status_t _ScanPartition(KPartition *partition, bool async, + DiskSystemMap* restrictScan = NULL); // the manager must be locked and the device write locked - status_t _ScanPartition(KPartition *partition); - // used by the other _ScanPartition() version only + status_t _ScanPartition(KPartition *partition, + DiskSystemMap* restrictScan); status_t _AddRemoveMonitoring(const char *path, bool add); - struct DeviceMap; - struct DiskSystemMap; - struct PartitionMap; - struct PartitionSet; - class DeviceWatcher; - BLocker fLock; DeviceMap *fDevices; PartitionMap *fPartitions; diff --git a/headers/private/kernel/disk_device_manager/KPartition.h b/headers/private/kernel/disk_device_manager/KPartition.h index 40311bf105..11e009bb84 100644 --- a/headers/private/kernel/disk_device_manager/KPartition.h +++ b/headers/private/kernel/disk_device_manager/KPartition.h @@ -148,8 +148,9 @@ public: // DiskSystem - void SetDiskSystem(KDiskSystem *diskSystem); + void SetDiskSystem(KDiskSystem *diskSystem, float priority = 0.0f); KDiskSystem *DiskSystem() const; + float DiskSystemPriority() const; KDiskSystem *ParentDiskSystem() const; // When setting a disk system, it must already be loaded. // The partition will load it too, hence it won't be unloaded before @@ -218,6 +219,7 @@ protected: KDiskDevice *fDevice; KPartition *fParent; KDiskSystem *fDiskSystem; + float fDiskSystemPriority; ListenerSet *fListeners; uint32 fChangeFlags; int32 fChangeCounter; diff --git a/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp b/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp index fbceec9ef4..da0583b8aa 100644 --- a/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007, Haiku, Inc. All rights reserved. + * Copyright 2004-2008, Haiku, Inc. All rights reserved. * Copyright 2003-2004, Ingo Weinhold, bonefish@cs.tu-berlin.de. All rights reserved. * * Distributed under the terms of the MIT License. @@ -159,14 +159,6 @@ class KDiskDeviceManager::DeviceWatcher : public NotificationListener { }; -static bool -is_active_job_status(uint32 status) -{ - return (status == B_DISK_DEVICE_JOB_SCHEDULED - || status == B_DISK_DEVICE_JOB_IN_PROGRESS); -} - - // #pragma mark - @@ -919,9 +911,9 @@ KDiskDeviceManager::StartMonitoring() } -// _RescanDiskSystems status_t -KDiskDeviceManager::_RescanDiskSystems(bool fileSystems) +KDiskDeviceManager::_RescanDiskSystems(DiskSystemMap& addedSystems, + bool fileSystems) { void *cookie = open_module_list(fileSystems ? kFileSystemPrefix : kPartitioningSystemPrefix); @@ -949,19 +941,43 @@ KDiskDeviceManager::_RescanDiskSystems(bool fileSystems) DBG(OUT("partitioning system: %s\n", name.Path())); _AddPartitioningSystem(name.Path()); } + + if (KDiskSystem* system = FindDiskSystem(name.Path())) + addedSystems.Put(system->ID(), system); } close_module_list(cookie); return B_OK; } -// RescanDiskSystems + +/*! Rescan the existing disk systems. This is called after the boot device + has become available. +*/ status_t KDiskDeviceManager::RescanDiskSystems() { + DiskSystemMap addedSystems; + // rescan for partitioning and file systems - _RescanDiskSystems(false); - _RescanDiskSystems(true); + _RescanDiskSystems(addedSystems, false); + _RescanDiskSystems(addedSystems, true); + + // rescan existing devices with the new disk systems + int32 cookie = 0; + while (KDiskDevice *device = RegisterNextDevice(&cookie)) { + PartitionRegistrar _(device, true); + if (DeviceWriteLocker deviceLocker = device) { + if (ManagerLocker locker = this) { + status_t status = _ScanPartition(device, false, &addedSystems); + device->UnmarkBusy(true); + if (status != B_OK) + break; + } else + return B_ERROR; + } else + return B_ERROR; + } return B_OK; } @@ -1158,7 +1174,8 @@ DBG(OUT(" found device: %s\n", path)); The device must be write locked, the manager must be locked. */ status_t -KDiskDeviceManager::_ScanPartition(KPartition *partition, bool async) +KDiskDeviceManager::_ScanPartition(KPartition *partition, bool async, + DiskSystemMap* restrictScan) { // TODO: There's no reason why the manager needs to be locked anymore. if (!partition) @@ -1197,22 +1214,26 @@ KDiskDeviceManager::_ScanPartition(KPartition *partition, bool async) // scan synchronously - return _ScanPartition(partition); + return _ScanPartition(partition, restrictScan); } status_t -KDiskDeviceManager::_ScanPartition(KPartition *partition) +KDiskDeviceManager::_ScanPartition(KPartition* partition, + DiskSystemMap* restrictScan) { // the partition's device must be write-locked - if (!partition) + if (partition == NULL) return B_BAD_VALUE; - if (!partition->Device()->HasMedia()) + if (!partition->Device()->HasMedia() || partition->IsMounted()) return B_OK; - if (partition->DiskSystem() != NULL) { - // TODO: this is more or less a hack to allow rescanning a partition - for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) - _ScanPartition(child); + + if (partition->CountChildren() > 0) { + // Since this partition has already children, we don't scan it + // again, but only its children. + for (int32 i = 0; KPartition* child = partition->ChildAt(i); i++) { + _ScanPartition(child, restrictScan); + } return B_OK; } @@ -1230,12 +1251,20 @@ KDiskDeviceManager::_ScanPartition(KPartition *partition) return error; } + DiskSystemMap* diskSystems = restrictScan; + if (diskSystems == NULL) + diskSystems = fDiskSystems; + // find the disk system that returns the best priority for this partition - float bestPriority = -1; + float bestPriority = partition->DiskSystemPriority(); KDiskSystem *bestDiskSystem = NULL; void *bestCookie = NULL; - int32 itCookie = 0; - while (KDiskSystem *diskSystem = LoadNextDiskSystem(&itCookie)) { + for (DiskSystemMap::Iterator iterator = diskSystems->Begin(); + iterator != diskSystems->End(); iterator++) { + KDiskSystem* diskSystem = iterator->Value(); + if (diskSystem->Load() != B_OK) + continue; + DBG(OUT(" trying: %s\n", diskSystem->Name())); void *cookie = NULL; @@ -1267,9 +1296,9 @@ KDiskDeviceManager::_ScanPartition(KPartition *partition) error = bestDiskSystem->Scan(partition, bestCookie); bestDiskSystem->FreeIdentifyCookie(partition, bestCookie); if (error == B_OK) { - partition->SetDiskSystem(bestDiskSystem); + partition->SetDiskSystem(bestDiskSystem, bestPriority); for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) - _ScanPartition(child); + _ScanPartition(child, restrictScan); } else { // TODO: Handle the error. DBG(OUT(" scanning failed: %s\n", strerror(error))); diff --git a/src/system/kernel/disk_device_manager/KPartition.cpp b/src/system/kernel/disk_device_manager/KPartition.cpp index c623a39a17..513aa1d078 100644 --- a/src/system/kernel/disk_device_manager/KPartition.cpp +++ b/src/system/kernel/disk_device_manager/KPartition.cpp @@ -1,4 +1,10 @@ -// KPartition.cpp +/* + * Copyright 2004-2008, Haiku, Inc. All rights reserved. + * Copyright 2003-2004, Ingo Weinhold, bonefish@cs.tu-berlin.de. All rights reserved. + * + * Distributed under the terms of the MIT License. + */ + #include #include @@ -44,6 +50,7 @@ KPartition::KPartition(partition_id id) fDevice(NULL), fParent(NULL), fDiskSystem(NULL), + fDiskSystemPriority(-1), fListeners(NULL), fChangeFlags(0), fChangeCounter(0), @@ -52,7 +59,7 @@ KPartition::KPartition(partition_id id) fObsolete(false), fPublished(false) { - fPartitionData.id = (id >= 0 ? id : _NextID()); + fPartitionData.id = id >= 0 ? id : _NextID(); fPartitionData.offset = 0; fPartitionData.size = 0; fPartitionData.content_size = 0; @@ -895,13 +902,14 @@ KPartition::VisitEachDescendant(KPartitionVisitor *visitor) // SetDiskSystem void -KPartition::SetDiskSystem(KDiskSystem *diskSystem) +KPartition::SetDiskSystem(KDiskSystem *diskSystem, float priority) { // unload former disk system if (fDiskSystem) { fPartitionData.content_type = NULL; fDiskSystem->Unload(); fDiskSystem = NULL; + fDiskSystemPriority = -1; } // set and load new one fDiskSystem = diskSystem; @@ -910,6 +918,7 @@ KPartition::SetDiskSystem(KDiskSystem *diskSystem) // update concerned partition flags if (fDiskSystem) { fPartitionData.content_type = fDiskSystem->PrettyName(); + fDiskSystemPriority = priority; if (fDiskSystem->IsFileSystem()) AddFlags(B_PARTITION_FILE_SYSTEM); else @@ -926,6 +935,14 @@ KPartition::DiskSystem() const return fDiskSystem; } + +float +KPartition::DiskSystemPriority() const +{ + return fDiskSystemPriority; +} + + // ParentDiskSystem KDiskSystem * KPartition::ParentDiskSystem() const