Added minimum block support needed by the physical partition allocator.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5647 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder 2003-12-11 06:10:03 +00:00
parent d8b4553a67
commit 52368aac43
2 changed files with 55 additions and 17 deletions

View File

@ -112,43 +112,49 @@ Allocator::GetExtent(Udf::extent_address extent)
\param block Output parameter into which the number of the \param block Output parameter into which the number of the
allocated block is stored. allocated block is stored.
\param minimumBlock The minimum acceptable block number (used
by the physical partition allocator).
\return \return
- B_OK: Success. - B_OK: Success.
- error code: Failure, no blocks available. - error code: Failure, no blocks available.
*/ */
status_t status_t
Allocator::GetNextBlock(uint32 &block) Allocator::GetNextBlock(uint32 &block, uint32 minimumBlock)
{ {
status_t error = InitCheck(); status_t error = InitCheck();
if (!error) { if (!error) {
Udf::extent_address extent; Udf::extent_address extent;
error = GetNextExtent(BlockSize(), true, extent); error = GetNextExtent(BlockSize(), true, extent, minimumBlock);
if (!error) if (!error)
block = extent.location(); block = extent.location();
} }
return error; return error;
} }
/*! \brief Allocates the next available block. /*! \brief Allocates the next available extent of given length.
\param length The desired length (in bytes) of the extent. \param length The desired length (in bytes) of the extent.
\param contiguous If false, signals that an extent of shorter length will \param contiguous If false, signals that an extent of shorter length will
be accepted. This allows for small chunks of be accepted. This allows for small chunks of
unallocated space to be consumed, provided a unallocated space to be consumed, provided a
contiguous chunk is not needed. contiguous chunk is not needed.
\param block Output parameter into which the extent as allocated \param extent Output parameter into which the extent as allocated
is stored. Note that the length field of the extent is stored. Note that the length field of the extent
may be shorter than the length parameter passed may be shorter than the length parameter passed
to this function is \a contiguous is false. to this function is \a contiguous is false.
\param minimumStartingBlock The minimum acceptable starting block
for the extent (used by the physical
partition allocator).
\return \return
- B_OK: Success. - B_OK: Success.
- error code: Failure. - error code: Failure.
*/ */
status_t status_t
Allocator::GetNextExtent(uint32 _length, bool contiguous, Allocator::GetNextExtent(uint32 _length, bool contiguous,
Udf::extent_address &extent) Udf::extent_address &extent,
uint32 minimumStartingBlock)
{ {
uint32 length = BlocksFor(_length); uint32 length = BlocksFor(_length);
bool isPartial = false; bool isPartial = false;
@ -159,8 +165,34 @@ Allocator::GetNextExtent(uint32 _length, bool contiguous,
i++) i++)
{ {
uint32 chunkOffset = i->location(); uint32 chunkOffset = i->location();
uint32 chunkLength = BlocksFor(i->length()); uint32 chunkLength = BlocksFor(i->length());
if (length <= chunkLength) { if (chunkOffset < minimumStartingBlock)
{
if (minimumStartingBlock < chunkOffset+chunkLength) {
// Start of chunk is below min starting block. See if
// any part of the chunk would make for an acceptable
// allocation
uint32 difference = minimumStartingBlock - chunkOffset;
uint32 newOffset = minimumStartingBlock;
uint32 newLength = chunkLength-difference;
if (length <= newLength) {
// new chunk is still long enough
Udf::extent_address newExtent(newOffset, _length);
if (GetExtent(newExtent) == B_OK) {
extent = newExtent;
return B_OK;
}
} else if (!contiguous) {
// new chunk is too short, but we're allowed to
// allocate a shorter extent, so we'll do it.
Udf::extent_address newExtent(newOffset, newLength<<BlockShift());
if (GetExtent(newExtent) == B_OK) {
extent = newExtent;
return B_OK;
}
}
}
} else if (length <= chunkLength) {
// Chunk is larger than necessary. Allocate first // Chunk is larger than necessary. Allocate first
// length blocks, and resize the chunk appropriately. // length blocks, and resize the chunk appropriately.
extent.set_location(chunkOffset); extent.set_location(chunkOffset);
@ -181,6 +213,9 @@ Allocator::GetNextExtent(uint32 _length, bool contiguous,
} }
// No sufficient chunk found, so try to allocate from the tail // No sufficient chunk found, so try to allocate from the tail
uint32 maxLength = LONG_MAX-Length(); uint32 maxLength = LONG_MAX-Length();
if (minimumStartingBlock > Tail())
maxLength -= minimumStartingBlock - Tail();
uint32 tail = minimumStartingBlock > Tail() ? minimumStartingBlock : Tail();
if (length > maxLength) { if (length > maxLength) {
if (contiguous) if (contiguous)
error = B_DEVICE_FULL; error = B_DEVICE_FULL;
@ -190,10 +225,12 @@ Allocator::GetNextExtent(uint32 _length, bool contiguous,
} }
} }
if (!error) { if (!error) {
extent.set_location(Length()); Udf::extent_address newExtent(tail, isPartial ? length<<BlockShift() : _length);
extent.set_length(isPartial ? length<<BlockShift() : _length); if (GetExtent(newExtent) == B_OK) {
fLength += length; extent = newExtent;
} return B_OK;
}
}
} }
return error; return error;
} }

View File

@ -30,9 +30,10 @@ public:
status_t GetBlock(uint32 block); status_t GetBlock(uint32 block);
status_t GetExtent(Udf::extent_address extent); status_t GetExtent(Udf::extent_address extent);
status_t GetNextBlock(uint32 &block); status_t GetNextBlock(uint32 &block, uint32 minimumBlock = 0);
status_t GetNextExtent(uint32 length, bool contiguous, status_t GetNextExtent(uint32 length, bool contiguous,
Udf::extent_address &extent); Udf::extent_address &extent,
uint32 minimumStartingBlock = 0);
uint32 Length() const { return fLength; } uint32 Length() const { return fLength; }
uint32 Tail() const { return fLength; } //!< Returns the first unallocated block in the tail uint32 Tail() const { return fLength; } //!< Returns the first unallocated block in the tail