Added support for relocation.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4839 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -344,6 +344,7 @@ KDiskDevice::WriteUserData(UserDataWriter &writer, bool shadow)
|
|||||||
if (data) {
|
if (data) {
|
||||||
data->device_flags = DeviceFlags();
|
data->device_flags = DeviceFlags();
|
||||||
data->path = path;
|
data->path = path;
|
||||||
|
writer.AddRelocationEntry(&data->path);
|
||||||
partition->WriteUserData(writer, &data->device_partition_data);
|
partition->WriteUserData(writer, &data->device_partition_data);
|
||||||
} else
|
} else
|
||||||
partition->WriteUserData(writer, NULL);
|
partition->WriteUserData(writer, NULL);
|
||||||
|
|||||||
@@ -938,13 +938,22 @@ KPartition::WriteUserData(UserDataWriter &writer, user_partition_data *data)
|
|||||||
data->parameters = parameters;
|
data->parameters = parameters;
|
||||||
data->content_parameters = contentParameters;
|
data->content_parameters = contentParameters;
|
||||||
data->child_count = CountChildren();
|
data->child_count = CountChildren();
|
||||||
|
// make buffer relocatable
|
||||||
|
writer.AddRelocationEntry(&data->name);
|
||||||
|
writer.AddRelocationEntry(&data->content_name);
|
||||||
|
writer.AddRelocationEntry(&data->type);
|
||||||
|
writer.AddRelocationEntry(&data->content_type);
|
||||||
|
writer.AddRelocationEntry(&data->parameters);
|
||||||
|
writer.AddRelocationEntry(&data->content_parameters);
|
||||||
}
|
}
|
||||||
// children
|
// children
|
||||||
for (int32 i = 0; KPartition *child = ChildAt(i); i++) {
|
for (int32 i = 0; KPartition *child = ChildAt(i); i++) {
|
||||||
user_partition_data *childData
|
user_partition_data *childData
|
||||||
= writer.AllocatePartitionData(child->CountChildren());
|
= writer.AllocatePartitionData(child->CountChildren());
|
||||||
if (data)
|
if (data) {
|
||||||
data->children[i] = childData;
|
data->children[i] = childData;
|
||||||
|
writer.AddRelocationEntry(&data->children[i]);
|
||||||
|
}
|
||||||
child->WriteUserData(writer, childData);
|
child->WriteUserData(writer, childData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,87 @@
|
|||||||
// UserDataWriter.cpp
|
// UserDataWriter.cpp
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include <ddm_userland_interface.h>
|
#include <ddm_userland_interface.h>
|
||||||
|
#include <Vector.h>
|
||||||
|
|
||||||
#include "UserDataWriter.h"
|
#include "UserDataWriter.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
typedef uint8 *addr;
|
||||||
|
|
||||||
|
// RelocationEntryList
|
||||||
|
struct UserDataWriter::RelocationEntryList : Vector<addr*> {};
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
UserDataWriter::UserDataWriter()
|
UserDataWriter::UserDataWriter()
|
||||||
: fBuffer(NULL),
|
: fBuffer(NULL),
|
||||||
fBufferSize(0),
|
fBufferSize(0),
|
||||||
fAllocatedSize(0)
|
fAllocatedSize(0),
|
||||||
|
fRelocationEntries(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
UserDataWriter::UserDataWriter(user_disk_device_data *buffer,
|
UserDataWriter::UserDataWriter(user_disk_device_data *buffer,
|
||||||
size_t bufferSize)
|
size_t bufferSize)
|
||||||
: fBuffer(buffer),
|
: fBuffer(NULL),
|
||||||
fBufferSize(bufferSize),
|
fBufferSize(0),
|
||||||
fAllocatedSize(0)
|
fAllocatedSize(0),
|
||||||
|
fRelocationEntries(NULL)
|
||||||
{
|
{
|
||||||
|
SetTo(buffer, bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
UserDataWriter::~UserDataWriter()
|
UserDataWriter::~UserDataWriter()
|
||||||
{
|
{
|
||||||
|
delete fRelocationEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo
|
||||||
|
status_t
|
||||||
|
UserDataWriter::SetTo(user_disk_device_data *buffer, size_t bufferSize)
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
fBuffer = buffer;
|
||||||
|
fBufferSize = bufferSize;
|
||||||
|
fAllocatedSize = 0;
|
||||||
|
if (fBuffer && fBufferSize > 0) {
|
||||||
|
fRelocationEntries = new(nothrow) RelocationEntryList;
|
||||||
|
if (!fRelocationEntries)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset
|
||||||
|
void
|
||||||
|
UserDataWriter::Unset()
|
||||||
|
{
|
||||||
|
delete fRelocationEntries;
|
||||||
|
fBuffer = NULL;
|
||||||
|
fBufferSize = 0;
|
||||||
|
fAllocatedSize = 0;
|
||||||
|
fRelocationEntries = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllocateData
|
// AllocateData
|
||||||
void *
|
void *
|
||||||
UserDataWriter::AllocateData(size_t size, size_t align = 1)
|
UserDataWriter::AllocateData(size_t size, size_t align = 1)
|
||||||
{
|
{
|
||||||
if (size == 0)
|
// handles size == 0 gracefully
|
||||||
return NULL;
|
// get a properly aligned offset
|
||||||
|
size_t offset = fAllocatedSize;
|
||||||
if (align > 1)
|
if (align > 1)
|
||||||
fAllocatedSize = (fAllocatedSize + align - 1) / align * align;
|
offset = (fAllocatedSize + align - 1) / align * align;
|
||||||
|
// get the result pointer
|
||||||
void *result = NULL;
|
void *result = NULL;
|
||||||
if (fAllocatedSize + size <= fBufferSize)
|
if (fBuffer && offset + size <= fBufferSize)
|
||||||
result = (uint8*)fBuffer + fAllocatedSize;
|
result = (uint8*)fBuffer + offset;
|
||||||
fAllocatedSize += size;
|
// always update the allocated size, even if there wasn't enough space
|
||||||
|
fAllocatedSize = offset + size;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,3 +125,29 @@ UserDataWriter::AllocatedSize() const
|
|||||||
return fAllocatedSize;
|
return fAllocatedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRelocationEntry
|
||||||
|
status_t
|
||||||
|
UserDataWriter::AddRelocationEntry(void *address)
|
||||||
|
{
|
||||||
|
if (fRelocationEntries && (addr)address >= (addr)fBuffer
|
||||||
|
&& (addr)address < (addr)fBuffer + fBufferSize - sizeof(void*)) {
|
||||||
|
return fRelocationEntries->PushBack((addr*)address);
|
||||||
|
}
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relocate
|
||||||
|
status_t
|
||||||
|
UserDataWriter::Relocate(void *address)
|
||||||
|
{
|
||||||
|
if (!fRelocationEntries || !fBuffer)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
int32 count = fRelocationEntries->Count();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
addr *entry = fRelocationEntries->ElementAt(i);
|
||||||
|
if (*entry)
|
||||||
|
*entry += (addr)address - (addr)fBuffer;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ public:
|
|||||||
UserDataWriter(user_disk_device_data *buffer, size_t bufferSize);
|
UserDataWriter(user_disk_device_data *buffer, size_t bufferSize);
|
||||||
~UserDataWriter();
|
~UserDataWriter();
|
||||||
|
|
||||||
|
status_t SetTo(user_disk_device_data *buffer, size_t bufferSize);
|
||||||
|
void Unset();
|
||||||
|
|
||||||
void *AllocateData(size_t size, size_t align = 1);
|
void *AllocateData(size_t size, size_t align = 1);
|
||||||
user_partition_data *AllocatePartitionData(size_t childCount);
|
user_partition_data *AllocatePartitionData(size_t childCount);
|
||||||
user_disk_device_data *AllocateDeviceData(size_t childCount);
|
user_disk_device_data *AllocateDeviceData(size_t childCount);
|
||||||
@@ -25,10 +28,16 @@ public:
|
|||||||
|
|
||||||
size_t AllocatedSize() const;
|
size_t AllocatedSize() const;
|
||||||
|
|
||||||
|
status_t AddRelocationEntry(void *address);
|
||||||
|
status_t Relocate(void *address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct RelocationEntryList;
|
||||||
|
|
||||||
user_disk_device_data *fBuffer;
|
user_disk_device_data *fBuffer;
|
||||||
size_t fBufferSize;
|
size_t fBufferSize;
|
||||||
size_t fAllocatedSize;
|
size_t fAllocatedSize;
|
||||||
|
RelocationEntryList *fRelocationEntries;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace DiskDevice
|
} // namespace DiskDevice
|
||||||
|
|||||||
Reference in New Issue
Block a user