Implemented a preliminary disk device scanning in KDiskDeviceManager.
Some changes to KPartition, KDiskDevice, KDiskSystem on this way. Still missing is KPartition::Publish() and its invocation in KDiskDeviceManager. Then everything should be in place to start with porting the scanning parts of our disk system modules. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3486 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
f3df767f76
commit
ef9b1b52ee
@ -23,7 +23,10 @@ public:
|
||||
KDiskDevice(partition_id id = -1);
|
||||
virtual ~KDiskDevice();
|
||||
|
||||
status_t SetTo(const char *path);
|
||||
void Unset();
|
||||
status_t InitCheck() const;
|
||||
// TODO: probably superfluous
|
||||
|
||||
// A read lock owner can be sure that the device (incl. all of its
|
||||
// partitions won't be changed).
|
||||
@ -64,6 +67,8 @@ public:
|
||||
team_id ShadowOwner() const;
|
||||
|
||||
private:
|
||||
void _InitPartitionData();
|
||||
|
||||
disk_device_data fDeviceData;
|
||||
RWLocker fLocker;
|
||||
int fFD;
|
||||
|
@ -44,12 +44,13 @@ public:
|
||||
|
||||
KDiskDevice *RegisterDevice(const char *path, bool noShadow = true);
|
||||
KDiskDevice *RegisterDevice(partition_id id, bool noShadow = true);
|
||||
KDiskDevice *RegisterNextDevice(int32 *cookie);
|
||||
KPartition *RegisterPartition(const char *path, bool noShadow = true);
|
||||
KPartition *RegisterPartition(partition_id id, bool noShadow = true);
|
||||
|
||||
// manager must be locked
|
||||
int32 CountDiskDevices();
|
||||
KDiskDevice *DiskDeviceAt(int32 index);
|
||||
int32 CountDevices();
|
||||
KDiskDevice *DeviceAt(int32 index);
|
||||
|
||||
bool PartitionAdded(KPartition *partition); // implementation internal
|
||||
bool PartitionRemoved(KPartition *partition); //
|
||||
@ -74,16 +75,24 @@ public:
|
||||
int32 CountDiskSystems();
|
||||
KDiskSystem *DiskSystemAt(int32 index);
|
||||
|
||||
KDiskSystem *LoadDiskSystem(disk_system_id id);
|
||||
KDiskSystem *LoadNextDiskSystem(int32 *cookie);
|
||||
|
||||
// Watching
|
||||
|
||||
// TODO: Watching service for the kernel. The userland watching is handled
|
||||
// by the registrar.
|
||||
|
||||
status_t InitialDeviceScan();
|
||||
|
||||
private:
|
||||
status_t _AddPartitioningSystem(const char *name);
|
||||
status_t _AddFileSystem(const char *name);
|
||||
status_t _AddDiskSystem(KDiskSystem *diskSystem);
|
||||
|
||||
status_t _Scan(const char *path);
|
||||
status_t _ScanPartition(KPartition *partition);
|
||||
|
||||
BLocker fLock;
|
||||
List<KDiskDevice*> fDevices; // TODO: Optimize!
|
||||
List<KPartition*> fPartitions; //
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
virtual bool IsFileSystem() const;
|
||||
bool IsPartitioningSystem() const;
|
||||
|
||||
// manager will be locked
|
||||
status_t Load(); // load/unload -- can be nested
|
||||
void Unload(); //
|
||||
bool IsLoaded() const;
|
||||
|
@ -139,6 +139,9 @@ public:
|
||||
KDiskSystem *DiskSystem() const;
|
||||
void SetParentDiskSystem(KDiskSystem *diskSystem);
|
||||
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
|
||||
// it is unset here.
|
||||
|
||||
void SetCookie(void *cookie);
|
||||
void *Cookie() const;
|
||||
@ -148,6 +151,7 @@ public:
|
||||
|
||||
private:
|
||||
void _UpdateChildIndices(int32 index);
|
||||
static int32 _NextID();
|
||||
|
||||
protected:
|
||||
partition_data fPartitionData;
|
||||
@ -157,6 +161,7 @@ protected:
|
||||
KDiskSystem *fDiskSystem;
|
||||
KDiskSystem *fParentDiskSystem;
|
||||
int32 fReferenceCount;
|
||||
static int32 fNextID;
|
||||
};
|
||||
|
||||
} // namespace DiskDevice
|
||||
|
@ -1,5 +1,11 @@
|
||||
// KDiskDevice.cpp
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <Drivers.h>
|
||||
|
||||
#include "KDiskDevice.h"
|
||||
#include "KDiskDeviceUtils.h"
|
||||
|
||||
@ -12,9 +18,59 @@ KDiskDevice::KDiskDevice(partition_id id)
|
||||
fMediaStatus(B_ERROR),
|
||||
fShadowOwner(-1)
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
// destructor
|
||||
KDiskDevice::~KDiskDevice()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
// SetTo
|
||||
status_t
|
||||
KDiskDevice::SetTo(const char *path)
|
||||
{
|
||||
// check initialization and parameter
|
||||
status_t error = InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (!path)
|
||||
return B_BAD_VALUE;
|
||||
Unset();
|
||||
// set the path
|
||||
error = set_string(fDeviceData.path, path);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// open the device
|
||||
fFD = open(path, O_RDONLY);
|
||||
if (fFD < 0)
|
||||
return errno;
|
||||
// get device geometry and media status
|
||||
// TODO: files need to be handled differently
|
||||
if (ioctl(fFD, B_GET_MEDIA_STATUS, &fMediaStatus) == 0
|
||||
&& ioctl(fFD, B_GET_GEOMETRY, &fDeviceData.geometry) == 0) {
|
||||
_InitPartitionData();
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
KDiskDevice::Unset()
|
||||
{
|
||||
if (fFD >= 0) {
|
||||
close(fFD);
|
||||
fFD = -1;
|
||||
}
|
||||
fMediaStatus = B_ERROR;
|
||||
fShadowOwner = -1;
|
||||
fDeviceData.id = -1;
|
||||
fDeviceData.flags = 0;
|
||||
fDeviceData.path = NULL;
|
||||
if (fDeviceData.path) {
|
||||
free(fDeviceData.path);
|
||||
fDeviceData.path = NULL;
|
||||
}
|
||||
fDeviceData.geometry.bytes_per_sector = 0;
|
||||
fDeviceData.geometry.sectors_per_track = 0;
|
||||
fDeviceData.geometry.cylinder_count = 0;
|
||||
@ -25,12 +81,6 @@ KDiskDevice::KDiskDevice(partition_id id)
|
||||
fDeviceData.geometry.write_once = false;
|
||||
}
|
||||
|
||||
// destructor
|
||||
KDiskDevice::~KDiskDevice()
|
||||
{
|
||||
free(fDeviceData.path);
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
status_t
|
||||
KDiskDevice::InitCheck() const
|
||||
@ -178,3 +228,16 @@ KDiskDevice::ShadowOwner() const
|
||||
return fShadowOwner;
|
||||
}
|
||||
|
||||
// _InitPartitionData
|
||||
void
|
||||
KDiskDevice::_InitPartitionData()
|
||||
{
|
||||
fDeviceData.id = fPartitionData.id;
|
||||
fPartitionData.block_size = fDeviceData.geometry.bytes_per_sector;
|
||||
fPartitionData.offset = 0;
|
||||
fPartitionData.size = (off_t)fPartitionData.block_size
|
||||
* fDeviceData.geometry.sectors_per_track
|
||||
* fDeviceData.geometry.cylinder_count
|
||||
* fDeviceData.geometry.head_count;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
// KDiskDeviceManager.cpp
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <module.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "KDiskDevice.h"
|
||||
#include "KDiskDeviceManager.h"
|
||||
@ -188,6 +192,26 @@ KDiskDeviceManager::RegisterDevice(partition_id id, bool noShadow)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// RegisterNextDevice
|
||||
KDiskDevice *
|
||||
KDiskDeviceManager::RegisterNextDevice(int32 *cookie)
|
||||
{
|
||||
if (!cookie)
|
||||
return NULL;
|
||||
if (ManagerLocker locker = this) {
|
||||
// TODO: This loop assumes that the device list is ordered. Make sure
|
||||
// that this is really the case.
|
||||
for (int32 i = 0; KDiskDevice *device = fDevices.ItemAt(i); i++) {
|
||||
if (device->ID() >= *cookie) {
|
||||
device->Register();
|
||||
*cookie = device->ID() + 1;
|
||||
return device;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// RegisterPartition
|
||||
KPartition *
|
||||
KDiskDeviceManager::RegisterPartition(const char *path, bool noShadow)
|
||||
@ -214,18 +238,18 @@ KDiskDeviceManager::RegisterPartition(partition_id id, bool noShadow)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// CountDiskDevices
|
||||
// CountDevices
|
||||
int32
|
||||
KDiskDeviceManager::CountDiskDevices()
|
||||
KDiskDeviceManager::CountDevices()
|
||||
{
|
||||
if (ManagerLocker locker = this)
|
||||
return fDevices.CountItems();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// DiskDeviceAt
|
||||
// DiskAt
|
||||
KDiskDevice *
|
||||
KDiskDeviceManager::DiskDeviceAt(int32 index)
|
||||
KDiskDeviceManager::DeviceAt(int32 index)
|
||||
{
|
||||
if (ManagerLocker locker = this)
|
||||
return fDevices.ItemAt(index);
|
||||
@ -330,6 +354,68 @@ KDiskDeviceManager::DiskSystemAt(int32 index)
|
||||
return fDiskSystems.ItemAt(index);
|
||||
}
|
||||
|
||||
// LoadDiskSystem
|
||||
KDiskSystem *
|
||||
KDiskDeviceManager::LoadDiskSystem(disk_system_id id)
|
||||
{
|
||||
KDiskSystem *diskSystem = NULL;
|
||||
if (ManagerLocker locker = this) {
|
||||
diskSystem = DiskSystemWithID(id);
|
||||
if (diskSystem && diskSystem->Load() != B_OK)
|
||||
diskSystem = NULL;
|
||||
}
|
||||
return diskSystem;
|
||||
}
|
||||
|
||||
// LoadNextDiskSystem
|
||||
KDiskSystem *
|
||||
KDiskDeviceManager::LoadNextDiskSystem(int32 *cookie)
|
||||
{
|
||||
if (!cookie)
|
||||
return NULL;
|
||||
if (ManagerLocker locker = this) {
|
||||
// TODO: This loop assumes that the disk system list is ordered.
|
||||
// Make sure that this is really the case.
|
||||
for (int32 i = 0; KDiskSystem *diskSystem = DiskSystemAt(i); i++) {
|
||||
if (diskSystem->ID() >= *cookie) {
|
||||
if (diskSystem->Load() == B_OK) {
|
||||
*cookie = diskSystem->ID() + 1;
|
||||
return diskSystem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// InitialDeviceScan
|
||||
status_t
|
||||
KDiskDeviceManager::InitialDeviceScan()
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
// scan for devices
|
||||
if (ManagerLocker locker = this)
|
||||
error = _Scan("/dev/disk");
|
||||
// scan the devices for partitions
|
||||
// TODO: This is only provisional.
|
||||
if (error == B_OK) {
|
||||
int32 cookie = 0;
|
||||
while (KDiskDevice *device = RegisterNextDevice(&cookie)) {
|
||||
if (device->WriteLock()) {
|
||||
// scan the device
|
||||
error = _ScanPartition(device);
|
||||
if (error != B_OK) {
|
||||
// ...
|
||||
error = B_OK;
|
||||
}
|
||||
device->WriteUnlock();
|
||||
}
|
||||
device->Unregister();
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _AddPartitioningSystem
|
||||
status_t
|
||||
KDiskDeviceManager::_AddPartitioningSystem(const char *name)
|
||||
@ -372,6 +458,107 @@ KDiskDeviceManager::_AddDiskSystem(KDiskSystem *diskSystem)
|
||||
return error;
|
||||
}
|
||||
|
||||
// _Scan
|
||||
status_t
|
||||
KDiskDeviceManager::_Scan(const char *path)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
struct stat st;
|
||||
if (lstat(path, &st) < 0)
|
||||
return errno;
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
// a directory: iterate through its contents
|
||||
DIR *dir = opendir(path);
|
||||
if (!dir)
|
||||
return errno;
|
||||
while (dirent *entry = readdir(dir)) {
|
||||
// skip "." and ".."
|
||||
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
|
||||
continue;
|
||||
if (strlen(path) + strlen(entry->d_name) + 1 >= B_PATH_NAME_LENGTH)
|
||||
continue;
|
||||
char entryPath[B_PATH_NAME_LENGTH];
|
||||
sprintf(entryPath, "%s/%s", path, entry->d_name);
|
||||
_Scan(entryPath);
|
||||
}
|
||||
closedir(dir);
|
||||
} else {
|
||||
// not a directory
|
||||
// check, if it is named "raw"
|
||||
int32 len = strlen(path);
|
||||
int32 leafLen = strlen("/raw");
|
||||
if (len <= leafLen || strcmp(path + len - leafLen, "/raw"))
|
||||
return B_ERROR;
|
||||
// create a KDiskDevice for it
|
||||
KDiskDevice *device = new(nothrow) KDiskDevice;
|
||||
if (!device)
|
||||
return B_NO_MEMORY;
|
||||
// init the KDiskDevice
|
||||
status_t error = device->SetTo(path);
|
||||
// add the device
|
||||
if (error == B_OK && !fDevices.AddItem(device))
|
||||
error = B_NO_MEMORY;
|
||||
// cleanup on error
|
||||
if (error != B_OK)
|
||||
delete device;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _ScanPartition
|
||||
status_t
|
||||
KDiskDeviceManager::_ScanPartition(KPartition *partition)
|
||||
{
|
||||
// the partition's device must be write-locked
|
||||
if (!partition)
|
||||
return B_BAD_VALUE;
|
||||
// find the disk system that returns the best priority for this partition
|
||||
float bestPriority = -1;
|
||||
KDiskSystem *bestDiskSystem = NULL;
|
||||
void *bestCookie = NULL;
|
||||
int32 itCookie;
|
||||
while (KDiskSystem *diskSystem = LoadNextDiskSystem(&itCookie)) {
|
||||
void *cookie = NULL;
|
||||
float priority = diskSystem->Identify(partition, &cookie);
|
||||
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
|
||||
status_t error = B_OK;
|
||||
if (bestDiskSystem) {
|
||||
error = bestDiskSystem->Scan(partition, bestCookie);
|
||||
if (error == B_OK) {
|
||||
partition->SetDiskSystem(bestDiskSystem);
|
||||
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
|
||||
child->SetParentDiskSystem(bestDiskSystem);
|
||||
_ScanPartition(child);
|
||||
}
|
||||
} else {
|
||||
// TODO: Handle the 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;
|
||||
}
|
||||
|
||||
|
||||
// singleton instance
|
||||
KDiskDeviceManager *KDiskDeviceManager::fDefaultManager = NULL;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "KDiskDeviceManager.h"
|
||||
#include "KDiskDeviceUtils.h"
|
||||
#include "KDiskSystem.h"
|
||||
|
||||
@ -75,6 +76,7 @@ KDiskSystem::IsPartitioningSystem() const
|
||||
status_t
|
||||
KDiskSystem::Load()
|
||||
{
|
||||
ManagerLocker locker(KDiskDeviceManager::Default());
|
||||
status_t error = B_OK;
|
||||
if (fLoadCounter == 0)
|
||||
error = LoadModule();
|
||||
@ -87,6 +89,7 @@ KDiskSystem::Load()
|
||||
void
|
||||
KDiskSystem::Unload()
|
||||
{
|
||||
ManagerLocker locker(KDiskDeviceManager::Default());
|
||||
if (fLoadCounter > 0 && --fLoadCounter == 0)
|
||||
UnloadModule();
|
||||
}
|
||||
@ -95,6 +98,7 @@ KDiskSystem::Unload()
|
||||
bool
|
||||
KDiskSystem::IsLoaded() const
|
||||
{
|
||||
ManagerLocker locker(KDiskDeviceManager::Default());
|
||||
return (fLoadCounter > 0);
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,10 @@
|
||||
#include "KDiskDevice.h"
|
||||
#include "KDiskDeviceManager.h"
|
||||
#include "KDiskDeviceUtils.h"
|
||||
#include "KDiskSystem.h"
|
||||
#include "KPartition.h"
|
||||
|
||||
using namespace std;
|
||||
using BPrivate::DiskDevice::KDiskSystem;
|
||||
|
||||
// constructor
|
||||
KPartition::KPartition(partition_id id)
|
||||
@ -29,7 +29,7 @@ KPartition::KPartition(partition_id id)
|
||||
fParentDiskSystem(NULL),
|
||||
fReferenceCount(0)
|
||||
{
|
||||
fPartitionData.id = id;
|
||||
fPartitionData.id = (id >= 0 ? id : _NextID());
|
||||
fPartitionData.offset = 0;
|
||||
fPartitionData.size = 0;
|
||||
fPartitionData.block_size = 0;
|
||||
@ -600,7 +600,15 @@ KPartition::IsShadowPartition() const
|
||||
void
|
||||
KPartition::SetDiskSystem(KDiskSystem *diskSystem)
|
||||
{
|
||||
// unload former disk system
|
||||
if (fDiskSystem) {
|
||||
fDiskSystem->Unload();
|
||||
fDiskSystem = NULL;
|
||||
}
|
||||
// set and load new one
|
||||
fDiskSystem = diskSystem;
|
||||
if (fDiskSystem)
|
||||
fDiskSystem->Load();
|
||||
}
|
||||
|
||||
// DiskSystem
|
||||
@ -614,7 +622,15 @@ KPartition::DiskSystem() const
|
||||
void
|
||||
KPartition::SetParentDiskSystem(KDiskSystem *diskSystem)
|
||||
{
|
||||
// unload former disk system
|
||||
if (fParentDiskSystem) {
|
||||
fParentDiskSystem->Unload();
|
||||
fParentDiskSystem = NULL;
|
||||
}
|
||||
// set and load new one
|
||||
fParentDiskSystem = diskSystem;
|
||||
if (fParentDiskSystem)
|
||||
fParentDiskSystem->Load();
|
||||
}
|
||||
|
||||
// ParentDiskSystem
|
||||
@ -660,3 +676,14 @@ KPartition::_UpdateChildIndices(int32 index)
|
||||
child->SetIndex(index);
|
||||
}
|
||||
|
||||
// _NextID
|
||||
int32
|
||||
KPartition::_NextID()
|
||||
{
|
||||
return atomic_add(&fNextID, 1);
|
||||
}
|
||||
|
||||
|
||||
// fNextID
|
||||
int32 KPartition::fNextID = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user