* KDiskDeviceManager::_ScanPartition() can now run synchronously (and execute the

scan job in the calling thread).
* KDiskDeviceManager::InitialDeviceScan() now runs synchronously, so that
  get_boot_partitions() doesn't need to do this ugly wait hack.
* KDiskDeviceManager::CreateFileDevice() can now run synchronously as well, which
  fixes a deadlock in fs_mount() - note, mounting file devices still doesn't work,
  though as Haiku's BFS doesn't allow this right now.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17334 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-05-05 10:54:10 +00:00
parent b02b72c448
commit 65bd831cbb
4 changed files with 74 additions and 56 deletions
@@ -1,11 +1,17 @@
// KDiskDeviceManager.h /*
* Copyright 2004-2006, Haiku, Inc. All rights reserved.
* Copyright 2003-2004, Ingo Weinhold, [email protected]. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _K_DISK_DEVICE_MANAGER_H #ifndef _K_DISK_DEVICE_MANAGER_H
#define _K_DISK_DEVICE_MANAGER_H #define _K_DISK_DEVICE_MANAGER_H
#include "disk_device_manager.h" #include "disk_device_manager.h"
#include "Locker.h" #include "Locker.h"
namespace BPrivate { namespace BPrivate {
namespace DiskDevice { namespace DiskDevice {
@@ -61,7 +67,7 @@ public:
// unregistered by the caller. // unregistered by the caller.
partition_id CreateFileDevice(const char *filePath, partition_id CreateFileDevice(const char *filePath,
bool *newlyCreated = NULL); bool *newlyCreated = NULL, bool async = true);
status_t DeleteFileDevice(const char *filePath); status_t DeleteFileDevice(const char *filePath);
status_t DeleteFileDevice(partition_id id); status_t DeleteFileDevice(partition_id id);
@@ -130,7 +136,7 @@ private:
bool updateBusyPartitions); bool updateBusyPartitions);
status_t _Scan(const char *path); 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 // the manager must be locked and the device write locked
struct DeviceMap; struct DeviceMap;
@@ -1,23 +1,11 @@
/* /*
** Copyright 2003-2004, Ingo Weinhold, [email protected]. All rights reserved. * Copyright 2004-2006, Haiku, Inc. All rights reserved.
** Distributed under the terms of the Haiku License. * Copyright 2003-2004, Ingo Weinhold, [email protected]. All rights reserved.
*/ *
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <util/kernel_cpp.h>
#include <dirent.h>
#include <errno.h>
#include <module.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <VectorMap.h>
#include <VectorSet.h>
#include "KDiskDevice.h" #include "KDiskDevice.h"
#include "KDiskDeviceJob.h" #include "KDiskDeviceJob.h"
#include "KDiskDeviceJobFactory.h" #include "KDiskDeviceJobFactory.h"
@@ -33,6 +21,20 @@
#include "KPath.h" #include "KPath.h"
#include "KShadowPartition.h" #include "KShadowPartition.h"
#include <VectorMap.h>
#include <VectorSet.h>
#include <KernelExport.h>
#include <util/kernel_cpp.h>
#include <dirent.h>
#include <errno.h>
#include <module.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
// debugging // debugging
//#define DBG(x) //#define DBG(x)
#define DBG(x) x #define DBG(x) x
@@ -515,7 +517,7 @@ KDiskDeviceManager::WriteLockPartition(partition_id id)
// CreateFileDevice // CreateFileDevice
partition_id partition_id
KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated) KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated, bool async)
{ {
if (!filePath) if (!filePath)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -543,6 +545,7 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated)
// initialize and add the device // initialize and add the device
error = device->SetTo(filePath); error = device->SetTo(filePath);
// Note: Here we are allowed to lock a device although already having // Note: Here we are allowed to lock a device although already having
// the manager locked, since it is not yet added to the manager. // the manager locked, since it is not yet added to the manager.
DeviceWriteLocker deviceLocker(device); DeviceWriteLocker deviceLocker(device);
@@ -553,7 +556,7 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated)
// scan device // scan device
if (error == B_OK) { if (error == B_OK) {
_ScanPartition(device); _ScanPartition(device, async);
if (newlyCreated) if (newlyCreated)
*newlyCreated = true; *newlyCreated = true;
@@ -901,19 +904,21 @@ status_t
KDiskDeviceManager::InitialDeviceScan() KDiskDeviceManager::InitialDeviceScan()
{ {
status_t error = B_ERROR; status_t error = B_ERROR;
// scan for devices // scan for devices
if (ManagerLocker locker = this) { if (ManagerLocker locker = this) {
error = _Scan("/dev/disk"); error = _Scan("/dev/disk");
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
// scan the devices for partitions // scan the devices for partitions
int32 cookie = 0; int32 cookie = 0;
while (KDiskDevice *device = RegisterNextDevice(&cookie)) { while (KDiskDevice *device = RegisterNextDevice(&cookie)) {
PartitionRegistrar _(device, true); PartitionRegistrar _(device, true);
if (DeviceWriteLocker deviceLocker = device) { if (DeviceWriteLocker deviceLocker = device) {
if (ManagerLocker locker = this) { if (ManagerLocker locker = this) {
error = _ScanPartition(device); error = _ScanPartition(device, false);
if (error != B_OK) if (error != B_OK)
break; break;
} else } else
@@ -1152,30 +1157,43 @@ DBG(OUT(" found device: %s\n", path));
The device must be write locked, the manager must be locked. The device must be write locked, the manager must be locked.
*/ */
status_t status_t
KDiskDeviceManager::_ScanPartition(KPartition *partition) KDiskDeviceManager::_ScanPartition(KPartition *partition, bool async)
{ {
if (!partition) if (!partition)
return B_BAD_VALUE; return B_BAD_VALUE;
// create a new job queue for the device
KDiskDeviceJobQueue *jobQueue = new(nothrow) KDiskDeviceJobQueue; if (async) {
if (!jobQueue) // create a new job queue for the device
return B_NO_MEMORY; KDiskDeviceJobQueue *jobQueue = new(nothrow) KDiskDeviceJobQueue;
jobQueue->SetDevice(partition->Device()); if (!jobQueue)
// create a job for scanning the device and add it to the job queue 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()); KDiskDeviceJob *job = fJobFactory->CreateScanPartitionJob(partition->ID());
if (!job) { if (job == NULL)
delete jobQueue;
return B_NO_MEMORY; return B_NO_MEMORY;
}
if (!jobQueue->AddJob(job)) { status_t status = job->Do();
delete jobQueue; UpdateBusyPartitions(partition->Device());
delete job;
return B_NO_MEMORY; delete job;
} return status;
// add the job queue
status_t error = AddJobQueue(jobQueue);
if (error != B_OK)
delete jobQueue;
return error;
} }
+4 -3
View File
@@ -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 // Partition not found: This either means, the user supplied
// an invalid path, or the path refers to an image file. We try // an invalid path, or the path refers to an image file. We try
// to let the DDM create a file device for the path. // to let the DDM create a file device for the path.
partition_id deviceID = ddm->CreateFileDevice( partition_id deviceID = ddm->CreateFileDevice(normalizedDevice.Path(),
normalizedDevice.Path(), &newlyCreatedFileDevice); &newlyCreatedFileDevice, false);
if (deviceID >= 0) { if (deviceID >= 0) {
partition = ddm->RegisterPartition(deviceID, true); partition = ddm->RegisterPartition(deviceID, true);
if (newlyCreatedFileDevice) if (newlyCreatedFileDevice)
fileDeviceDeleter.id = deviceID; 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; return B_ERROR;
} }
} }
DeviceWriteLocker writeLocker(diskDevice, true); DeviceWriteLocker writeLocker(diskDevice, true);
// this takes over the write lock acquired before
if (partition) { if (partition) {
// make sure, that the partition is not busy // make sure, that the partition is not busy
+1 -8
View File
@@ -206,14 +206,7 @@ get_boot_partitions(kernel_args *args, PartitionStack &partitions)
KDiskDeviceManager *manager = KDiskDeviceManager::Default(); KDiskDeviceManager *manager = KDiskDeviceManager::Default();
status_t status = manager->InitialDeviceScan(); status_t status = manager->InitialDeviceScan();
if (status == B_OK) { if (status != B_OK) {
// ToDo: do this for real... (no hacks allowed :))
for (;;) {
snooze(500000);
if (manager->CountJobs() == 0)
break;
}
} else {
dprintf("KDiskDeviceManager::InitialDeviceScan() failed: %s\n", strerror(status)); dprintf("KDiskDeviceManager::InitialDeviceScan() failed: %s\n", strerror(status));
return status; return status;
} }