I tried to follow the example of PartitionMapAddOn and implemented more

stuff for the ExtendedPartitionAddOn. If I understand correctly, from the
point of view of the Disk Device API, ExtendedPartitionAddOn is a disk system
which supports child partitions and is analogous to PartitionMapAddOn. The
type string for the supported child partitions is probably wrong, since I
used "Intel Logical Partition".... In fact, the types currently returned by
PartitionMapAddOn are not as intended either. We will have to think of how
we want this particular feature to work.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23877 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2008-02-05 17:57:40 +00:00
parent af4ad10c3e
commit fd6477d3e6
2 changed files with 409 additions and 1 deletions

View File

@ -9,17 +9,42 @@
#include <DiskDeviceTypes.h>
#include <MutablePartition.h>
#include <PartitioningInfo.h>
#include <AutoDeleter.h>
using std::nothrow;
static const uint32 kDiskSystemFlags =
0
// | B_DISK_SYSTEM_SUPPORTS_CHECKING
// | B_DISK_SYSTEM_SUPPORTS_REPAIRING
// | B_DISK_SYSTEM_SUPPORTS_RESIZING
// | B_DISK_SYSTEM_SUPPORTS_MOVING
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
| B_DISK_SYSTEM_SUPPORTS_INITIALIZING
// | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
// | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
// | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
// | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME
| B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
// | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS
| B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD
| B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD
// | B_DISK_SYSTEM_SUPPORTS_NAME
;
// #pragma mark - ExtendedPartitionAddOn
// constructor
ExtendedPartitionAddOn::ExtendedPartitionAddOn()
: BDiskSystemAddOn(kPartitionTypeIntelExtended, 0)
: BDiskSystemAddOn(kPartitionTypeIntelExtended, kDiskSystemFlags)
{
}
@ -51,6 +76,79 @@ ExtendedPartitionAddOn::CreatePartitionHandle(BMutablePartition* partition,
}
// CanInitialize
bool
ExtendedPartitionAddOn::CanInitialize(const BMutablePartition* partition)
{
// If it's big enough, we can initialize it.
return partition->Size() >= 2 * SECTOR_SIZE;
}
// GetInitializationParameterEditor
status_t
ExtendedPartitionAddOn::GetInitializationParameterEditor(
const BMutablePartition* partition, BDiskDeviceParameterEditor** editor)
{
// Nothing to edit, really.
*editor = NULL;
return B_OK;
}
// ValidateInitialize
status_t
ExtendedPartitionAddOn::ValidateInitialize(const BMutablePartition* partition,
BString* name, const char* parameters)
{
if (!CanInitialize(partition)
|| parameters != NULL && strlen(parameters) > 0) {
return B_BAD_VALUE;
}
// we don't support a content name
if (name != NULL)
name->Truncate(0);
return B_OK;
}
// Initialize
status_t
ExtendedPartitionAddOn::Initialize(BMutablePartition* partition,
const char* name, const char* parameters, BPartitionHandle** _handle)
{
if (!CanInitialize(partition)
|| name != NULL && strlen(name) > 0
|| parameters != NULL && strlen(parameters) > 0) {
return B_BAD_VALUE;
}
// create the handle
ExtendedPartitionHandle* handle
= new(nothrow) ExtendedPartitionHandle(partition);
if (!handle)
return B_NO_MEMORY;
ObjectDeleter<ExtendedPartitionHandle> handleDeleter(handle);
// init the partition
status_t error = partition->SetContentType(Name());
if (error != B_OK)
return error;
// TODO: The content type could as well be set by the caller.
partition->SetContentName(NULL);
partition->SetContentParameters(NULL);
partition->SetBlockSize(SECTOR_SIZE);
partition->SetContentSize(partition->Size() / SECTOR_SIZE * SECTOR_SIZE);
*_handle = handleDeleter.Detach();
return B_OK;
}
// #pragma mark - ExtendedPartitionHandle
@ -107,3 +205,281 @@ ExtendedPartitionHandle::Init()
return B_OK;
}
// SupportedOperations
uint32
ExtendedPartitionHandle::SupportedOperations(uint32 mask)
{
uint32 flags = B_DISK_SYSTEM_SUPPORTS_INITIALIZING;
// creating child
if (mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) {
BPartitioningInfo info;
if (GetPartitioningInfo(&info) == B_OK
&& info.CountPartitionableSpaces() > 1) {
flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD;
}
}
return flags;
}
// SupportedChildOperations
uint32
ExtendedPartitionHandle::SupportedChildOperations(
const BMutablePartition* child, uint32 mask)
{
return B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD;
}
// GetNextSupportedType
status_t
ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child,
int32* cookie, BString* type)
{
if (*cookie != 0)
return B_ENTRY_NOT_FOUND;
*cookie = *cookie + 1;
*type = kPartitionTypeIntelLogical;
return B_OK;
}
// GetPartitioningInfo
status_t
ExtendedPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info)
{
// NOTE stippi: At first I tried to use the fPrimaryPartition
// here but it does not return any LogicalPartitions. What
// happens now is probably what used to happen before, though
// I don't understand *where*, since this handle type never
// implemented this virtual function.
// init to the full size (minus the first sector)
BMutablePartition* partition = Partition();
off_t offset = partition->Offset();// + SECTOR_SIZE;
off_t size = partition->Size();//- SECTOR_SIZE;
status_t error = info->SetTo(offset, size);
if (error != B_OK)
return error;
// exclude the space of the existing logical partitions
int32 count = partition->CountChildren();
printf("%ld logical partitions\n", count);
for (int32 i = 0; i < count; i++) {
BMutablePartition* child = partition->ChildAt(i);
// TODO: Does this correctly account for the partition table
// sectors? Preceeding each logical partition should be a
// sector for the partition table entry. Those entries form
// the linked list of "inner extended partition" + "real partition"
// Following the logic above (copied from PartitionMapAddOn),
// the outer size includes the first sector and is therefor
// what we need here.
error = info->ExcludeOccupiedSpace(child->Offset(), child->Size());
printf(" %ld: offset = %lld (relative: %lld), size = %lld\n", i,
child->Offset(), child->Offset() - offset, child->Size());
if (error != B_OK)
return error;
}
info->PrintToStream();
return B_OK;
}
// GetChildCreationParameterEditor
status_t
ExtendedPartitionHandle::GetChildCreationParameterEditor(const char* type,
BDiskDeviceParameterEditor** editor)
{
// TODO: We actually need an editor here.
*editor = NULL;
return B_OK;
}
// ValidateCreateChild
status_t
ExtendedPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size,
const char* typeString, BString* name, const char* parameters)
{
// check type
if (!typeString || strcmp(typeString, kPartitionTypeIntelLogical) != 0)
return B_BAD_VALUE;
// check name
if (name)
name->Truncate(0);
// check parameters
// TODO:...
return B_NOT_SUPPORTED;
// // check the free space situation
// BPartitioningInfo info;
// status_t error = GetPartitioningInfo(&info);
// if (error != B_OK)
// return error;
//
// // any space in the partition at all?
// int32 spacesCount = info.CountPartitionableSpaces();
// if (spacesCount == 0)
// return B_BAD_VALUE;
//
// // check offset and size
// off_t offset = sector_align(*_offset);
// off_t size = sector_align(*_size);
// // TODO: Rather round size up?
// off_t end = offset + size;
//
// // get the first partitionable space the requested interval intersects with
// int32 spaceIndex = -1;
// int32 closestSpaceIndex = -1;
// off_t closestSpaceDistance = 0;
// for (int32 i = 0; i < spacesCount; i++) {
// off_t spaceOffset, spaceSize;
// info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
// off_t spaceEnd = spaceOffset + spaceSize;
//
// if (spaceOffset >= offset && spaceOffset < end
// || offset >= spaceOffset && offset < spaceEnd) {
// spaceIndex = i;
// break;
// }
//
// off_t distance;
// if (offset < spaceOffset)
// distance = spaceOffset - end;
// else
// distance = spaceEnd - offset;
//
// if (closestSpaceIndex == -1 || distance < closestSpaceDistance) {
// closestSpaceIndex = i;
// closestSpaceDistance = distance;
// }
// }
//
// // get the space we found
// off_t spaceOffset, spaceSize;
// info.GetPartitionableSpaceAt(
// spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset,
// &spaceSize);
// off_t spaceEnd = spaceOffset + spaceSize;
//
// // If the requested intervald doesn't intersect with any space yet, move
// // it, so that it does.
// if (spaceIndex < 0) {
// spaceIndex = closestSpaceIndex;
// if (offset < spaceOffset) {
// offset = spaceOffset;
// end = offset + size;
// } else {
// end = spaceEnd;
// offset = end - size;
// }
// }
//
// // move/shrink the interval, so that it fully lies within the space
// if (offset < spaceOffset) {
// offset = spaceOffset;
// end = offset + size;
// if (end > spaceEnd) {
// end = spaceEnd;
// size = end - offset;
// }
// } else if (end > spaceEnd) {
// end = spaceEnd;
// offset = end - size;
// if (offset < spaceOffset) {
// offset = spaceOffset;
// size = end - offset;
// }
// }
//
// *_offset = offset;
// *_size = size;
//
// return B_OK;
}
// CreateChild
status_t
ExtendedPartitionHandle::CreateChild(off_t offset, off_t size,
const char* typeString, const char* name, const char* parameters,
BMutablePartition** _child)
{
// check type
if (!typeString || strcmp(typeString, kPartitionTypeIntelLogical) != 0)
return B_BAD_VALUE;
// check name
if (name && strlen(name) > 0)
return B_BAD_VALUE;
// check parameters
// TODO:...
return B_NOT_SUPPORTED;
// // offset properly aligned?
// if (offset != sector_align(offset) || size != sector_align(size))
// return B_BAD_VALUE;
//
// // check the free space situation
// BPartitioningInfo info;
// status_t error = GetPartitioningInfo(&info);
// if (error != B_OK)
// return error;
//
// bool foundSpace = false;
// off_t end = offset + size;
// int32 spacesCount = info.CountPartitionableSpaces();
// for (int32 i = 0; i < spacesCount; i++) {
// off_t spaceOffset, spaceSize;
// info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
// off_t spaceEnd = spaceOffset + spaceSize;
//
// if (offset >= spaceOffset && end <= spaceEnd) {
// foundSpace = true;
// break;
// }
// }
//
// if (!foundSpace)
// return B_BAD_VALUE;
//
// // everything looks good, do it
//
// // create the child
// // (Note: the primary partition index is indeed the child index, since
// // we picked the first empty primary partition.)
// BMutablePartition* partition = Partition();
// BMutablePartition* child;
// error = partition->CreateChild(primary->Index(), typeString, NULL,
// parameters, &child);
// if (error != B_OK)
// return error;
//
// // init the child
// child->SetOffset(offset);
// child->SetSize(size);
// child->SetBlockSize(SECTOR_SIZE);
// //child->SetFlags(0);
// child->SetChildCookie(primary);
//
// // init the primary partition
// bool active = false;
// // TODO: Get from parameters!
// primary->SetTo(offset, size, type.Type(), active);
//
//// TODO: If the child is an extended partition, we should trigger its
//// initialization.
//
// *_child = child;
// return B_OK;
}

