* Added open_partition to disk_device_manager

* Rewrote PartitionMapWriter
* Updated style to match current style guide for the intel partitioning system.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32235 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Bryce Groff
2009-08-10 22:28:47 +00:00
parent 99452e33a8
commit 1987b05aa0
10 changed files with 744 additions and 747 deletions
+2
View File
@@ -101,6 +101,8 @@ partition_data *get_partition(partition_id partitionID);
partition_data *get_parent_partition(partition_id partitionID); partition_data *get_parent_partition(partition_id partitionID);
partition_data *get_child_partition(partition_id partitionID, int32 index); partition_data *get_child_partition(partition_id partitionID, int32 index);
int open_partition(partition_id partitionID, int openMode);
// partition write access // partition write access
// (write lock required) // (write lock required)
partition_data *create_child_partition(partition_id partitionID, int32 index, partition_data *create_child_partition(partition_id partitionID, int32 index,
@@ -36,7 +36,7 @@ static const uint32 kDiskSystemFlags =
// | B_DISK_SYSTEM_SUPPORTS_MOVING // | B_DISK_SYSTEM_SUPPORTS_MOVING
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
| B_DISK_SYSTEM_SUPPORTS_INITIALIZING // | B_DISK_SYSTEM_SUPPORTS_INITIALIZING
// | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME // | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
// | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD // | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
@@ -92,7 +92,7 @@ bool
ExtendedPartitionAddOn::CanInitialize(const BMutablePartition* partition) ExtendedPartitionAddOn::CanInitialize(const BMutablePartition* partition)
{ {
// If it's big enough, we can initialize it. // If it's big enough, we can initialize it.
return partition->Size() >= 2 * partition->BlockSize(); return false;
} }
@@ -222,7 +222,7 @@ ExtendedPartitionHandle::Init()
uint32 uint32
ExtendedPartitionHandle::SupportedOperations(uint32 mask) ExtendedPartitionHandle::SupportedOperations(uint32 mask)
{ {
uint32 flags = B_DISK_SYSTEM_SUPPORTS_INITIALIZING; uint32 flags = 0;//B_DISK_SYSTEM_SUPPORTS_INITIALIZING;
// creating child // creating child
if (mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) { if (mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) {
@@ -254,10 +254,25 @@ ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child,
TRACE("%p->ExtendedPartitionHandle::GetNextSupportedType(child: %p, " TRACE("%p->ExtendedPartitionHandle::GetNextSupportedType(child: %p, "
"cookie: %ld)\n", this, child, *cookie); "cookie: %ld)\n", this, child, *cookie);
if (*cookie != 0) int32 index = *cookie;
const partition_type* nextType;
PartitionMap partitionMap;
while (true) {
nextType = partitionMap.GetNextSupportedPartitionType(index);
if (nextType == NULL)
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
*cookie = *cookie + 1; index++;
*type = kPartitionTypeIntelLogical; if (nextType->used
&& strcmp(nextType->name, kPartitionTypeIntelExtended) != 0)
break;
}
if (!nextType)
return B_ENTRY_NOT_FOUND;
type->SetTo(nextType->name);
*cookie = index;
return B_OK; return B_OK;
} }
@@ -266,39 +281,22 @@ ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child,
status_t status_t
ExtendedPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info) 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) // init to the full size (minus the first sector)
BMutablePartition* partition = Partition(); BMutablePartition* partition = Partition();
off_t offset = partition->Offset();// + SECTOR_SIZE; off_t offset = partition->Offset();
off_t size = partition->Size();//- SECTOR_SIZE; off_t size = partition->Size();
status_t error = info->SetTo(offset, size); status_t error = info->SetTo(offset, size);
if (error != B_OK) if (error != B_OK)
return error; return error;
// exclude the space of the existing logical partitions // exclude the space of the existing logical partitions
int32 count = partition->CountChildren(); int32 count = partition->CountChildren();
printf("%ld logical partitions\n", count);
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
BMutablePartition* child = partition->ChildAt(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()); 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) if (error != B_OK)
return error; return error;
} }
info->PrintToStream();
return B_OK; return B_OK;
} }
@@ -309,7 +307,6 @@ status_t
ExtendedPartitionHandle::GetChildCreationParameterEditor(const char* type, ExtendedPartitionHandle::GetChildCreationParameterEditor(const char* type,
BPartitionParameterEditor** editor) BPartitionParameterEditor** editor)
{ {
// TODO: We actually need an editor here.
*editor = NULL; *editor = NULL;
return B_OK; return B_OK;
} }
@@ -321,102 +318,98 @@ ExtendedPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size,
const char* typeString, BString* name, const char* parameters) const char* typeString, BString* name, const char* parameters)
{ {
// check type // check type
if (!typeString || strcmp(typeString, kPartitionTypeIntelLogical) != 0) if (!typeString)
return B_BAD_VALUE; return B_BAD_VALUE;
// check name // check name
if (name) if (name)
name->Truncate(0); name->Truncate(0);
// check parameters // check the free space situation
// TODO:... BPartitioningInfo info;
status_t error = GetPartitioningInfo(&info);
if (error != B_OK)
return error;
return B_NOT_SUPPORTED; // any space in the partition at all?
// // check the free space situation int32 spacesCount = info.CountPartitionableSpaces();
// BPartitioningInfo info; if (spacesCount == 0)
// status_t error = GetPartitioningInfo(&info); return B_BAD_VALUE;
// if (error != B_OK)
// return error; // check offset and size
// off_t offset = sector_align(*_offset, Partition()->BlockSize());
// // any space in the partition at all? off_t size = sector_align(*_size, Partition()->BlockSize());
// int32 spacesCount = info.CountPartitionableSpaces(); // TODO: Rather round size up?
// if (spacesCount == 0) off_t end = offset + size;
// return B_BAD_VALUE;
// // get the first partitionable space the requested interval intersects with
// // check offset and size int32 spaceIndex = -1;
// off_t offset = sector_align(*_offset); int32 closestSpaceIndex = -1;
// off_t size = sector_align(*_size); off_t closestSpaceDistance = 0;
// // TODO: Rather round size up? for (int32 i = 0; i < spacesCount; i++) {
// off_t end = offset + size; off_t spaceOffset, spaceSize;
// info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
// // get the first partitionable space the requested interval intersects with off_t spaceEnd = spaceOffset + spaceSize;
// int32 spaceIndex = -1;
// int32 closestSpaceIndex = -1; if (spaceOffset >= offset && spaceOffset < end
// off_t closestSpaceDistance = 0; || offset >= spaceOffset && offset < spaceEnd) {
// for (int32 i = 0; i < spacesCount; i++) { spaceIndex = i;
// off_t spaceOffset, spaceSize; break;
// info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize); }
// off_t spaceEnd = spaceOffset + spaceSize;
// off_t distance;
// if (spaceOffset >= offset && spaceOffset < end if (offset < spaceOffset)
// || offset >= spaceOffset && offset < spaceEnd) { distance = spaceOffset - end;
// spaceIndex = i; else
// break; distance = spaceEnd - offset;
// }
// if (closestSpaceIndex == -1 || distance < closestSpaceDistance) {
// off_t distance; closestSpaceIndex = i;
// if (offset < spaceOffset) closestSpaceDistance = distance;
// distance = spaceOffset - end; }
// else }
// distance = spaceEnd - offset;
// // get the space we found
// if (closestSpaceIndex == -1 || distance < closestSpaceDistance) { off_t spaceOffset, spaceSize;
// closestSpaceIndex = i; info.GetPartitionableSpaceAt(
// closestSpaceDistance = distance; spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset,
// } &spaceSize);
// } off_t spaceEnd = spaceOffset + spaceSize;
//
// // get the space we found // If the requested intervald doesn't intersect with any space yet, move
// off_t spaceOffset, spaceSize; // it, so that it does.
// info.GetPartitionableSpaceAt( if (spaceIndex < 0) {
// spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset, spaceIndex = closestSpaceIndex;
// &spaceSize); if (offset < spaceOffset) {
// off_t spaceEnd = spaceOffset + spaceSize; offset = spaceOffset;
// end = offset + size;
// // If the requested intervald doesn't intersect with any space yet, move } else {
// // it, so that it does. end = spaceEnd;
// if (spaceIndex < 0) { offset = end - size;
// spaceIndex = closestSpaceIndex; }
// if (offset < spaceOffset) { }
// offset = spaceOffset;
// end = offset + size; // move/shrink the interval, so that it fully lies within the space
// } else { if (offset < spaceOffset) {
// end = spaceEnd; offset = spaceOffset;
// offset = end - size; end = offset + size;
// } if (end > spaceEnd) {
// } end = spaceEnd;
// size = end - offset;
// // move/shrink the interval, so that it fully lies within the space }
// if (offset < spaceOffset) { } else if (end > spaceEnd) {
// offset = spaceOffset; end = spaceEnd;
// end = offset + size; offset = end - size;
// if (end > spaceEnd) { if (offset < spaceOffset) {
// end = spaceEnd; offset = spaceOffset;
// size = end - offset; size = end - offset;
// } }
// } else if (end > spaceEnd) { }
// end = spaceEnd;
// offset = end - size; *_offset = offset;
// if (offset < spaceOffset) { *_size = size;
// offset = spaceOffset;
// size = end - offset; return B_OK;
// }
// }
//
// *_offset = offset;
// *_size = size;
//
// return B_OK;
} }
@@ -427,73 +420,69 @@ ExtendedPartitionHandle::CreateChild(off_t offset, off_t size,
BMutablePartition** _child) BMutablePartition** _child)
{ {
// check type // check type
if (!typeString || strcmp(typeString, kPartitionTypeIntelLogical) != 0) PartitionType type;
if (!type.SetType(typeString) || type.IsEmpty())
return B_BAD_VALUE; return B_BAD_VALUE;
// check name // check name
if (name && strlen(name) > 0) if (name && strlen(name) > 0)
return B_BAD_VALUE; return B_BAD_VALUE;
// check parameters // offset properly aligned?
// TODO:... if (offset != sector_align(offset, Partition()->BlockSize())
|| size != sector_align(size, Partition()->BlockSize()))
return B_BAD_VALUE;
return B_NOT_SUPPORTED; // check the free space situation
// // offset properly aligned? BPartitioningInfo info;
// if (offset != sector_align(offset) || size != sector_align(size)) status_t error = GetPartitioningInfo(&info);
// return B_BAD_VALUE; if (error != B_OK)
// return error;
// // check the free space situation
// BPartitioningInfo info; bool foundSpace = false;
// status_t error = GetPartitioningInfo(&info); off_t end = offset + size;
// if (error != B_OK) int32 spacesCount = info.CountPartitionableSpaces();
// return error; for (int32 i = 0; i < spacesCount; i++) {
// off_t spaceOffset, spaceSize;
// bool foundSpace = false; info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
// off_t end = offset + size; off_t spaceEnd = spaceOffset + spaceSize;
// int32 spacesCount = info.CountPartitionableSpaces();
// for (int32 i = 0; i < spacesCount; i++) { if (offset >= spaceOffset && end <= spaceEnd) {
// off_t spaceOffset, spaceSize; foundSpace = true;
// info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize); break;
// off_t spaceEnd = spaceOffset + spaceSize; }
// }
// if (offset >= spaceOffset && end <= spaceEnd) {
// foundSpace = true; if (!foundSpace)
// break; return B_BAD_VALUE;
// }
// } // everything looks good, do it
// // create the child
// if (!foundSpace) BMutablePartition* child;
// return B_BAD_VALUE; error = Partition()->CreateChild(-1, typeString,
// NULL, parameters, &child);
// // everything looks good, do it if (error != B_OK)
// return error;
// // create the child
// // (Note: the primary partition index is indeed the child index, since // init the child
// // we picked the first empty primary partition.) child->SetOffset(offset);
// BMutablePartition* partition = Partition(); child->SetSize(size);
// BMutablePartition* child; child->SetBlockSize(Partition()->BlockSize());
// error = partition->CreateChild(primary->Index(), typeString, NULL, //child->SetFlags(0);
// parameters, &child); child->SetChildCookie(Partition());
// if (error != B_OK)
// return error; *_child = child;
// return B_OK;
// // 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;
} }
// DeleteChild
status_t
ExtendedPartitionHandle::DeleteChild(BMutablePartition* child)
{
BMutablePartition* parent = child->Parent();
status_t error = parent->DeleteChild(child);
return error;
}
@@ -62,6 +62,8 @@ public:
const char* type, const char* name, const char* type, const char* name,
const char* parameters, const char* parameters,
BMutablePartition** child); BMutablePartition** child);
virtual status_t DeleteChild(BMutablePartition* child);
private: private:
PrimaryPartition* fPrimaryPartition; PrimaryPartition* fPrimaryPartition;
}; };
@@ -356,19 +356,6 @@ Partition::Unset()
} }
void
Partition::GetPartitionDescriptor(partition_descriptor *descriptor,
off_t baseOffset) const
{
descriptor->start = (fOffset - baseOffset) / fBlockSize;
descriptor->size = fSize / fBlockSize;
descriptor->type = fType;
descriptor->active = fActive ? 0x80 : 0x00;
descriptor->begin.Unset();
descriptor->end.Unset();
}
#ifdef _BOOT_MODE #ifdef _BOOT_MODE
void void
Partition::AdjustSize(off_t sessionSize) Partition::AdjustSize(off_t sessionSize)
@@ -389,7 +376,8 @@ Partition::CheckLocation(off_t sessionSize) const
// lie within the session // lie within the session
if (fPartitionTableOffset % fBlockSize != 0) { if (fPartitionTableOffset % fBlockSize != 0) {
TRACE(("Partition::CheckLocation() - bad partition table offset: %lld " TRACE(("Partition::CheckLocation() - bad partition table offset: %lld "
"(session: %lld)\n", fPartitionTableOffset, sessionSize)); "(session: %lld), (fBlockSize: %ld)\n", fPartitionTableOffset,
sessionSize, fBlockSize));
return false; return false;
} }
if (fOffset % fBlockSize != 0) { if (fOffset % fBlockSize != 0) {
@@ -426,7 +414,8 @@ Partition::CheckLocation(off_t sessionSize) const
PrimaryPartition::PrimaryPartition() PrimaryPartition::PrimaryPartition()
: Partition(), :
Partition(),
fHead(NULL), fHead(NULL),
fTail(NULL), fTail(NULL),
fLogicalPartitionCount(0) fLogicalPartitionCount(0)
@@ -470,13 +459,13 @@ status_t
PrimaryPartition::Assign(const PrimaryPartition& other) PrimaryPartition::Assign(const PrimaryPartition& other)
{ {
partition_descriptor descriptor; partition_descriptor descriptor;
other.GetPartitionDescriptor(&descriptor, 0); other.GetPartitionDescriptor(&descriptor);
SetTo(&descriptor, 0, other.BlockSize()); SetTo(&descriptor, 0, other.BlockSize());
const LogicalPartition* otherLogical = other.fHead; const LogicalPartition* otherLogical = other.fHead;
while (otherLogical) { while (otherLogical) {
off_t tableOffset = otherLogical->PartitionTableOffset(); off_t tableOffset = otherLogical->PartitionTableOffset();
otherLogical->GetPartitionDescriptor(&descriptor, tableOffset); otherLogical->GetPartitionDescriptor(&descriptor);
LogicalPartition* logical = new(nothrow) LogicalPartition( LogicalPartition* logical = new(nothrow) LogicalPartition(
&descriptor, tableOffset, this); &descriptor, tableOffset, this);
@@ -492,6 +481,22 @@ PrimaryPartition::Assign(const PrimaryPartition& other)
} }
void
PrimaryPartition::GetPartitionDescriptor(partition_descriptor* descriptor) const
{
if (IsEmpty()) {
memset(descriptor, 0, sizeof(partition_descriptor));
} else {
descriptor->start = Offset() / BlockSize();
descriptor->size = Size() / BlockSize();
descriptor->type = Type();
descriptor->active = Active() ? 0x80 : 0x00;
descriptor->begin.Unset();
descriptor->end.Unset();
}
}
LogicalPartition* LogicalPartition*
PrimaryPartition::LogicalPartitionAt(int32 index) const PrimaryPartition::LogicalPartitionAt(int32 index) const
{ {
@@ -554,7 +559,8 @@ PrimaryPartition::RemoveLogicalPartition(LogicalPartition* partition)
LogicalPartition::LogicalPartition() LogicalPartition::LogicalPartition()
: Partition(), :
Partition(),
fPrimary(NULL), fPrimary(NULL),
fNext(NULL), fNext(NULL),
fPrevious(NULL) fPrevious(NULL)
@@ -564,7 +570,8 @@ LogicalPartition::LogicalPartition()
LogicalPartition::LogicalPartition(const partition_descriptor* descriptor, LogicalPartition::LogicalPartition(const partition_descriptor* descriptor,
off_t tableOffset, PrimaryPartition* primary) off_t tableOffset, PrimaryPartition* primary)
: Partition(), :
Partition(),
fPrimary(NULL), fPrimary(NULL),
fNext(NULL), fNext(NULL),
fPrevious(NULL) fPrevious(NULL)
@@ -622,6 +629,27 @@ LogicalPartition::Unset()
} }
void
LogicalPartition::GetPartitionDescriptor(partition_descriptor* descriptor,
bool inner) const
{
PrimaryPartition* primary = GetPrimaryPartition();
if (inner) {
descriptor->start = (PartitionTableOffset() - primary->Offset())
/ BlockSize();
descriptor->type = primary->Type();
} else {
descriptor->start = (Offset() - PartitionTableOffset()) / BlockSize();
descriptor->type = Type();
}
descriptor->size = Size() / BlockSize();
descriptor->active = 0x00;
descriptor->begin.Unset();
descriptor->end.Unset();
}
// #pragma mark - PartitionMap // #pragma mark - PartitionMap
@@ -169,9 +169,6 @@ public:
uint32 BlockSize() const { return fBlockSize; } uint32 BlockSize() const { return fBlockSize; }
void GetTypeString(char* buffer) const void GetTypeString(char* buffer) const
{ get_partition_type_string(fType, buffer); } { get_partition_type_string(fType, buffer); }
void GetPartitionDescriptor(
partition_descriptor* descriptor,
off_t baseOffset) const;
void SetPartitionTableOffset(off_t offset) void SetPartitionTableOffset(off_t offset)
{ fPartitionTableOffset = offset; } { fPartitionTableOffset = offset; }
@@ -183,6 +180,8 @@ public:
{ fType = type; } { fType = type; }
void SetActive(bool active) void SetActive(bool active)
{ fActive = active; } { fActive = active; }
void SetBlockSize(uint32 blockSize)
{ fBlockSize = blockSize; }
bool CheckLocation(off_t sessionSize) const; bool CheckLocation(off_t sessionSize) const;
#ifdef _BOOT_MODE #ifdef _BOOT_MODE
@@ -215,6 +214,9 @@ public:
int32 Index() const { return fIndex; } int32 Index() const { return fIndex; }
void SetIndex(int32 index) { fIndex = index; } void SetIndex(int32 index) { fIndex = index; }
void GetPartitionDescriptor(
partition_descriptor* descriptor) const;
// private // private
// only if extended // only if extended
@@ -249,6 +251,10 @@ public:
bool active, off_t tableOffset, bool active, off_t tableOffset,
PrimaryPartition* primary); PrimaryPartition* primary);
void Unset(); void Unset();
void GetPartitionDescriptor(
partition_descriptor* descriptor,
bool inner = false) const;
void SetPrimaryPartition(PrimaryPartition* primary) void SetPrimaryPartition(PrimaryPartition* primary)
{ fPrimary = primary; } { fPrimary = primary; }
@@ -3,7 +3,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Tomas Kucera, kucerat@centrum.cz * Bryce Groff, brycegroff@gmail.com
*/ */
#include "PartitionMapWriter.h" #include "PartitionMapWriter.h"
@@ -34,293 +34,225 @@ using std::nothrow;
#endif #endif
// TODO: get rid of this - there is no such thing as a fixed sector size! bool
static const uint32 SECTOR_SIZE = 512; check_logical_location(const LogicalPartition* child,
const PrimaryPartition* parent)
{
if (child->PartitionTableOffset() % child->BlockSize() != 0) {
TRACE(("check_logical_location() - PartitionTableOffset: %lld not a "
"multiple of media's block size: %ld\n",
child->PartitionTableOffset(), child->BlockSize()));
return false;
}
if (child->Offset() % child->BlockSize() != 0) {
TRACE(("check_logical_location() - Parition offset: %lld "
"is not a multiple of block size: %ld\n", child->Offset(),
child->BlockSize()));
return false;
}
if (child->Size() % child->BlockSize() != 0) {
TRACE(("check_logical_location() - Size: (%lld) is not a multiple of"
" block size: (%ld)\n", child->Size(), child->BlockSize()));
return false;
}
if (child->PartitionTableOffset() < parent->Offset()
|| child->PartitionTableOffset() >= parent->Offset()
+ parent->Size()) {
TRACE(("check_logical_location() - Partition table: (%lld) not within "
"extended partition (start: %lld), (end: %lld)\n",
child->PartitionTableOffset(), parent->Offset(), parent->Offset()
+ parent->Size()));
return false;
}
if (child->Offset() + child->Size() > parent->Offset() + parent->Size()) {
TRACE(("check_logical_location() - logical paritition does not lie "
"within extended partition\n"));
return false;
}
return true;
}
// constructor PartitionMapWriter::PartitionMapWriter(int deviceFD, uint32 blockSize)
/*! \brief Creates the writer.
\param deviceFD File descriptor.
\param sessionOffset Disk offset of the partition with partitioning system.
\param sessionSize Size of the partition with partitioning system.
*/
PartitionMapWriter::PartitionMapWriter(int deviceFD, off_t sessionOffset,
off_t sessionSize)
: :
fDeviceFD(deviceFD), fDeviceFD(deviceFD),
fSessionOffset(sessionOffset), fBlockSize(blockSize)
fSessionSize(sessionSize),
fMap(NULL)
{ {
} }
// destructor
PartitionMapWriter::~PartitionMapWriter() PartitionMapWriter::~PartitionMapWriter()
{ {
} }
// WriteMBR
/*! \brief Writes Master Boot Record to the first sector of the disk.
If a \a block is not specified, the sector is firstly read from the disk
and after changing relevant items it is written back to the disk.
This allows to keep code area in MBR intact.
\param pts Pointer to \c partition_table.
\param map Pointer to the PartitionMap structure describing disk partitions.
*/
status_t status_t
PartitionMapWriter::WriteMBR(const PartitionMap *map, bool clearSectors) PartitionMapWriter::WriteMBR(const PartitionMap* map, bool clearCode)
{ {
if (!map) if (map == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
fMap = map; partition_table partitionTable;
if (clearCode) {
partitionTable.clear_code_area();
} else {
status_t error = _ReadBlock(0, partitionTable);
if (error != B_OK)
return error;
}
uint8 sector[SECTOR_SIZE]; partitionTable.signature = kPartitionTableSectorSignature;
partition_table* pts = (partition_table*)sector;
// If we shall not clear the first two sectors, we need to read the first for (int i = 0; i < 4; i++) {
// sector in, first. partition_descriptor* descriptor = &partitionTable.table[i];
status_t error = B_OK; const PrimaryPartition* partition = map->PrimaryPartitionAt(i);
if (clearSectors)
memset(sector, 0, SECTOR_SIZE); partition->GetPartitionDescriptor(descriptor);
}
status_t error = _WriteBlock(0, partitionTable);
return error;
}
status_t
PartitionMapWriter::WriteLogical(const LogicalPartition* logical,
const PrimaryPartition* primary, bool clearCode)
{
if (logical == NULL || primary == NULL)
return B_BAD_VALUE;
if (!check_logical_location(logical, primary))
return B_BAD_DATA;
partition_table partitionTable;
if (clearCode) {
partitionTable.clear_code_area();
} else {
status_t error = _ReadBlock(logical->PartitionTableOffset(),
partitionTable);
if (error != B_OK)
return error;
}
partitionTable.signature = kPartitionTableSectorSignature;
partition_descriptor* descriptor = &partitionTable.table[0];
logical->GetPartitionDescriptor(descriptor);
descriptor = &partitionTable.table[1];
if (logical->Next() != NULL)
logical->Next()->GetPartitionDescriptor(descriptor, true);
else else
error = _ReadSector(0, pts); memset(descriptor, 0, sizeof(partition_descriptor));
if (error == B_OK) { // last two descriptors are empty
error = _WritePrimary(pts);
if (error == B_OK)
error = _WriteSector(0, pts);
}
// Clear the second sector, if desired. We do that to make the partition
// unrecognizable by BFS.
if (error == B_OK && clearSectors) {
memset(sector, 0, SECTOR_SIZE);
error = _WriteSector(SECTOR_SIZE, pts);
}
fMap = NULL;
return error;
}
// WriteLogical
/*! \brief Writes Partition Table Sector of the logical \a partition to the
disk.
This function ensures that the connection of the following linked list
of logical partitions will be correct. It does nothing with the connection
of previous logical partitions (call this function on previous logical
partition to ensure it).
\param pts Pointer to \c partition_table.
\param partition Pointer to the logical partition.
*/
status_t
PartitionMapWriter::WriteLogical(partition_table* pts,
const LogicalPartition* partition)
{
if (partition == NULL)
return B_BAD_VALUE;
partition_table _pts;
if (pts == NULL) {
// no partition table given, use stack based partition table and read
// from disk first
pts = &_pts;
status_t error = _ReadSector(partition->PartitionTableOffset(), pts);
if (error != B_OK)
return error;
}
status_t error = _WriteExtended(pts, partition, partition->Next());
if (error != B_OK)
return error;
return _WriteSector(partition->PartitionTableOffset(), pts);
}
// WriteExtendedHead
/*! \brief Writes Extended Boot Record to the first sector of Extended
Partition.
Writes the head of linked list describing logical partitions.
If the \a firstPartition is not specified, it only initializes EBR and the
linked list contains no logical partitions.
\param pts Pointer to \c partition_table.
\param firstPartition Pointer to the first logical partition.
*/
status_t
PartitionMapWriter::WriteExtendedHead(partition_table* pts,
const LogicalPartition* firstPartition)
{
LogicalPartition partition;
if (firstPartition != NULL)
partition.SetPrimaryPartition(firstPartition->GetPrimaryPartition());
partition_table _pts;
if (pts == NULL) {
// no partition table given, use stack based partition table and read
// from disk first
pts = &_pts;
status_t error = _ReadSector(0, pts);
if (error != B_OK)
return error;
}
status_t error = _WriteExtended(pts, &partition, firstPartition);
if (error != B_OK)
return error;
return _WriteSector(0, pts);
}
// #pragma mark - fill a partition table in memory
// _WritePrimary
status_t
PartitionMapWriter::_WritePrimary(partition_table* pts)
{
if (pts == NULL)
return B_BAD_VALUE;
// write the signature
pts->signature = kPartitionTableSectorSignature;
// write the table
for (int32 i = 0; i < 4; i++) {
partition_descriptor *descriptor = &pts->table[i];
const PrimaryPartition *partition = fMap->PrimaryPartitionAt(i);
// ignore, if location is bad
if (!partition->CheckLocation(fSessionSize)) {
TRACE(("intel: _WritePrimary(): partition %ld: bad location, "
"ignoring\n", i));
return B_BAD_DATA;
}
partition->GetPartitionDescriptor(descriptor, 0);
// TODO: Should this be fSessionOffset?!
}
return B_OK;
}
// _WriteExtended
status_t
PartitionMapWriter::_WriteExtended(partition_table *pts,
const LogicalPartition *partition, const LogicalPartition *next)
{
if (pts == NULL || partition == NULL)
return B_BAD_VALUE;
// write the signature
pts->signature = kPartitionTableSectorSignature;
// check the partition's location
if (!partition->CheckLocation(fSessionSize)) {
TRACE(("intel: _WriteExtended(): Invalid partition "
"location: pts: %lld, offset: %lld, size: %lld, "
"fSessionSize: %lld\n",
partition->PartitionTableOffset(), partition->Offset(),
partition->Size(), fSessionSize));
return B_BAD_DATA;
}
// NOTE: The OS/2 boot manager needs the first entry to describe the
// data partition, while the second entry should describe the "inner
// extended" partition.
// write the table
partition_descriptor* descriptor = &(pts->table[0]);
partition->GetPartitionDescriptor(descriptor,
partition->PartitionTableOffset());
// location is relative to this partition's table offset
// Set offset and size of the next partition in the linked list.
// This is done via a so called "inner extended" partition which is
// only used to point to the next partition table location (start sector of
// the inner extended partition).
descriptor = &pts->table[1];
LogicalPartition extended;
if (next) {
extended.SetPartitionTableOffset(partition->PartitionTableOffset());
extended.SetOffset(next->PartitionTableOffset());
// Strictly speaking, the size is not relevant and just needs to
// be non-zero. But some operating systems check the size of
// inner extended partitions and it needs to include the next data
// partition. Therefor the size is the size of the next data partition
// plus the offset between the next partition table and the data
// partition start offset.
// This assumes of course that the start offset is behind the partition
// table offset, which is actually not dictated by a minimal
// specification.
extended.SetSize(next->Size()
+ (next->Offset() - next->PartitionTableOffset()));
// Use the same extended partition type as the primary extended
// partition.
extended.SetType(partition->GetPrimaryPartition()->Type());
extended.GetPartitionDescriptor(descriptor, 0);
// Unsetting to get an empty descriptor for the remaining slots.
extended.Unset();
} else
extended.GetPartitionDescriptor(descriptor, 0);
// last two descriptors are empty ("extended" is unset)
for (int32 i = 2; i < 4; i++) { for (int32 i = 2; i < 4; i++) {
descriptor = &(pts->table[i]); descriptor = &partitionTable.table[i];
extended.GetPartitionDescriptor(descriptor, 0); memset(descriptor, 0, sizeof(partition_descriptor));
} }
status_t error = _WriteBlock(logical->PartitionTableOffset(),
partitionTable);
return error;
}
status_t
PartitionMapWriter::WriteExtendedHead(const LogicalPartition* logical,
const PrimaryPartition* primary, bool clearCode)
{
if (primary == NULL)
return B_BAD_VALUE;
partition_table partitionTable;
if (clearCode) {
partitionTable.clear_code_area();
} else {
status_t error = _ReadBlock(primary->Offset(), partitionTable);
if (error != B_OK)
return error;
}
partitionTable.signature = kPartitionTableSectorSignature;
partition_descriptor* descriptor;
if (logical == NULL) {
for (int32 i = 0; i < 4; i++) {
descriptor = &partitionTable.table[i];
memset(descriptor, 0, sizeof(partition_descriptor));
}
} else {
LogicalPartition partition;
partition.SetPartitionTableOffset(primary->Offset());
partition.SetBlockSize(logical->BlockSize());
partition.SetOffset(logical->Offset());
partition.SetSize(logical->Size());
partition.SetType(logical->Type());
// set the logicals partition table to the correct location
descriptor = &partitionTable.table[0];
partition.GetPartitionDescriptor(descriptor);
descriptor = &partitionTable.table[1];
LogicalPartition* next = logical->Next();
if (next != NULL)
next->GetPartitionDescriptor(descriptor, true);
else
memset(descriptor, 0, sizeof(partition_descriptor));
// last two descriptors are empty
for (int32 i = 2; i < 4; i++) {
descriptor = &partitionTable.table[i];
memset(descriptor, 0, sizeof(partition_descriptor));
}
}
status_t error = _WriteBlock(primary->Offset(), partitionTable);
if (error != B_OK)
return error;
return B_OK; return B_OK;
} }
// #pragma mark - to/from disk
// _ReadSector
/*! \brief Reads the sector from the disk.
*/
status_t status_t
PartitionMapWriter::_ReadSector(off_t offset, partition_table* pts) PartitionMapWriter::ClearExtendedHead(const PrimaryPartition* primary)
{ {
int32 toRead = sizeof(partition_table); if (primary == NULL)
// same as SECTOR_SIZE actually
// check the offset
if (offset < 0 || offset + toRead > fSessionSize) {
TRACE(("intel: _ReadSector(): bad offset: %Ld\n", offset));
return B_BAD_VALUE; return B_BAD_VALUE;
partition_table partitionTable;
partitionTable.clear_code_area();
partitionTable.signature = kPartitionTableSectorSignature;
partition_descriptor* descriptor;
for (int32 i = 0; i < 4; i++) {
descriptor = &partitionTable.table[i];
memset(descriptor, 0, sizeof(partition_descriptor));
} }
// read status_t error = _WriteBlock(primary->Offset(), partitionTable);
offset += fSessionOffset; if (error != B_OK)
if (read_pos(fDeviceFD, offset, pts, toRead) != toRead) { return error;
#ifndef _BOOT_MODE
return B_OK;
}
status_t
PartitionMapWriter::_ReadBlock(off_t partitionOffset,
partition_table& partitionTable)
{
if (partitionOffset < 0)
return B_BAD_VALUE;
// TODO: If fBlockSize > sizeof(partition_table) then stop/read NULL after
if (read_pos(fDeviceFD, partitionOffset, &partitionTable, fBlockSize)
!= fBlockSize) {
status_t error = errno; status_t error = errno;
if (error == B_OK) if (error == B_OK)
error = B_IO_ERROR; error = B_IO_ERROR;
#else
status_t error = B_IO_ERROR;
#endif
TRACE(("intel: _ReadSector(): reading the partition table failed: %lx\n",
error));
return error; return error;
} }
@@ -328,31 +260,19 @@ PartitionMapWriter::_ReadSector(off_t offset, partition_table* pts)
} }
// _WriteSector
/*! \brief Writes the sector to the disk.
*/
status_t status_t
PartitionMapWriter::_WriteSector(off_t offset, const partition_table* pts) PartitionMapWriter::_WriteBlock(off_t partitionOffset,
const partition_table& partitionTable)
{ {
int32 toWrite = sizeof(partition_table); if (partitionOffset < 0)
// same as SECTOR_SIZE actually
// check the offset
if (offset < 0 || offset + toWrite > fSessionSize) {
TRACE(("intel: _WriteSector(): bad offset: %Ld\n", offset));
return B_BAD_VALUE; return B_BAD_VALUE;
} // TODO: If fBlockSize > sizeof(partition_table) then stop/write NULL after
if (write_pos(fDeviceFD, partitionOffset, &partitionTable, fBlockSize)
offset += fSessionOffset; != fBlockSize) {
// write
if (write_pos(fDeviceFD, offset, pts, toWrite) != toWrite) {
status_t error = errno; status_t error = errno;
if (error == B_OK) if (error == B_OK)
error = B_IO_ERROR; error = B_IO_ERROR;
TRACE(("intel: _WriteSector(): writing the partition table failed: "
"%lx\n", error));
return error; return error;
} }
@@ -4,6 +4,7 @@
* *
* Authors: * Authors:
* Tomas Kucera, kucerat@centrum.cz * Tomas Kucera, kucerat@centrum.cz
* Bryce Groff, brycegroff@gmail.com
*/ */
/*! /*!
@@ -26,8 +27,12 @@
class PartitionMap; class PartitionMap;
class LogicalPartition; class LogicalPartition;
class PrimaryPartition;
struct partition_table; struct partition_table;
bool check_logical_location(const LogicalPartition* logical,
const PrimaryPartition* primary);
/*! /*!
\brief Writer for "Intel" style partitions. \brief Writer for "Intel" style partitions.
@@ -36,33 +41,32 @@ struct partition_table;
class PartitionMapWriter { class PartitionMapWriter {
public: public:
PartitionMapWriter(int deviceFD, PartitionMapWriter(int deviceFD,
off_t sessionOffset, off_t sessionSize); uint32 blockSize);
~PartitionMapWriter(); ~PartitionMapWriter();
status_t WriteMBR(const PartitionMap* map, status_t WriteMBR(const PartitionMap* map,
bool clearSectors); bool clearCode);
status_t WriteLogical(partition_table* pts, status_t WriteLogical(const LogicalPartition* logical,
const LogicalPartition* partition); const PrimaryPartition* primary,
status_t WriteExtendedHead(partition_table* pts, bool clearCode);
const LogicalPartition* firstPartition); status_t WriteExtendedHead(
const LogicalPartition* logical,
const PrimaryPartition* primary,
bool clearCode);
status_t ClearExtendedHead(
const PrimaryPartition* primary);
private: private:
status_t _WritePrimary(partition_table* pts); status_t _ReadBlock(off_t offset,
status_t _WriteExtended(partition_table* pts, partition_table& partitionTable);
const LogicalPartition* partition, status_t _WriteBlock(off_t offset,
const LogicalPartition* next); const partition_table& partitionTable);
status_t _ReadSector(off_t offset,
partition_table* pts);
status_t _WriteSector(off_t offset,
const partition_table* pts);
private: private:
int fDeviceFD; int fDeviceFD;
off_t fSessionOffset; int32 fBlockSize;
off_t fSessionSize;
const PartitionMap* fMap; // while writing
}; };
#endif // PARTITION_MAP_WRITER_H #endif // PARTITION_MAP_WRITER_H
@@ -40,9 +40,9 @@ static const int32 MAX_MOVE_BUFFER = 2 * 1024 * 4;
// for logical partitions in Intel Extended Partition // for logical partitions in Intel Extended Partition
// Count of free sectors after Partition Table Sector (at logical partition). // Count of free sectors after Partition Table Sector (at logical partition).
static const uint32 FREE_SECTORS_AFTER_PTS = 0; static const uint32 FREE_SECTORS_AFTER_PTS = 63;
// Count of free sectors after Master Boot Record. // Count of free sectors after Master Boot Record.
static const uint32 FREE_SECTORS_AFTER_MBR = 0; static const uint32 FREE_SECTORS_AFTER_MBR = 63;
// size of logical partition header in blocks // size of logical partition header in blocks
static const uint32 PTS_OFFSET = FREE_SECTORS_AFTER_PTS + 1; static const uint32 PTS_OFFSET = FREE_SECTORS_AFTER_PTS + 1;
static const uint32 MBR_OFFSET = FREE_SECTORS_AFTER_MBR + 1; static const uint32 MBR_OFFSET = FREE_SECTORS_AFTER_MBR + 1;
@@ -448,15 +448,15 @@ pm_validate_set_type(partition_data *partition, const char *type)
if (!partition || !type) if (!partition || !type)
return false; return false;
partition_data *father = get_parent_partition(partition->id); partition_data* parent = get_parent_partition(partition->id);
if (!father) if (!parent)
return false; return false;
PrimaryPartition* child = (PrimaryPartition*)partition->cookie; PrimaryPartition* child = (PrimaryPartition*)partition->cookie;
if (!child) if (!child)
return false; return false;
// validity check of the type // validity check of the type
return is_type_valid_pm(type, father, child); return is_type_valid_pm(type, parent, child);
} }
// pm_validate_initialize // pm_validate_initialize
@@ -564,8 +564,8 @@ pm_validate_create_child(partition_data *partition, off_t *start, off_t *size,
return false; return false;
*index = newIndex; *index = newIndex;
if (*start < partition->offset + MBR_OFFSET * SECTOR_SIZE) { if (*start < partition->offset + MBR_OFFSET * partition->block_size) {
*start = partition->offset + MBR_OFFSET * SECTOR_SIZE; *start = partition->offset + MBR_OFFSET * partition->block_size;
*start = sector_align_up(*start); *start = sector_align_up(*start);
} }
@@ -658,12 +658,11 @@ get_partitionable_spaces(partition_data *partition,
// offset alignment (to upper bound) // offset alignment (to upper bound)
offset = sector_align_up(offset); offset = sector_align_up(offset);
// finding out all partitionable spaces // finding out all partitionable spaces
for (int32 i = 0; i < partition_count; i++) { for (int32 i = 0; i < partition_count; i++) {
size = positions[i].offset - offset; size = positions[i].offset - offset;
size = sector_align(size); size = sector_align(size);
if (size > limitSize) { if (size >= limitSize) {
if (actualCount < count) { if (actualCount < count) {
buffer[actualCount].offset = offset; buffer[actualCount].offset = offset;
buffer[actualCount].size = size; buffer[actualCount].size = size;
@@ -714,7 +713,7 @@ pm_get_partitionable_spaces(partition_data *partition,
return B_BAD_VALUE; return B_BAD_VALUE;
return get_partitionable_spaces(partition, buffer, count, actualCount, return get_partitionable_spaces(partition, buffer, count, actualCount,
fill_partitionable_spaces_buffer_pm, MBR_OFFSET * SECTOR_SIZE, fill_partitionable_spaces_buffer_pm, MBR_OFFSET * partition->block_size,
0, 0); 0, 0);
} }
@@ -994,7 +993,7 @@ pm_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job)
primary->SetSize(validatedSize); primary->SetSize(validatedSize);
// TODO: The partition is not supposed to be locked here! // TODO: The partition is not supposed to be locked here!
PartitionMapWriter writer(fd, 0, partition->size); PartitionMapWriter writer(fd, primary->BlockSize());
// TODO: disk size? // TODO: disk size?
status_t error = writer.WriteMBR(map, false); status_t error = writer.WriteMBR(map, false);
if (error != B_OK) { if (error != B_OK) {
@@ -1151,7 +1150,7 @@ pm_move_child(int fd, partition_id partitionID, partition_id childID,
// buffer allocation // buffer allocation
int32 allocated; int32 allocated;
uint8 *buffer = allocate_buffer(SECTOR_SIZE, MAX_MOVE_BUFFER, uint8* buffer = allocate_buffer(partition->block_size, MAX_MOVE_BUFFER,
&allocated); &allocated);
if (!buffer) if (!buffer)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -1161,7 +1160,7 @@ pm_move_child(int fd, partition_id partitionID, partition_id childID,
update_disk_device_job_progress(job, 0.0); update_disk_device_job_progress(job, 0.0);
status_t error = B_OK; status_t error = B_OK;
error = move_partition(fd, child->offset, validatedOffset, child->size, error = move_partition(fd, child->offset, validatedOffset, child->size,
buffer, allocated * SECTOR_SIZE, job); buffer, allocated * partition->block_size, job);
delete[] buffer; delete[] buffer;
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -1171,7 +1170,7 @@ pm_move_child(int fd, partition_id partitionID, partition_id childID,
child->offset = validatedOffset; child->offset = validatedOffset;
primary->SetOffset(validatedOffset); primary->SetOffset(validatedOffset);
PartitionMapWriter writer(fd, 0, partition->size); PartitionMapWriter writer(fd, partition->block_size);
// TODO: disk size? // TODO: disk size?
error = writer.WriteMBR(map, false); error = writer.WriteMBR(map, false);
if (error != B_OK) if (error != B_OK)
@@ -1230,7 +1229,7 @@ pm_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job)
primary->SetType(ptype.Type()); primary->SetType(ptype.Type());
// TODO: The partition is not supposed to be locked at this point! // TODO: The partition is not supposed to be locked at this point!
PartitionMapWriter writer(fd, 0, partition->size); PartitionMapWriter writer(fd, primary->BlockSize());
// TODO: disk size? // TODO: disk size?
status_t error = writer.WriteMBR(map, false); status_t error = writer.WriteMBR(map, false);
if (error != B_OK) { if (error != B_OK) {
@@ -1261,13 +1260,21 @@ pm_initialize(int fd, partition_id partitionID, const char *name,
if (fd < 0) if (fd < 0)
return B_ERROR; return B_ERROR;
PartitionWriteLocker locker(partitionID);
if (!locker.IsLocked())
return B_ERROR;
// get partition and partition map structure
partition_data* partition = get_partition(partitionID);
if (!partition)
return B_BAD_VALUE;
update_disk_device_job_progress(job, 0.0); update_disk_device_job_progress(job, 0.0);
// we will write an empty partition map // we will write an empty partition map
PartitionMap map; PartitionMap map;
// write the sector to disk // write the sector to disk
PartitionMapWriter writer(fd, 0, partitionSize); PartitionMapWriter writer(fd, partition->block_size);
// TODO: disk size or 2 * SECTOR_SIZE? // TODO: disk size or 2 * SECTOR_SIZE?
status_t error = writer.WriteMBR(&map, true); status_t error = writer.WriteMBR(&map, true);
if (error != B_OK) if (error != B_OK)
@@ -1345,6 +1352,7 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size,
return B_ERROR; return B_ERROR;
bool active = get_driver_boolean_parameter(handle, "active", false, true); bool active = get_driver_boolean_parameter(handle, "active", false, true);
delete_driver_settings(handle);
// set the active flags to false // set the active flags to false
if (active) { if (active) {
@@ -1361,8 +1369,8 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size,
primary->SetActive(active); primary->SetActive(active);
// write changes to disk // write changes to disk
PartitionMapWriter writer(fd, 0, partition->size); PartitionMapWriter writer(fd, primary->BlockSize());
// TODO: disk size or 2 * SECTOR_SIZE?
// TODO: The partition is not supposed to be locked at this point! // TODO: The partition is not supposed to be locked at this point!
status_t error = writer.WriteMBR(map, false); status_t error = writer.WriteMBR(map, false);
if (error != B_OK) { if (error != B_OK) {
@@ -1374,7 +1382,7 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size,
*childID = child->id; *childID = child->id;
child->block_size = SECTOR_SIZE; child->block_size = primary->BlockSize();
// (no name) // (no name)
child->type = strdup(type); child->type = strdup(type);
// parameters // parameters
@@ -1384,6 +1392,14 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size,
if (!child->type || !child->parameters) if (!child->type || !child->parameters)
return B_NO_MEMORY; return B_NO_MEMORY;
// rescan partition if needed
if (strcmp(type, INTEL_EXTENDED_PARTITION_NAME) == 0) {
writer.ClearExtendedHead(primary);
error = scan_partition(partitionID);
if (error != B_OK)
return error;
}
// all changes applied // all changes applied
update_disk_device_job_progress(job, 1.0); update_disk_device_job_progress(job, 1.0);
partition_modified(partitionID); partition_modified(partitionID);
@@ -1422,7 +1438,7 @@ pm_delete_child(int fd, partition_id partitionID, partition_id childID,
primary->Unset(); primary->Unset();
// write changes to disk // write changes to disk
PartitionMapWriter writer(fd, 0, partition->size); PartitionMapWriter writer(fd, primary->BlockSize());
// TODO: disk size or 2 * SECTOR_SIZE? // TODO: disk size or 2 * SECTOR_SIZE?
// TODO: The partition is not supposed to be locked at this point! // TODO: The partition is not supposed to be locked at this point!
status_t error = writer.WriteMBR(map, false); status_t error = writer.WriteMBR(map, false);
@@ -1458,7 +1474,7 @@ ep_get_supported_operations(partition_data* partition, uint32 mask)
// creating child // creating child
int32 countSpaces = 0; int32 countSpaces = 0;
if (pm_get_partitionable_spaces(partition, NULL, 0, &countSpaces) if (ep_get_partitionable_spaces(partition, NULL, 0, &countSpaces)
== B_BUFFER_OVERFLOW == B_BUFFER_OVERFLOW
&& countSpaces > 0) { && countSpaces > 0) {
flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD;
@@ -1635,21 +1651,20 @@ ep_validate_create_child(partition_data *partition, off_t *_start, off_t *_size,
// finding out index of the new partition (it will be the last child) // finding out index of the new partition (it will be the last child)
*index = partition->child_count; *index = partition->child_count;
// validate position // validate position
off_t diffOffset = PTS_OFFSET * SECTOR_SIZE; off_t start = *_start + FREE_SECTORS_AFTER_PTS * partition->block_size;
off_t start = *_start - diffOffset; off_t size = *_size - FREE_SECTORS_AFTER_PTS * partition->block_size;
off_t size = *_size + diffOffset; if (start < partition->offset + FREE_SECTORS_AFTER_PTS * partition->block_size) {
if (start < partition->offset + PTS_OFFSET * SECTOR_SIZE) { start = partition->offset + FREE_SECTORS_AFTER_PTS * partition->block_size;
start = partition->offset + PTS_OFFSET * SECTOR_SIZE;
start = sector_align_up(start); start = sector_align_up(start);
} }
if (!validate_create_child_partition(partition, &start, &size, if (!validate_create_child_partition(partition, &start, &size,
get_sibling_partitions_ep)) { get_sibling_partitions_ep)) {
return false; return false;
} }
*_start = start + diffOffset;
*_size = size - diffOffset; *_start = start;
*_size = size;
if (*_size == 0) if (*_size == 0)
return false; return false;
return true; return true;
@@ -1673,9 +1688,9 @@ ep_get_partitionable_spaces(partition_data *partition,
return get_partitionable_spaces(partition, buffer, count, actualCount, return get_partitionable_spaces(partition, buffer, count, actualCount,
fill_partitionable_spaces_buffer_ep, fill_partitionable_spaces_buffer_ep,
partition->offset + PTS_OFFSET * SECTOR_SIZE, partition->offset + PTS_OFFSET * partition->block_size,
PTS_OFFSET * SECTOR_SIZE, PTS_OFFSET * partition->block_size,
PTS_OFFSET * SECTOR_SIZE); PTS_OFFSET * partition->block_size);
} }
@@ -1795,7 +1810,8 @@ ep_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job)
if (!partition || !child) if (!partition || !child)
return B_BAD_VALUE; return B_BAD_VALUE;
LogicalPartition* logical = (LogicalPartition*)child->cookie; LogicalPartition* logical = (LogicalPartition*)child->cookie;
if (!logical) PrimaryPartition* primary = (PrimaryPartition*)partition->cookie;
if (!logical || !primary)
return B_BAD_VALUE; return B_BAD_VALUE;
// validate the new size // validate the new size
@@ -1810,17 +1826,17 @@ ep_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job)
update_disk_device_job_progress(job, 0.0); update_disk_device_job_progress(job, 0.0);
logical->SetSize(validatedSize); logical->SetSize(validatedSize);
PartitionMapWriter writer(fd, partition->offset, partition->size); PartitionMapWriter writer(fd, partition->block_size);
// TODO: The partition is not supposed to be locked here! // TODO: The partition is not supposed to be locked here!
status_t error = writer.WriteLogical(NULL, logical); status_t error = writer.WriteLogical(logical, primary, false);
if (error != B_OK) { if (error != B_OK) {
// putting into previous state // putting into previous state
logical->SetSize(child->size); logical->SetSize(child->size);
return error; return error;
} }
LogicalPartition* prev = logical->Previous(); LogicalPartition* prev = logical->Previous();
error = prev ? writer.WriteLogical(NULL, prev) error = prev ? writer.WriteLogical(prev, primary, false)
: writer.WriteExtendedHead(NULL, logical); : writer.WriteLogical(logical, primary, false);
if (error != B_OK) if (error != B_OK)
// this should be not so fatal // this should be not so fatal
return error; return error;
@@ -1882,7 +1898,8 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID,
if (!partition || !child) if (!partition || !child)
return B_BAD_VALUE; return B_BAD_VALUE;
LogicalPartition* logical = (LogicalPartition*)child->cookie; LogicalPartition* logical = (LogicalPartition*)child->cookie;
if (!logical) PrimaryPartition* primary = (PrimaryPartition*)partition->cookie;
if (!logical || !primary)
return B_BAD_VALUE; return B_BAD_VALUE;
// TODO: The parameter has already been checked and must not be altered! // TODO: The parameter has already been checked and must not be altered!
@@ -1898,7 +1915,8 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID,
// buffer allocation // buffer allocation
int32 allocated; int32 allocated;
uint8 *buffer = allocate_buffer(SECTOR_SIZE, MAX_MOVE_BUFFER, &allocated); uint8* buffer = allocate_buffer(partition->block_size, MAX_MOVE_BUFFER,
&allocated);
if (!buffer) if (!buffer)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -1909,7 +1927,7 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID,
off_t pts_offset = logical->Offset() - logical->PartitionTableOffset(); off_t pts_offset = logical->Offset() - logical->PartitionTableOffset();
error = move_partition(fd, child->offset - pts_offset, error = move_partition(fd, child->offset - pts_offset,
validatedOffset - pts_offset, child->size + pts_offset, buffer, validatedOffset - pts_offset, child->size + pts_offset, buffer,
allocated * SECTOR_SIZE, job); allocated * partition->block_size, job);
delete[] buffer; delete[] buffer;
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -1920,18 +1938,18 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID,
logical->SetOffset(logical->Offset() + diffOffset); logical->SetOffset(logical->Offset() + diffOffset);
logical->SetPartitionTableOffset(logical->PartitionTableOffset() + diffOffset); logical->SetPartitionTableOffset(logical->PartitionTableOffset() + diffOffset);
PartitionMapWriter writer(fd, partition->offset, partition->size); PartitionMapWriter writer(fd, partition->block_size);
// TODO: If partition->offset is > prev->offset, then writing // TODO: If partition->offset is > prev->offset, then writing
// the previous logical partition table will fail! // the previous logical partition table will fail!
// TODO: The partition is not supposed to be locked here! // TODO: The partition is not supposed to be locked here!
error = writer.WriteLogical(NULL, logical); error = writer.WriteLogical(logical, primary, false);
if (error != B_OK) if (error != B_OK)
// something went wrong - this is fatal (partition has been moved) // something went wrong - this is fatal (partition has been moved)
// but EBR is not updated // but EBR is not updated
return error; return error;
LogicalPartition* prev = logical->Previous(); LogicalPartition* prev = logical->Previous();
error = prev ? writer.WriteLogical(NULL, prev) error = prev ? writer.WriteLogical(prev, primary, false)
: writer.WriteExtendedHead(NULL, logical); : writer.WriteLogical(logical, primary, false);
if (error != B_OK) if (error != B_OK)
// this is fatal - linked list is not updated // this is fatal - linked list is not updated
return error; return error;
@@ -1962,7 +1980,8 @@ ep_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job)
if (!partition || !child) if (!partition || !child)
return B_BAD_VALUE; return B_BAD_VALUE;
LogicalPartition* logical = (LogicalPartition*)child->cookie; LogicalPartition* logical = (LogicalPartition*)child->cookie;
if (!logical) PrimaryPartition* primary = (PrimaryPartition*)partition->cookie;
if (!logical || !primary)
return B_BAD_VALUE; return B_BAD_VALUE;
// TODO: The parameter has already been checked and must not be altered! // TODO: The parameter has already been checked and must not be altered!
@@ -1984,9 +2003,9 @@ ep_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job)
uint8 oldType = logical->Type(); uint8 oldType = logical->Type();
logical->SetType(ptype.Type()); logical->SetType(ptype.Type());
PartitionMapWriter writer(fd, partition->offset, partition->size); PartitionMapWriter writer(fd, partition->block_size);
// TODO: The partition is not supposed to be locked here! // TODO: The partition is not supposed to be locked here!
status_t error = writer.WriteLogical(NULL, logical); status_t error = writer.WriteLogical(logical, primary, false);
if (error != B_OK) { if (error != B_OK) {
// something went wrong - putting into previous state // something went wrong - putting into previous state
logical->SetType(oldType); logical->SetType(oldType);
@@ -2021,7 +2040,8 @@ ep_initialize(int fd, partition_id partitionID, const char *name,
// get partition // get partition
partition_data* partition = get_partition(partitionID); partition_data* partition = get_partition(partitionID);
if (!partition) PrimaryPartition* primary = (PrimaryPartition*)partition->cookie;
if (!partition || !primary)
return B_BAD_VALUE; return B_BAD_VALUE;
// name is ignored - we cannot set it to the Intel Extended Partition // name is ignored - we cannot set it to the Intel Extended Partition
@@ -2031,7 +2051,6 @@ ep_initialize(int fd, partition_id partitionID, const char *name,
// partition init (we have no child partition) // partition init (we have no child partition)
update_disk_device_job_progress(job, 0.0); update_disk_device_job_progress(job, 0.0);
PrimaryPartition *primary = (PrimaryPartition*)partition->cookie;
// fill in the partition_data structure // fill in the partition_data structure
partition->status = B_PARTITION_VALID; partition->status = B_PARTITION_VALID;
partition->flags |= B_PARTITION_PARTITIONING_SYSTEM; partition->flags |= B_PARTITION_PARTITIONING_SYSTEM;
@@ -2044,9 +2063,9 @@ ep_initialize(int fd, partition_id partitionID, const char *name,
partition_table table; partition_table table;
table.clear_code_area(); table.clear_code_area();
PartitionMapWriter writer(fd, partition->offset, partition->size); PartitionMapWriter writer(fd, partition->block_size);
// TODO: The partition is not supposed to be locked here! // TODO: The partition is not supposed to be locked here!
status_t error = writer.WriteExtendedHead(&table, NULL); status_t error = writer.ClearExtendedHead(primary);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -2076,25 +2095,22 @@ ep_create_child(int fd, partition_id partitionID, off_t offset, off_t size,
if (!locker.IsLocked()) if (!locker.IsLocked())
return B_ERROR; return B_ERROR;
// get parent, partition and PrimaryPartition structure
partition_data *parent = get_parent_partition(partitionID);
partition_data* partition = get_partition(partitionID); partition_data* partition = get_partition(partitionID);
if (!parent || !partition) partition_data* device = get_parent_partition(partitionID);
if (partition == NULL || device == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
PrimaryPartition* primary = (PrimaryPartition*)partition->cookie; PrimaryPartition* primary = (PrimaryPartition*)partition->cookie;
if (!primary) if (!primary)
return B_BAD_VALUE; return B_BAD_VALUE;
// validate the offset, size and get index of the new partition // validate the offset, size and get index of the new partition
// TODO: The parameter has already been checked and must not be altered!
off_t validatedOffset = offset; off_t validatedOffset = offset;
off_t validatedSize = size; off_t validatedSize = size;
int32 index = 0; int32 index = 0;
if (!ep_validate_create_child(partition, &validatedOffset, &validatedSize, if (!ep_validate_create_child(partition, &validatedOffset, &validatedSize,
type, name, parameters, &index)) { type, name, parameters, &index))
return B_BAD_VALUE; return B_BAD_VALUE;
}
LogicalPartition* logical = new(nothrow) LogicalPartition; LogicalPartition* logical = new(nothrow) LogicalPartition;
if (!logical) if (!logical)
@@ -2104,54 +2120,60 @@ ep_create_child(int fd, partition_id partitionID, off_t offset, off_t size,
update_disk_device_job_progress(job, 0.0); update_disk_device_job_progress(job, 0.0);
partition_data* child = create_child_partition(partition->id, index, partition_data* child = create_child_partition(partition->id, index,
validatedOffset, validatedSize, *childID); validatedOffset, validatedSize, *childID);
if (!child) { if (!child)
delete logical;
return B_ERROR; return B_ERROR;
}
PartitionType ptype; PartitionType ptype;
ptype.SetType(type); ptype.SetType(type);
logical->SetPartitionTableOffset(
logical->SetPartitionTableOffset(validatedOffset - PTS_OFFSET * SECTOR_SIZE validatedOffset - FREE_SECTORS_AFTER_PTS * partition->block_size);
- partition->offset); logical->SetOffset(validatedOffset);
logical->SetOffset(validatedOffset - partition->offset);
logical->SetSize(validatedSize); logical->SetSize(validatedSize);
logical->SetType(ptype.Type()); logical->SetType(ptype.Type());
// TODO: correctly fill active parameter
logical->SetActive(false); logical->SetActive(false);
logical->SetPrimaryPartition(primary);
logical->SetBlockSize(partition->block_size);
primary->AddLogicalPartition(logical);
// we delete code area in EBR - nothing should be there // If the table offset of this partition is supposed to be at the start
partition_table table; // of the extended partition, but is not the first logical partition to
table.clear_code_area(); // be written, then increased the table offset by one block.
if (logical->PartitionTableOffset() == primary->Offset()
&& logical->Previous() != NULL) {
logical->SetPartitionTableOffset(logical->PartitionTableOffset()
+ logical->BlockSize());
}
int deviceFD = open_partition(device->id, O_RDWR);
if (deviceFD < 0)
return B_IO_ERROR;
// write changes to disk // write changes to disk
PartitionMapWriter writer(fd, partition->offset, partition->size); PartitionMapWriter writer(deviceFD, primary->BlockSize());
// TODO: wrong offset range, writing prev will fail // Write the logical partition's EBR first in case of failure.
// This way we will not add a partition to the previous logical
// partition. If there is no previous logical partition then write
// the current partition's EBR to the first sector of the primary partition
// TODO: The partition is not supposed to be locked here! status_t error = writer.WriteLogical(logical, primary, true);
status_t error = writer.WriteLogical(&table, logical);
if (error != B_OK) { if (error != B_OK) {
// putting into previous state
delete_partition(child->id);
delete logical;
return error;
}
// update linked list
primary->AddLogicalPartition(logical);
LogicalPartition *prev = logical->Previous();
error = prev ? writer.WriteLogical(NULL, prev)
: writer.WriteExtendedHead(NULL, logical);
if (error != B_OK) {
// putting into previous state
delete_partition(child->id);
primary->RemoveLogicalPartition(logical); primary->RemoveLogicalPartition(logical);
delete logical; delete logical;
return error; return error;
} }
LogicalPartition* previous = logical->Previous();
if (previous != NULL) {
error = writer.WriteLogical(previous, primary, true);
if (error != B_OK) {
primary->RemoveLogicalPartition(logical);
delete logical;
return error;
}
}
*childID = child->id; *childID = child->id;
child->block_size = SECTOR_SIZE; child->block_size = logical->BlockSize();
// (no name) // (no name)
child->type = strdup(type); child->type = strdup(type);
// parameters // parameters
@@ -2183,34 +2205,42 @@ ep_delete_child(int fd, partition_id partitionID, partition_id childID,
return B_ERROR; return B_ERROR;
partition_data* partition = get_partition(partitionID); partition_data* partition = get_partition(partitionID);
partition_data* device = get_parent_partition(partitionID);
partition_data* child = get_partition(childID); partition_data* child = get_partition(childID);
if (!partition || !child) if (partition == NULL || device == NULL || child == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
PrimaryPartition* primary = (PrimaryPartition*)partition->cookie; PrimaryPartition* primary = (PrimaryPartition*)partition->cookie;
LogicalPartition* logical = (LogicalPartition*)child->cookie; LogicalPartition* logical = (LogicalPartition*)child->cookie;
if (!primary || !logical) if (primary == NULL || logical == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
// deleting child // deleting child
update_disk_device_job_progress(job, 0.0); update_disk_device_job_progress(job, 0.0);
if (!delete_partition(childID)) if (!delete_partition(childID))
return B_ERROR; return B_ERROR;
LogicalPartition *next_logical = logical->Next(); LogicalPartition* previous = logical->Previous();
LogicalPartition *prev_logical = logical->Previous(); LogicalPartition* next = logical->Next();
primary->RemoveLogicalPartition(logical); primary->RemoveLogicalPartition(logical);
delete logical; delete logical;
int deviceFD = open_partition(device->id, O_RDWR);
if (deviceFD < 0)
return B_IO_ERROR;
// write changes to disk // write changes to disk
PartitionMapWriter writer(fd, partition->offset, partition->size); PartitionMapWriter writer(deviceFD, primary->BlockSize());
// TODO: Check offset range! Writing "prev/next_logical"?
// Should be parent->offset and parent->size? status_t error = previous ? writer.WriteLogical(previous, primary, true)
// TODO: The partition is not supposed to be locked here! : writer.WriteExtendedHead(next, primary, true);
status_t error = prev_logical ? writer.WriteLogical(NULL, prev_logical)
: writer.WriteExtendedHead(NULL, next_logical); if (error != B_OK) {
if (error != B_OK) delete logical;
return error; return error;
}
// all changes applied // all changes applied
update_disk_device_job_progress(job, 1.0); update_disk_device_job_progress(job, 1.0);
@@ -154,6 +154,22 @@ get_child_partition(partition_id partitionID, int32 index)
} }
int
open_partition(partition_id partitionID, int openMode)
{
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
KPartition *partition = manager->FindPartition(partitionID);
if (partition == NULL)
return B_BAD_VALUE;
int fd = -1;
status_t result = partition->Open(openMode, &fd);
if (result != B_OK)
return -1;
return fd;
}
// create_child_partition // create_child_partition
partition_data * partition_data *
create_child_partition(partition_id partitionID, int32 index, off_t offset, create_child_partition(partition_id partitionID, int32 index, off_t offset,