* 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

View File

@ -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;

View File

@ -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 <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 "KDiskDeviceJob.h"
#include "KDiskDeviceJobFactory.h"
@ -33,6 +21,20 @@
#include "KPath.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
//#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;
}

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
// 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

View File

@ -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;
}