diff --git a/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h b/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h index f92524702b..99afe4b8ed 100644 --- a/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h +++ b/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h @@ -1,11 +1,17 @@ -// KDiskDeviceManager.h - +/* + * Copyright 2004-2006, 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. + */ #ifndef _K_DISK_DEVICE_MANAGER_H #define _K_DISK_DEVICE_MANAGER_H + #include "disk_device_manager.h" #include "Locker.h" + namespace BPrivate { namespace DiskDevice { @@ -61,7 +67,7 @@ public: // unregistered by the caller. partition_id CreateFileDevice(const char *filePath, - bool *newlyCreated = NULL); + bool *newlyCreated = NULL, bool async = true); status_t DeleteFileDevice(const char *filePath); status_t DeleteFileDevice(partition_id id); @@ -130,7 +136,7 @@ private: bool updateBusyPartitions); status_t _Scan(const char *path); - status_t _ScanPartition(KPartition *partition); + status_t _ScanPartition(KPartition *partition, bool async); // the manager must be locked and the device write locked struct DeviceMap; diff --git a/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp b/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp index 5e8769ef21..c34fb0fb59 100644 --- a/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp @@ -1,23 +1,11 @@ -/* -** Copyright 2003-2004, Ingo Weinhold, bonefish@cs.tu-berlin.de. All rights reserved. -** Distributed under the terms of the Haiku License. -*/ +/* + * Copyright 2004-2006, 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 - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - #include "KDiskDevice.h" #include "KDiskDeviceJob.h" #include "KDiskDeviceJobFactory.h" @@ -33,6 +21,20 @@ #include "KPath.h" #include "KShadowPartition.h" +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + // debugging //#define DBG(x) #define DBG(x) x @@ -515,7 +517,7 @@ KDiskDeviceManager::WriteLockPartition(partition_id id) // CreateFileDevice partition_id -KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated) +KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated, bool async) { if (!filePath) return B_BAD_VALUE; @@ -543,6 +545,7 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated) // initialize and add the device error = device->SetTo(filePath); + // Note: Here we are allowed to lock a device although already having // the manager locked, since it is not yet added to the manager. DeviceWriteLocker deviceLocker(device); @@ -553,7 +556,7 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated) // scan device if (error == B_OK) { - _ScanPartition(device); + _ScanPartition(device, async); if (newlyCreated) *newlyCreated = true; @@ -901,19 +904,21 @@ status_t KDiskDeviceManager::InitialDeviceScan() { status_t error = B_ERROR; + // scan for devices if (ManagerLocker locker = this) { error = _Scan("/dev/disk"); if (error != B_OK) return error; } + // scan the devices for partitions int32 cookie = 0; while (KDiskDevice *device = RegisterNextDevice(&cookie)) { PartitionRegistrar _(device, true); if (DeviceWriteLocker deviceLocker = device) { if (ManagerLocker locker = this) { - error = _ScanPartition(device); + error = _ScanPartition(device, false); if (error != B_OK) break; } else @@ -1152,30 +1157,43 @@ DBG(OUT(" found device: %s\n", path)); The device must be write locked, the manager must be locked. */ status_t -KDiskDeviceManager::_ScanPartition(KPartition *partition) +KDiskDeviceManager::_ScanPartition(KPartition *partition, bool async) { if (!partition) return B_BAD_VALUE; - // create a new job queue for the device - KDiskDeviceJobQueue *jobQueue = new(nothrow) KDiskDeviceJobQueue; - if (!jobQueue) - return B_NO_MEMORY; - jobQueue->SetDevice(partition->Device()); - // create a job for scanning the device and add it to the job queue + + if (async) { + // create a new job queue for the device + KDiskDeviceJobQueue *jobQueue = new(nothrow) KDiskDeviceJobQueue; + if (!jobQueue) + return B_NO_MEMORY; + jobQueue->SetDevice(partition->Device()); + // create a job for scanning the device and add it to the job queue + KDiskDeviceJob *job = fJobFactory->CreateScanPartitionJob(partition->ID()); + if (!job) { + delete jobQueue; + return B_NO_MEMORY; + } + if (!jobQueue->AddJob(job)) { + delete jobQueue; + delete job; + return B_NO_MEMORY; + } + // add the job queue + status_t error = AddJobQueue(jobQueue); + if (error != B_OK) + delete jobQueue; + return error; + } + KDiskDeviceJob *job = fJobFactory->CreateScanPartitionJob(partition->ID()); - if (!job) { - delete jobQueue; + if (job == NULL) return B_NO_MEMORY; - } - if (!jobQueue->AddJob(job)) { - delete jobQueue; - delete job; - return B_NO_MEMORY; - } - // add the job queue - status_t error = AddJobQueue(jobQueue); - if (error != B_OK) - delete jobQueue; - return error; + + status_t status = job->Do(); + UpdateBusyPartitions(partition->Device()); + + delete job; + return status; } diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 8aeac98a01..e1d9503ab5 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -5152,13 +5152,12 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags, // Partition not found: This either means, the user supplied // an invalid path, or the path refers to an image file. We try // to let the DDM create a file device for the path. - partition_id deviceID = ddm->CreateFileDevice( - normalizedDevice.Path(), &newlyCreatedFileDevice); + partition_id deviceID = ddm->CreateFileDevice(normalizedDevice.Path(), + &newlyCreatedFileDevice, false); if (deviceID >= 0) { partition = ddm->RegisterPartition(deviceID, true); if (newlyCreatedFileDevice) fileDeviceDeleter.id = deviceID; -// TODO: We must wait here, until the partition scan job is done. } } @@ -5182,7 +5181,9 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags, return B_ERROR; } } + DeviceWriteLocker writeLocker(diskDevice, true); + // this takes over the write lock acquired before if (partition) { // make sure, that the partition is not busy diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index 4b2430c694..5cc002b49e 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -206,14 +206,7 @@ get_boot_partitions(kernel_args *args, PartitionStack &partitions) KDiskDeviceManager *manager = KDiskDeviceManager::Default(); status_t status = manager->InitialDeviceScan(); - if (status == B_OK) { - // ToDo: do this for real... (no hacks allowed :)) - for (;;) { - snooze(500000); - if (manager->CountJobs() == 0) - break; - } - } else { + if (status != B_OK) { dprintf("KDiskDeviceManager::InitialDeviceScan() failed: %s\n", strerror(status)); return status; }