diff --git a/src/kernel/core/disk_device_manager/jobs/KScanPartitionJob.cpp b/src/kernel/core/disk_device_manager/jobs/KScanPartitionJob.cpp index d12846b5f9..d0cbd60e7d 100644 --- a/src/kernel/core/disk_device_manager/jobs/KScanPartitionJob.cpp +++ b/src/kernel/core/disk_device_manager/jobs/KScanPartitionJob.cpp @@ -1,3 +1,115 @@ // KScanPartitionJob.cpp +#include +#include + +#include "KDiskDevice.h" +#include "KDiskDeviceManager.h" +#include "KDiskDeviceUtils.h" +#include "KDiskSystem.h" +#include "KPartition.h" #include "KScanPartitionJob.h" + +// debugging +//#define DBG(x) +#define DBG(x) x +#define OUT printf + +// constructor +KScanPartitionJob::KScanPartitionJob(partition_id partitionID) + : KDiskDeviceJob(B_DISK_DEVICE_JOB_SCAN, partitionID) +{ +} + +// destructor +KScanPartitionJob::~KScanPartitionJob() +{ +} + +// Do +status_t +KScanPartitionJob::Do() +{ + // get the partition + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *partition = manager->WriteLockPartition(PartitionID()); + if (!partition) + return B_ENTRY_NOT_FOUND; + KDiskDevice *device = partition->Device(); + PartitionRegistrar registrar1(partition, true); + PartitionRegistrar registrar2(device, true); + DeviceWriteLocker locker(device, true); + // scan the partition + status_t error = B_OK; + if (device->HasMedia()) { + error = _ScanPartition(partition); + if (error != B_OK) { + // ... + error = B_OK; + } + } + return error; +} + +// _ScanPartition +status_t +KScanPartitionJob::_ScanPartition(KPartition *partition) +{ + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // the partition's device must be write-locked + if (!partition) + return B_BAD_VALUE; +char partitionPath[B_PATH_NAME_LENGTH]; +partition->GetPath(partitionPath); +DBG(OUT("KDiskDeviceManager::_ScanPartition(%s)\n", partitionPath)); + // publish the partition + status_t error = partition->PublishDevice(); + if (error != B_OK) + return error; + // find the disk system that returns the best priority for this partition + float bestPriority = -1; + KDiskSystem *bestDiskSystem = NULL; + void *bestCookie = NULL; + int32 itCookie = 0; + while (KDiskSystem *diskSystem = manager->LoadNextDiskSystem(&itCookie)) { +DBG(OUT(" trying: %s\n", diskSystem->Name())); + void *cookie = NULL; + float priority = diskSystem->Identify(partition, &cookie); +DBG(OUT(" returned: %f\n", priority)); + if (priority >= 0 && priority > bestPriority) { + // new best disk system + if (bestDiskSystem) { + bestDiskSystem->FreeIdentifyCookie(partition, bestCookie); + bestDiskSystem->Unload(); + } + bestPriority = priority; + bestDiskSystem = diskSystem; + bestCookie = cookie; + } else { + // disk system doesn't identify the partition or worse than our + // current favorite + diskSystem->FreeIdentifyCookie(partition, cookie); + diskSystem->Unload(); + } + } + // now, if we have found a disk system, let it scan the partition + if (bestDiskSystem) { +DBG(OUT(" scanning with: %s\n", bestDiskSystem->Name())); + error = bestDiskSystem->Scan(partition, bestCookie); + if (error == B_OK) { + partition->SetDiskSystem(bestDiskSystem); + for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) + _ScanPartition(child); + } else { + // TODO: Handle the error. +DBG(OUT(" scanning failed: %s\n", strerror(error))); + } + // now we can safely unload the disk system -- it has been loaded by + // the partition(s) and thus will not really be unloaded + bestDiskSystem->Unload(); + } else { + // contents not recognized + // nothing to be done -- partitions are created as unrecognized + } + return error; +} diff --git a/src/kernel/core/disk_device_manager/jobs/KScanPartitionJob.h b/src/kernel/core/disk_device_manager/jobs/KScanPartitionJob.h index 26c85cf623..8a8db88804 100644 --- a/src/kernel/core/disk_device_manager/jobs/KScanPartitionJob.h +++ b/src/kernel/core/disk_device_manager/jobs/KScanPartitionJob.h @@ -3,17 +3,22 @@ #ifndef _K_DISK_DEVICE_SCAN_PARTITION_JOB_H #define _K_DISK_DEVICE_SCAN_PARTITION_JOB_H +#include "KDiskDeviceJob.h" + namespace BPrivate { namespace DiskDevice { -#include "KDiskDeviceJob.h" +class KPartition; class KScanPartitionJob : public KDiskDeviceJob { public: - KScanPartitionJob(partition_id partition); + KScanPartitionJob(partition_id partitionID); virtual ~KScanPartitionJob(); virtual status_t Do(); + +private: + status_t _ScanPartition(KPartition *partition); }; } // namespace DiskDevice