mirror of
https://review.haiku-os.org/haiku
synced 2025-02-09 23:27:57 +01:00
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@11909 a95241bf-73f2-0310-859d-f6bbb57e9c96
143 lines
4.9 KiB
C++
143 lines
4.9 KiB
C++
//----------------------------------------------------------------------
|
|
// This software is part of the OpenBeOS distribution and is covered
|
|
// by the OpenBeOS license.
|
|
//
|
|
// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
|
|
//----------------------------------------------------------------------
|
|
|
|
/*! \file PartitionAllocator.h
|
|
|
|
Udf physical partition allocator (implementation).
|
|
*/
|
|
|
|
#include "PhysicalPartitionAllocator.h"
|
|
|
|
Udf::extent_address PhysicalPartitionAllocator::dummyExtent;
|
|
|
|
PhysicalPartitionAllocator::PhysicalPartitionAllocator(uint16 number,
|
|
uint32 offset,
|
|
Allocator &allocator)
|
|
: fNumber(number)
|
|
, fOffset(offset)
|
|
, fAllocator(allocator)
|
|
{
|
|
|
|
}
|
|
|
|
/*! \brief Allocates the next available block.
|
|
|
|
\param block Output parameter into which the number of the
|
|
allocated block (in the partition) is stored.
|
|
\param physicalBlock Output parameter into which the number of the
|
|
allocated block (on the physical volume) is
|
|
stored.
|
|
|
|
\return
|
|
- B_OK: Success.
|
|
- error code: Failure, no blocks available.
|
|
*/
|
|
status_t
|
|
PhysicalPartitionAllocator::GetNextBlock(uint32 &block, uint32 &physicalBlock)
|
|
{
|
|
status_t error = fAllocator.GetNextBlock(physicalBlock, fOffset);
|
|
if (!error)
|
|
block = physicalBlock-fOffset;
|
|
return error;
|
|
}
|
|
|
|
/*! \brief Allocates the next available extent of given length.
|
|
|
|
\param length The desired length (in bytes) of the extent.
|
|
\param contiguous If false, signals that an extent of shorter length will
|
|
be accepted. This allows for small chunks of
|
|
unallocated space to be consumed, provided a
|
|
contiguous chunk is not needed.
|
|
\param extent Output parameter into which the extent as allocated
|
|
in the partition is stored. Note that the length
|
|
field of the extent may be shorter than the length
|
|
parameter passed to this function is \a contiguous is
|
|
false.
|
|
\param physicalExtent Output parameter into which the extent as allocated
|
|
on the physical volume is stored. Note that the length
|
|
field of the extent may be shorter than the length
|
|
parameter passed to this function is \a contiguous is
|
|
false.
|
|
|
|
\return
|
|
- B_OK: Success.
|
|
- error code: Failure.
|
|
*/
|
|
status_t
|
|
PhysicalPartitionAllocator::GetNextExtent(uint32 length,
|
|
bool contiguous,
|
|
Udf::long_address &extent,
|
|
Udf::extent_address &physicalExtent)
|
|
{
|
|
status_t error = fAllocator.GetNextExtent(length, contiguous, physicalExtent, fOffset);
|
|
if (!error) {
|
|
extent.set_partition(PartitionNumber());
|
|
extent.set_block(physicalExtent.location()-fOffset);
|
|
extent.set_length(physicalExtent.length());
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/*! \brief Allocates enough extents to add up to length bytes and stores said
|
|
extents in the given address lists.
|
|
|
|
\param length The desired length (in bytes) to be allocated.
|
|
\param extents Output parameter into which the extents as allocated
|
|
in the partition are stored.
|
|
\param physicalExtent Output parameter into which the extents as allocated
|
|
on the physical volume are stored.
|
|
|
|
\return
|
|
- B_OK: Success.
|
|
- error code: Failure.
|
|
*/
|
|
status_t
|
|
PhysicalPartitionAllocator::GetNextExtents(off_t length, std::list<Udf::long_address> &extents,
|
|
std::list<Udf::extent_address> &physicalExtents)
|
|
{
|
|
DEBUG_INIT_ETC("PhysicalPartitionAllocator", ("length: %lld", length));
|
|
extents.empty();
|
|
physicalExtents.empty();
|
|
|
|
// Allocate extents until we're done or we hit an error
|
|
status_t error = B_OK;
|
|
while (error == B_OK) {
|
|
Udf::long_address extent;
|
|
Udf::extent_address physicalExtent;
|
|
uint32 chunkLength = length <= ULONG_MAX ? uint32(length) : ULONG_MAX;
|
|
error = GetNextExtent(chunkLength, false, extent, physicalExtent);
|
|
if (!error) {
|
|
extents.push_back(extent);
|
|
physicalExtents.push_back(physicalExtent);
|
|
if (physicalExtent.length() > chunkLength) {
|
|
// This should never happen, but just to be safe
|
|
PRINT(("ERROR: allocated extent length longer than requested "
|
|
" extent length (allocated: %ld, requested: %ld)\n",
|
|
physicalExtent.length(), chunkLength));
|
|
error = B_ERROR;
|
|
} else {
|
|
// ToDo: Might want to add some checks for 0 length allocations here
|
|
length -= physicalExtent.length();
|
|
if (length == 0) {
|
|
// All done
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
RETURN(error);
|
|
}
|
|
|
|
/*! \brief Returns the length of the partition in blocks.
|
|
*/
|
|
uint32
|
|
PhysicalPartitionAllocator::Length() const
|
|
{
|
|
uint32 length = fAllocator.Length();
|
|
return fOffset >= length ? 0 : length-fOffset;
|
|
}
|