1//---------------------------------------------------------------------- 2// This software is part of the OpenBeOS distribution and is covered 3// by the OpenBeOS license. 4// 5// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net 6//---------------------------------------------------------------------- 7 8/*! \file PartitionAllocator.h 9 10 Udf physical partition allocator (implementation). 11*/ 12 13#include "PhysicalPartitionAllocator.h" 14 15Udf::extent_address PhysicalPartitionAllocator::dummyExtent; 16 17PhysicalPartitionAllocator::PhysicalPartitionAllocator(uint16 number, 18 uint32 offset, 19 Allocator &allocator) 20 : fNumber(number) 21 , fOffset(offset) 22 , fAllocator(allocator) 23{ 24 25} 26 27/*! \brief Allocates the next available block. 28 29 \param block Output parameter into which the number of the 30 allocated block (in the partition) is stored. 31 \param physicalBlock Output parameter into which the number of the 32 allocated block (on the physical volume) is 33 stored. 34 35 \return 36 - B_OK: Success. 37 - error code: Failure, no blocks available. 38*/ 39status_t 40PhysicalPartitionAllocator::GetNextBlock(uint32 &block, uint32 &physicalBlock) 41{ 42 status_t error = fAllocator.GetNextBlock(physicalBlock, fOffset); 43 if (!error) 44 block = physicalBlock-fOffset; 45 return error; 46} 47 48/*! \brief Allocates the next available extent of given length. 49 50 \param length The desired length (in bytes) of the extent. 51 \param contiguous If false, signals that an extent of shorter length will 52 be accepted. This allows for small chunks of 53 unallocated space to be consumed, provided a 54 contiguous chunk is not needed. 55 \param extent Output parameter into which the extent as allocated 56 in the partition is stored. Note that the length 57 field of the extent may be shorter than the length 58 parameter passed to this function is \a contiguous is 59 false. 60 \param physicalExtent Output parameter into which the extent as allocated 61 on the physical volume is stored. Note that the length 62 field of the extent may be shorter than the length 63 parameter passed to this function is \a contiguous is 64 false. 65 66 \return 67 - B_OK: Success. 68 - error code: Failure. 69*/ 70status_t 71PhysicalPartitionAllocator::GetNextExtent(uint32 length, 72 bool contiguous, 73 Udf::long_address &extent, 74 Udf::extent_address &physicalExtent) 75{ 76 status_t error = fAllocator.GetNextExtent(length, contiguous, physicalExtent, fOffset); 77 if (!error) { 78 extent.set_partition(PartitionNumber()); 79 extent.set_block(physicalExtent.location()-fOffset); 80 extent.set_length(physicalExtent.length()); 81 } 82 return error; 83} 84 85/*! \brief Allocates enough extents to add up to length bytes and stores said 86 extents in the given address lists. 87 88 \param length The desired length (in bytes) to be allocated. 89 \param extents Output parameter into which the extents as allocated 90 in the partition are stored. 91 \param physicalExtent Output parameter into which the extents as allocated 92 on the physical volume are stored. 93 94 \return 95 - B_OK: Success. 96 - error code: Failure. 97*/ 98status_t 99PhysicalPartitionAllocator::GetNextExtents(off_t length, std::list<Udf::long_address> &extents, 100 std::list<Udf::extent_address> &physicalExtents) 101{ 102 DEBUG_INIT_ETC("PhysicalPartitionAllocator", ("length: %lld", length)); 103 extents.empty(); 104 physicalExtents.empty(); 105 106 // Allocate extents until we're done or we hit an error 107 status_t error = B_OK; 108 while (error == B_OK) { 109 Udf::long_address extent; 110 Udf::extent_address physicalExtent; 111 uint32 chunkLength = length <= ULONG_MAX ? uint32(length) : ULONG_MAX; 112 error = GetNextExtent(chunkLength, false, extent, physicalExtent); 113 if (!error) { 114 extents.push_back(extent); 115 physicalExtents.push_back(physicalExtent); 116 if (physicalExtent.length() > chunkLength) { 117 // This should never happen, but just to be safe 118 PRINT(("ERROR: allocated extent length longer than requested " 119 " extent length (allocated: %ld, requested: %ld)\n", 120 physicalExtent.length(), chunkLength)); 121 error = B_ERROR; 122 } else { 123 // ToDo: Might want to add some checks for 0 length allocations here 124 length -= physicalExtent.length(); 125 if (length == 0) { 126 // All done 127 break; 128 } 129 } 130 } 131 } 132 RETURN(error); 133} 134 135/*! \brief Returns the length of the partition in blocks. 136*/ 137uint32 138PhysicalPartitionAllocator::Length() const 139{ 140 uint32 length = fAllocator.Length(); 141 return fOffset >= length ? 0 : length-fOffset; 142} 143