View File

@ -19,6 +19,17 @@ public:
BMutablePartition* partition,
BPartitionHandle** handle);
virtual bool CanInitialize(
const BMutablePartition* partition);
virtual status_t GetInitializationParameterEditor(
const BMutablePartition* partition,
BDiskDeviceParameterEditor** editor);
virtual status_t ValidateInitialize(
const BMutablePartition* partition,
BString* name, const char* parameters);
virtual status_t Initialize(BMutablePartition* partition,
const char* name, const char* parameters,
BPartitionHandle** handle);
};
@ -30,6 +41,27 @@ public:
status_t Init();
virtual uint32 SupportedOperations(uint32 mask);
virtual uint32 SupportedChildOperations(
const BMutablePartition* child,
uint32 mask);
virtual status_t GetNextSupportedType(
const BMutablePartition* child,
int32* cookie, BString* type);
virtual status_t GetPartitioningInfo(BPartitioningInfo* info);
virtual status_t GetChildCreationParameterEditor(
const char* type,
BDiskDeviceParameterEditor** editor);
virtual status_t ValidateCreateChild(off_t* offset,
off_t* size, const char* type,
BString* name, const char* parameters);
virtual status_t CreateChild(off_t offset, off_t size,
const char* type, const char* name,
const char* parameters,
BMutablePartition** child);
private:
PrimaryPartition* fPrimaryPartition;
};