* added some support for 64bit feature: extended struct ext2_block_group, block number types changed from uint32 to off_t

* added error traces, asserts
* BitmapBlock::CheckUnmarked() and CheckMarked() computed a wrong remainingBits and mask


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39203 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2010-10-30 13:45:01 +00:00
parent 0a5b0dae01
commit d8772e0c20
14 changed files with 434 additions and 239 deletions
@@ -251,11 +251,11 @@ Attribute::_Find(const char* name, int32 index)
// try to find it in the small data region
if (fInode->HasExtraAttributes()
&& recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
uint32 block;
fVolume->GetInodeBlock(fInode->ID(), block);
off_t blockNum;
fVolume->GetInodeBlock(fInode->ID(), blockNum);
if (block != 0) {
fBlock.SetTo(block);
if (blockNum != 0) {
fBlock.SetTo(blockNum);
const uint8* start = fBlock.Block()
+ fVolume->InodeBlockIndex(fInode->ID()) * fVolume->InodeSize();
const uint8* end = start + fVolume->InodeSize();
@@ -63,10 +63,12 @@ BitmapBlock::CheckUnmarked(uint32 start, uint32 length)
if (start + length > fNumBits)
return false;
if (length == 0)
return true;
uint32 startIndex = start >> 5;
uint32 startBit = start & 0x1F;
uint32 remainingBits = (length - startBit) & 0x1F;
uint32 remainingBits = (length + startBit) & 0x1F;
uint32 iterations;
@@ -86,28 +88,39 @@ BitmapBlock::CheckUnmarked(uint32 start, uint32 length)
uint32 index = startIndex;
uint32 mask = 0;
TRACE("BitmapBlock::CheckUnmarked(): startBit: %lu iterations %lu remainingbits %lu\n",
startBit, iterations, remainingBits);
if (startBit != 0) {
mask = ~((1 << startBit) - 1);
uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
if ((bits & mask) != 0)
if ((bits & mask) != 0) {
TRACE("BitmapBlock::CheckUnmarked(): start %lx mask %lx\n", bits, mask);
return false;
}
index += 1;
} else
iterations++;
for (; iterations > 0; --iterations) {
if (data[index++] != 0)
if (data[index++] != 0) {
TRACE("BitmapBlock::CheckUnmarked(): iterations %lu bits: %lX\n", iterations,
data[index - 1]);
return false;
}
}
if (remainingBits != 0) {
mask = (1 << (remainingBits + 1)) - 1;
mask = (1 << remainingBits) - 1;
uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
if ((bits & mask) != 0)
if ((bits & mask) != 0) {
TRACE("BitmapBlock::CheckUnmarked(): remainingBits %ld remaining %lX mask %lX\n",
remainingBits, bits, mask);
return false;
}
}
return true;
@@ -123,10 +136,12 @@ BitmapBlock::CheckMarked(uint32 start, uint32 length)
if (start + length > fNumBits)
return false;
if (length == 0)
return true;
uint32 startIndex = start >> 5;
uint32 startBit = start & 0x1F;
uint32 remainingBits = (length - startBit) & 0x1F;
uint32 remainingBits = (length + startBit) & 0x1F;
uint32 iterations;
@@ -164,7 +179,7 @@ BitmapBlock::CheckMarked(uint32 start, uint32 length)
}
if (remainingBits != 0) {
mask = (1 << (remainingBits + 1)) - 1;
mask = (1 << remainingBits) - 1;
uint32 bits = B_HOST_TO_LENDIAN_INT32(data[index]);
if ((bits & mask) != mask)
@@ -183,7 +198,7 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
uint32 startIndex = start >> 5;
uint32 startBit = start & 0x1F;
uint32 remainingBits = (length - 32 + startBit) & 0x1F;
uint32 remainingBits = (length + startBit) & 0x1F;
uint32 iterations;
@@ -194,8 +209,11 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
uint32 mask = (1 << (startBit + length)) - 1;
mask &= ~((1 << startBit) - 1);
if ((bits & mask) != 0)
if ((bits & mask) != 0) {
TRACE("BitmapBlock::Mark() Marking failed bits %lx "
"startBit %ld\n", bits, startBit);
return false;
}
bits |= mask;
@@ -221,8 +239,11 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
TRACE("BitmapBlock::Mark(): index %lu mask: %lX, bits: %lX\n", index,
mask, bits);
if (!force && (bits & mask) != 0)
if (!force && (bits & mask) != 0) {
TRACE("BitmapBlock::Mark() Marking failed bits %lx "
"startBit %ld\n", bits, startBit);
return false;
}
bits |= mask;
fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
@@ -233,8 +254,11 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
mask = 0xFFFFFFFF;
for (; iterations > 0; --iterations) {
if (!force && fData[index] != 0)
if (!force && fData[index] != 0) {
TRACE("BitmapBlock::Mark() Marking failed "
"index %ld, iterations %ld\n", index, iterations);
return false;
}
fData[index++] |= mask;
}
@@ -244,8 +268,10 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
TRACE("BitmapBlock::Mark(): marking index %lu remaining %lu bits: %lX,"
" mask: %lX\n", index, remainingBits, bits, mask);
if (!force && (bits & mask) != 0)
if (!force && (bits & mask) != 0) {
TRACE("BitmapBlock::Mark() Marking failed remaining\n");
return false;
}
bits |= mask;
fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
@@ -266,7 +292,7 @@ BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
uint32 startIndex = start >> 5;
uint32 startBit = start & 0x1F;
uint32 remainingBits = (length - 32 + startBit) & 0x1F;
uint32 remainingBits = (length + startBit) & 0x1F;
TRACE("BitmapBlock::Unmark(): start index: %lu, start bit: %lu, remaining "
"bits: %lu)\n", startIndex, startBit, remainingBits);
@@ -282,8 +308,11 @@ BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
TRACE("BitmapBlock::Unmark(): mask: %lx\n", mask);
if ((bits & mask) != mask)
if ((bits & mask) != mask) {
TRACE("BitmapBlock::Unmark() Marking failed bits %lx "
"startBit %ld\n", bits, startBit);
return false;
}
bits &= ~mask;
@@ -319,8 +348,11 @@ BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
mask = 0xFFFFFFFF;
for (; iterations > 0; --iterations) {
if (!force && fData[index] != mask)
if (!force && fData[index] != mask) {
TRACE("BitmapBlock::Unmark() Marking failed "
"index %ld, iterations %ld\n", index, iterations);
return false;
}
fData[index++] = 0;
}
@@ -332,8 +364,10 @@ BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
TRACE("BitmapBlock::Unmark(): mask: %lx, bits: %lx\n", mask, bits);
if (!force && (bits & mask) != mask)
if (!force && (bits & mask) != mask) {
TRACE("BitmapBlock::Unmark() Marking failed remaining\n");
return false;
}
bits &= ~mask;
fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
@@ -460,7 +494,7 @@ BitmapBlock::FindNextUnmarked(uint32& pos)
}
}
panic("Couldn't find unmarked bit inside an int32 whith value zero!?\n");
panic("Couldn't find unmarked bit inside an int32 with value zero!?\n");
}
@@ -504,6 +538,9 @@ BitmapBlock::FindPreviousMarked(uint32& pos)
bit = 31;
}
TRACE("BitmapBlock::FindPreviousMarked(): index: %lu bit: %lu bits: %lx\n",
index, bit, bits);
for (; bit >= 0; --bit) {
// Find the unmarked bit
if ((bits >> bit & 1) != 0) {
@@ -512,7 +549,7 @@ BitmapBlock::FindPreviousMarked(uint32& pos)
}
}
panic("Couldn't find marked bit inside an int32 whith value different than "
panic("Couldn't find marked bit inside an int32 with value different than "
"zero!?\n");
}
@@ -15,12 +15,16 @@
#include "Inode.h"
#undef ASSERT
//#define TRACE_EXT2
#ifdef TRACE_EXT2
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
# define ASSERT(x) { if (!(x)) kernel_debugger("ext2: assert failed: " #x "\n"); }
#else
# define TRACE(x...) ;
# define ASSERT(x) ;
#endif
#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
class AllocationBlockGroup : public TransactionListener {
@@ -67,7 +71,7 @@ private:
uint32 fStart;
uint32 fNumBits;
uint32 fBitmapBlock;
off_t fBitmapBlock;
uint32 fFreeBits;
uint32 fFirstFree;
@@ -122,14 +126,15 @@ AllocationBlockGroup::Initialize(Volume* volume, uint32 blockGroup,
if (status != B_OK)
return status;
fBitmapBlock = fGroupDescriptor->BlockBitmap();
fBitmapBlock = fGroupDescriptor->BlockBitmap(fVolume->Has64bitFeature());
status = ScanFreeRanges();
if (fGroupDescriptor->FreeBlocks() != fFreeBits) {
if (fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature()) != fFreeBits) {
TRACE("AllocationBlockGroup::Initialize(): Mismatch between counted "
"free blocks (%lu) and what is set on the group descriptor "
"(%lu)\n", fFreeBits, (uint32)fGroupDescriptor->FreeBlocks());
"(%lu)\n", fFreeBits,
fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature()));
return B_BAD_DATA;
}
@@ -161,6 +166,7 @@ AllocationBlockGroup::ScanFreeRanges()
if (start != block.NumBits()) {
block.FindNextMarked(end);
_AddFreeRange(start, end - start);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
start = end;
}
}
@@ -191,15 +197,19 @@ AllocationBlockGroup::Allocate(Transaction& transaction, uint32 start,
if (!block.SetToWritable(transaction, fBitmapBlock))
return B_ERROR;
TRACE("AllocationBlockGroup::Allocate(): Largest range in %lu-%lu\n",
fLargestStart, fLargestStart + fLargestLength);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
if (!block.Mark(start, length)) {
TRACE("Failed to allocate blocks from %lu to %lu. Some were "
ERROR("Failed to allocate blocks from %lu to %lu. Some were "
"already allocated.\n", start, start + length);
return B_ERROR;
}
fFreeBits -= length;
fGroupDescriptor->SetFreeBlocks((uint16)fFreeBits);
fGroupDescriptor->SetFreeBlocks(fFreeBits, fVolume->Has64bitFeature());
fVolume->WriteBlockGroup(transaction, fBlockGroup);
if (start == fLargestStart) {
@@ -227,6 +237,10 @@ AllocationBlockGroup::Allocate(Transaction& transaction, uint32 start,
return B_OK;
}
TRACE("AllocationBlockGroup::Allocate(): Largest range in %lu-%lu\n",
fLargestStart, fLargestStart + fLargestLength);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
if (fLargestLength < fNumBits / 2)
block.FindLargestUnmarkedRange(fLargestStart, fLargestLength);
@@ -256,8 +270,12 @@ AllocationBlockGroup::Free(Transaction& transaction, uint32 start,
if (!block.SetToWritable(transaction, fBitmapBlock))
return B_ERROR;
TRACE("AllocationBlockGroup::Free(): Largest range in %lu-%lu\n",
fLargestStart, fLargestStart + fLargestLength);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
if (!block.Unmark(start, length)) {
TRACE("Failed to free blocks from %lu to %lu. Some were "
ERROR("Failed to free blocks from %lu to %lu. Some were "
"already freed.\n", start, start + length);
return B_ERROR;
}
@@ -279,6 +297,7 @@ AllocationBlockGroup::Free(Transaction& transaction, uint32 start,
uint32 newStart = start;
block.FindPreviousMarked(newStart);
newStart++;
if (newEnd - newStart > fLargestLength) {
fLargestLength = newEnd - newStart;
@@ -286,8 +305,12 @@ AllocationBlockGroup::Free(Transaction& transaction, uint32 start,
}
}
TRACE("AllocationBlockGroup::Free(): Largest range in %lu-%lu\n",
fLargestStart, fLargestStart + fLargestLength);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
fFreeBits += length;
fGroupDescriptor->SetFreeBlocks((uint16)fFreeBits);
fGroupDescriptor->SetFreeBlocks(fFreeBits, fVolume->Has64bitFeature());
fVolume->WriteBlockGroup(transaction, fBlockGroup);
return B_OK;
@@ -459,17 +482,17 @@ BlockAllocator::Initialize()
status_t
BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
uint32 maximum, uint32& blockGroup, uint32& start, uint32& length)
uint32 maximum, uint32& blockGroup, off_t& start, uint32& length)
{
TRACE("BlockAllocator::AllocateBlocks()\n");
MutexLocker lock(fLock);
TRACE("BlockAllocator::AllocateBlocks(): Acquired lock\n");
TRACE("BlockAllocator::AllocateBlocks(): transaction: %ld, min: %lu, "
"max: %lu, block group: %lu, start: %lu, num groups: %lu\n",
"max: %lu, block group: %lu, start: %llu, num groups: %lu\n",
transaction.ID(), minimum, maximum, blockGroup, start, fNumGroups);
uint32 bestStart = 0;
off_t bestStart = 0;
uint32 bestLength = 0;
uint32 bestGroup = 0;
@@ -490,7 +513,7 @@ BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
bestGroup = groupNum;
TRACE("BlockAllocator::AllocateBlocks(): Found a better "
"range: block group: %lu, %lu-%lu\n", groupNum,
"range: block group: %lu, %llu-%llu\n", groupNum,
bestStart, bestStart + bestLength);
if (bestLength >= maximum)
@@ -520,7 +543,7 @@ BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
bestLength = maximum;
TRACE("BlockAllocator::AllocateBlocks(): Selected range: block group %lu, "
"%lu-%lu\n", bestGroup, bestStart, bestStart + bestLength);
"%llu-%llu\n", bestGroup, bestStart, bestStart + bestLength);
status_t status = fGroups[bestGroup].Allocate(transaction, bestStart,
bestLength);
@@ -540,7 +563,7 @@ BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
status_t
BlockAllocator::Allocate(Transaction& transaction, Inode* inode,
off_t numBlocks, uint32 minimum, uint32& start, uint32& allocated)
off_t numBlocks, uint32 minimum, off_t& start, uint32& allocated)
{
if (numBlocks <= 0)
return B_ERROR;
@@ -617,9 +640,9 @@ BlockAllocator::Allocate(Transaction& transaction, Inode* inode,
status_t
BlockAllocator::Free(Transaction& transaction, uint32 start, uint32 length)
BlockAllocator::Free(Transaction& transaction, off_t start, uint32 length)
{
TRACE("BlockAllocator::Free(%lu, %lu)\n", start, length);
TRACE("BlockAllocator::Free(%llu, %lu)\n", start, length);
MutexLocker lock(fLock);
if (start <= fFirstBlock) {
@@ -633,17 +656,19 @@ BlockAllocator::Free(Transaction& transaction, uint32 start, uint32 length)
TRACE("BlockAllocator::Free(): first block: %lu, blocks per group: %lu\n",
fFirstBlock, fBlocksPerGroup);
start -= fFirstBlock;
uint32 end = start + length - 1;
//start -= fFirstBlock;
off_t end = start + length - 1;
uint32 group = start / fBlocksPerGroup;
if (group >= fNumGroups)
panic("BlockAllocator::Free() group %ld too big (fNumGroups %ld)\n", group, fNumGroups);
uint32 lastGroup = end / fBlocksPerGroup;
start = start % fBlocksPerGroup;
if (group == lastGroup)
return fGroups[group].Free(transaction, start, length);
TRACE("BlockAllocator::Free(): Freeing from group %lu: %lu, %lu\n", group,
TRACE("BlockAllocator::Free(): Freeing from group %lu: %llu, %llu\n", group,
start, fGroups[group].NumBits() - start);
status_t status = fGroups[group].Free(transaction, start,
@@ -658,7 +683,7 @@ BlockAllocator::Free(Transaction& transaction, uint32 start, uint32 length)
return status;
}
TRACE("BlockAllocator::Free(): Freeing from group %lu: 0-%lu \n", group,
TRACE("BlockAllocator::Free(): Freeing from group %lu: 0-%llu \n", group,
end % fBlocksPerGroup);
return fGroups[group].Free(transaction, 0, (end + 1) % fBlocksPerGroup);
}
@@ -674,8 +699,8 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
AllocationBlockGroup* groups = allocator->fGroups;
uint32 numGroups = allocator->fNumGroups - 1;
uint32 freeBlocks = 0;
TRACE("BlockAllocator::_Initialize(): free blocks: %lu\n", freeBlocks);
off_t freeBlocks = 0;
TRACE("BlockAllocator::_Initialize(): free blocks: %llu\n", freeBlocks);
for (uint32 i = 0; i < numGroups; ++i) {
status_t status = groups[i].Initialize(volume, i,
@@ -686,7 +711,7 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
}
freeBlocks += groups[i].FreeBits();
TRACE("BlockAllocator::_Initialize(): free blocks: %lu\n", freeBlocks);
TRACE("BlockAllocator::_Initialize(): free blocks: %llu\n", freeBlocks);
}
// Last block group may have less blocks
@@ -700,13 +725,13 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
freeBlocks += groups[numGroups].FreeBits();
TRACE("BlockAllocator::_Initialize(): free blocks: %lu\n", freeBlocks);
TRACE("BlockAllocator::_Initialize(): free blocks: %llu\n", freeBlocks);
mutex_unlock(&allocator->fLock);
if (freeBlocks != volume->NumFreeBlocks()) {
TRACE("Counted free blocks (%lu) doesn't match value in the "
"superblock (%lu).\n", freeBlocks, (uint32)volume->NumFreeBlocks());
TRACE("Counted free blocks (%llu) doesn't match value in the "
"superblock (%llu).\n", freeBlocks, volume->NumFreeBlocks());
return B_BAD_DATA;
}
@@ -27,11 +27,11 @@ public:
status_t AllocateBlocks(Transaction& transaction,
uint32 minimum, uint32 maximum, uint32& blockGroup,
uint32& start, uint32& length);
off_t& start, uint32& length);
status_t Allocate(Transaction& transaction, Inode* inode,
off_t numBlocks, uint32 minimum, uint32& start,
off_t numBlocks, uint32 minimum, off_t& start,
uint32& length);
status_t Free(Transaction& transaction, uint32 start,
status_t Free(Transaction& transaction, off_t start,
uint32 length);
uint32 FreeBlocks();
@@ -16,16 +16,16 @@
class CachedBlock {
public:
CachedBlock(Volume* volume);
CachedBlock(Volume* volume, uint32 block);
CachedBlock(Volume* volume, off_t block);
~CachedBlock();
void Keep();
void Unset();
const uint8* SetTo(uint32 block);
const uint8* SetTo(off_t block);
uint8* SetToWritable(Transaction& transaction,
uint32 block, bool empty = false);
uint8* SetToWritableWithoutTransaction(uint32 block,
off_t block, bool empty = false);
uint8* SetToWritableWithoutTransaction(off_t block,
bool empty = false);
const uint8* Block() const { return fBlock; }
@@ -36,12 +36,12 @@ private:
CachedBlock &operator=(const CachedBlock &);
// no implementation
uint8* _SetToWritableEtc(int32 transaction, uint32 block,
uint8* _SetToWritableEtc(int32 transaction, off_t block,
bool empty);
protected:
Volume* fVolume;
uint32 fBlockNumber;
off_t fBlockNumber;
uint8* fBlock;
};
@@ -60,7 +60,7 @@ CachedBlock::CachedBlock(Volume* volume)
inline
CachedBlock::CachedBlock(Volume* volume, uint32 block)
CachedBlock::CachedBlock(Volume* volume, off_t block)
:
fVolume(volume),
fBlockNumber(0),
@@ -95,7 +95,7 @@ CachedBlock::Unset()
inline const uint8 *
CachedBlock::SetTo(uint32 block)
CachedBlock::SetTo(off_t block)
{
Unset();
fBlockNumber = block;
@@ -104,20 +104,20 @@ CachedBlock::SetTo(uint32 block)
inline uint8*
CachedBlock::SetToWritable(Transaction& transaction, uint32 block, bool empty)
CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty)
{
return _SetToWritableEtc(transaction.ID(), block, empty);
}
inline uint8*
CachedBlock::SetToWritableWithoutTransaction(uint32 block, bool empty)
CachedBlock::SetToWritableWithoutTransaction(off_t block, bool empty)
{
return _SetToWritableEtc((int32)-1, block, empty);
}
inline uint8*
CachedBlock::_SetToWritableEtc(int32 transaction, uint32 block, bool empty)
CachedBlock::_SetToWritableEtc(int32 transaction, off_t block, bool empty)
{
Unset();
fBlockNumber = block;
@@ -19,6 +19,7 @@
#else
# define TRACE(x...) ;
#endif
#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
DataStream::DataStream(Volume* volume, ext2_data_stream* stream,
@@ -51,12 +52,12 @@ DataStream::~DataStream()
status_t
DataStream::Enlarge(Transaction& transaction, uint32& numBlocks)
DataStream::Enlarge(Transaction& transaction, off_t& numBlocks)
{
TRACE("DataStream::Enlarge(): current size: %lu, target size: %lu\n",
TRACE("DataStream::Enlarge(): current size: %llu, target size: %llu\n",
fNumBlocks, numBlocks);
uint32 targetBlocks = numBlocks;
off_t targetBlocks = numBlocks;
fWaiting = _BlocksNeeded(numBlocks);
numBlocks = fWaiting;
@@ -65,42 +66,57 @@ DataStream::Enlarge(Transaction& transaction, uint32& numBlocks)
if (fNumBlocks <= kMaxDirect) {
status = _AddForDirectBlocks(transaction, targetBlocks);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::Enlarge(): _AddForDirectBlocks() failed\n");
return status;
}
TRACE("DataStream::Enlarge(): current size: %lu, target size: %lu\n",
TRACE("DataStream::Enlarge(): current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
if (fNumBlocks == targetBlocks)
return B_OK;
}
TRACE("DataStream::Enlarge(): indirect current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
if (fNumBlocks <= kMaxIndirect) {
status = _AddForIndirectBlock(transaction, targetBlocks);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::Enlarge(): _AddForIndirectBlock() failed\n");
return status;
}
TRACE("DataStream::Enlarge(): current size: %lu, target size: %lu\n",
TRACE("DataStream::Enlarge(): current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
if (fNumBlocks == targetBlocks)
return B_OK;
}
TRACE("DataStream::Enlarge(): indirect2 current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
if (fNumBlocks <= kMaxDoubleIndirect) {
status = _AddForDoubleIndirectBlock(transaction, targetBlocks);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::Enlarge(): _AddForDoubleIndirectBlock() failed\n");
return status;
}
TRACE("DataStream::Enlarge(): current size: %lu, target size: %lu\n",
TRACE("DataStream::Enlarge(): current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
if (fNumBlocks == targetBlocks)
return B_OK;
}
TRACE("DataStream::Enlarge(): indirect3 current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
TRACE("DataStream::Enlarge(): allocated: %lu, waiting: %lu\n", fAllocated,
fWaiting);
@@ -109,25 +125,27 @@ DataStream::Enlarge(Transaction& transaction, uint32& numBlocks)
status_t
DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
DataStream::Shrink(Transaction& transaction, off_t& numBlocks)
{
TRACE("DataStream::Shrink(): current size: %lu, target size: %lu\n",
TRACE("DataStream::Shrink(): current size: %llu, target size: %llu\n",
fNumBlocks, numBlocks);
fFreeStart = 0;
fFreeCount = 0;
fRemovedBlocks = 0;
uint32 oldNumBlocks = fNumBlocks;
uint32 blocksToRemove = fNumBlocks - numBlocks;
off_t oldNumBlocks = fNumBlocks;
off_t blocksToRemove = fNumBlocks - numBlocks;
status_t status;
if (numBlocks < kMaxDirect) {
status = _RemoveFromDirectBlocks(transaction, numBlocks);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::Shrink(): _RemoveFromDirectBlocks() failed\n");
return status;
}
if (fRemovedBlocks == blocksToRemove) {
fNumBlocks -= fRemovedBlocks;
@@ -140,8 +158,10 @@ DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
if (numBlocks < kMaxIndirect) {
status = _RemoveFromIndirectBlock(transaction, numBlocks);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::Shrink(): _RemoveFromIndirectBlock() failed\n");
return status;
}
if (fRemovedBlocks == blocksToRemove) {
fNumBlocks -= fRemovedBlocks;
@@ -154,8 +174,10 @@ DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
if (numBlocks < kMaxDoubleIndirect) {
status = _RemoveFromDoubleIndirectBlock(transaction, numBlocks);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::Shrink(): _RemoveFromDoubleIndirectBlock() failed\n");
return status;
}
if (fRemovedBlocks == blocksToRemove) {
fNumBlocks -= fRemovedBlocks;
@@ -167,8 +189,10 @@ DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
status = _RemoveFromTripleIndirectBlock(transaction, numBlocks);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::Shrink(): _RemoveFromTripleIndirectBlock() failed\n");
return status;
}
fNumBlocks -= fRemovedBlocks;
numBlocks = _BlocksNeeded(oldNumBlocks);
@@ -178,10 +202,10 @@ DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
uint32
DataStream::_BlocksNeeded(uint32 numBlocks)
DataStream::_BlocksNeeded(off_t numBlocks)
{
TRACE("DataStream::BlocksNeeded(): num blocks %lu\n", numBlocks);
uint32 blocksNeeded = 0;
TRACE("DataStream::BlocksNeeded(): num blocks %llu\n", numBlocks);
off_t blocksNeeded = 0;
if (numBlocks > fNumBlocks) {
blocksNeeded += numBlocks - fNumBlocks;
@@ -214,15 +238,15 @@ DataStream::_BlocksNeeded(uint32 numBlocks)
}
}
TRACE("DataStream::BlocksNeeded(): %lu\n", blocksNeeded);
TRACE("DataStream::BlocksNeeded(): %llu\n", blocksNeeded);
return blocksNeeded;
}
status_t
DataStream::_GetBlock(Transaction& transaction, uint32& block)
DataStream::_GetBlock(Transaction& transaction, uint32& blockNum)
{
TRACE("DataStream::_GetBlock(): allocated: %lu, pos: %lu, waiting: %lu\n",
TRACE("DataStream::_GetBlock(): allocated: %lu, pos: %llu, waiting: %lu\n",
fAllocated, fAllocatedPos, fWaiting);
if (fAllocated == 0) {
@@ -232,18 +256,20 @@ DataStream::_GetBlock(Transaction& transaction, uint32& block)
status_t status = fVolume->AllocateBlocks(transaction, 1, fWaiting,
blockGroup, fAllocatedPos, fAllocated);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::_GetBlock(): AllocateBlocks() failed()\n");
return status;
}
fWaiting -= fAllocated;
fAllocatedPos += fVolume->BlocksPerGroup() * blockGroup + fFirstBlock;
TRACE("DataStream::_GetBlock(): newAllocated: %lu, newpos: %lu,"
TRACE("DataStream::_GetBlock(): newAllocated: %lu, newpos: %llu,"
"newwaiting: %lu\n", fAllocated, fAllocatedPos, fWaiting);
}
fAllocated--;
block = fAllocatedPos++;
blockNum = (uint32)fAllocatedPos++;
return B_OK;
}
@@ -258,8 +284,10 @@ DataStream::_PrepareBlock(Transaction& transaction, uint32* pos,
if (blockNum == 0) {
status_t status = _GetBlock(transaction, blockNum);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::_PrepareBlock() _GetBlock() failed blockNum %ld\n", blockNum);
return status;
}
*pos = B_HOST_TO_LENDIAN_INT32(blockNum);
clear = true;
@@ -270,10 +298,10 @@ DataStream::_PrepareBlock(Transaction& transaction, uint32* pos,
status_t
DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 _count)
DataStream::_AddBlocks(Transaction& transaction, uint32* block, off_t _count)
{
uint32 count = _count;
TRACE("DataStream::_AddBlocks(): count: %lu\n", count);
off_t count = _count;
TRACE("DataStream::_AddBlocks(): count: %llu\n", count);
while (count > 0) {
uint32 blockNum;
@@ -292,10 +320,10 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 _count)
status_t
DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
uint32 end, int recursion)
DataStream::_AddBlocks(Transaction& transaction, uint32* block, off_t start,
off_t end, int recursion)
{
TRACE("DataStream::_AddBlocks(): start: %lu, end %lu, recursion: %d\n",
TRACE("DataStream::_AddBlocks(): start: %llu, end %llu, recursion: %d\n",
start, end, recursion);
bool clear;
@@ -339,8 +367,10 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
if (start % elementWidth != 0) {
status = _AddBlocks(transaction, &childBlock[elementPos],
start % elementWidth, elementWidth, recursion);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::_AddBlocks() _AddBlocks() start failed\n");
return status;
}
elementPos++;
}
@@ -348,8 +378,10 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
while (elementPos < endPos) {
status = _AddBlocks(transaction, &childBlock[elementPos], 0,
elementWidth, recursion);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::_AddBlocks() _AddBlocks() mid failed\n");
return status;
}
elementPos++;
}
@@ -357,8 +389,10 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
if (end % elementWidth != 0) {
status = _AddBlocks(transaction, &childBlock[elementPos], 0,
end % elementWidth, recursion);
if (status != B_OK)
if (status != B_OK) {
ERROR("DataStream::_AddBlocks() _AddBlocks() end failed\n");
return status;
}
}
return B_OK;
@@ -368,7 +402,7 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
status_t
DataStream::_AddForDirectBlocks(Transaction& transaction, uint32 numBlocks)
{
TRACE("DataStream::_AddForDirectBlocks(): current size: %lu, target size: "
TRACE("DataStream::_AddForDirectBlocks(): current size: %llu, target size: "
"%lu\n", fNumBlocks, numBlocks);
uint32* direct = &fStream->direct[fNumBlocks];
uint32 end = numBlocks > kMaxDirect ? kMaxDirect : numBlocks;
@@ -380,7 +414,7 @@ DataStream::_AddForDirectBlocks(Transaction& transaction, uint32 numBlocks)
status_t
DataStream::_AddForIndirectBlock(Transaction& transaction, uint32 numBlocks)
{
TRACE("DataStream::_AddForIndirectBlocks(): current size: %lu, target "
TRACE("DataStream::_AddForIndirectBlocks(): current size: %llu, target "
"size: %lu\n", fNumBlocks, numBlocks);
uint32 *indirect = &fStream->indirect;
uint32 start = fNumBlocks - kMaxDirect;
@@ -397,7 +431,7 @@ status_t
DataStream::_AddForDoubleIndirectBlock(Transaction& transaction,
uint32 numBlocks)
{
TRACE("DataStream::_AddForDoubleIndirectBlock(): current size: %lu, "
TRACE("DataStream::_AddForDoubleIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks);
uint32 *doubleIndirect = &fStream->double_indirect;
uint32 start = fNumBlocks - kMaxIndirect;
@@ -414,7 +448,7 @@ status_t
DataStream::_AddForTripleIndirectBlock(Transaction& transaction,
uint32 numBlocks)
{
TRACE("DataStream::_AddForTripleIndirectBlock(): current size: %lu, "
TRACE("DataStream::_AddForTripleIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks);
uint32 *tripleIndirect = &fStream->triple_indirect;
uint32 start = fNumBlocks - kMaxDoubleIndirect;
@@ -446,9 +480,11 @@ DataStream::_PerformFree(Transaction& transaction)
status_t
DataStream::_MarkBlockForRemoval(Transaction& transaction, uint32* block)
{
TRACE("DataStream::_MarkBlockForRemoval(*(%p) = %lu): free start: %lu, "
"free count: %lu\n", block, *block, fFreeStart, fFreeCount);
uint32 blockNum = B_LENDIAN_TO_HOST_INT32(*block);
"free count: %lu\n", block, B_LENDIAN_TO_HOST_INT32(*block),
fFreeStart, fFreeCount);
uint32 blockNum = B_LENDIAN_TO_HOST_INT32(*block);
*block = 0;
if (blockNum != fFreeStart + fFreeCount) {
@@ -491,11 +527,11 @@ DataStream::_FreeBlocks(Transaction& transaction, uint32* block, uint32 _count)
status_t
DataStream::_FreeBlocks(Transaction& transaction, uint32* block, uint32 start,
uint32 end, bool freeParent, int recursion)
DataStream::_FreeBlocks(Transaction& transaction, uint32* block, off_t start,
off_t end, bool freeParent, int recursion)
{
// TODO: Designed specifically for shrinking. Perhaps make it more general?
TRACE("DataStream::_FreeBlocks(%p, %lu, %lu, %c, %d)\n",
TRACE("DataStream::_FreeBlocks(%p, %llu, %llu, %c, %d)\n",
block, start, end, freeParent ? 't' : 'f', recursion);
uint32 blockNum = B_LENDIAN_TO_HOST_INT32(*block);
@@ -567,10 +603,10 @@ DataStream::_FreeBlocks(Transaction& transaction, uint32* block, uint32 start,
status_t
DataStream::_RemoveFromDirectBlocks(Transaction& transaction, uint32 numBlocks)
{
TRACE("DataStream::_RemoveFromDirectBlocks(): current size: %lu, "
TRACE("DataStream::_RemoveFromDirectBlocks(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks);
uint32* direct = &fStream->direct[numBlocks];
uint32 end = fNumBlocks > kMaxDirect ? kMaxDirect : fNumBlocks;
off_t end = fNumBlocks > kMaxDirect ? kMaxDirect : fNumBlocks;
return _FreeBlocks(transaction, direct, end - numBlocks);
}
@@ -579,11 +615,11 @@ DataStream::_RemoveFromDirectBlocks(Transaction& transaction, uint32 numBlocks)
status_t
DataStream::_RemoveFromIndirectBlock(Transaction& transaction, uint32 numBlocks)
{
TRACE("DataStream::_RemoveFromIndirectBlock(): current size: %lu, "
TRACE("DataStream::_RemoveFromIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks);
uint32* indirect = &fStream->indirect;
uint32 start = numBlocks <= kMaxDirect ? 0 : numBlocks - kMaxDirect;
uint32 end = fNumBlocks - kMaxDirect;
off_t start = numBlocks <= kMaxDirect ? 0 : numBlocks - kMaxDirect;
off_t end = fNumBlocks - kMaxDirect;
if (end > kIndirectsPerBlock)
end = kIndirectsPerBlock;
@@ -598,11 +634,11 @@ status_t
DataStream::_RemoveFromDoubleIndirectBlock(Transaction& transaction,
uint32 numBlocks)
{
TRACE("DataStream::_RemoveFromDoubleIndirectBlock(): current size: %lu, "
TRACE("DataStream::_RemoveFromDoubleIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks);
uint32* doubleIndirect = &fStream->double_indirect;
uint32 start = numBlocks <= kMaxIndirect ? 0 : numBlocks - kMaxIndirect;
uint32 end = fNumBlocks - kMaxIndirect;
off_t start = numBlocks <= kMaxIndirect ? 0 : numBlocks - kMaxIndirect;
off_t end = fNumBlocks - kMaxIndirect;
if (end > kIndirectsPerBlock2)
end = kIndirectsPerBlock2;
@@ -617,12 +653,12 @@ status_t
DataStream::_RemoveFromTripleIndirectBlock(Transaction& transaction,
uint32 numBlocks)
{
TRACE("DataStream::_RemoveFromTripleIndirectBlock(): current size: %lu, "
TRACE("DataStream::_RemoveFromTripleIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks);
uint32* tripleIndirect = &fStream->triple_indirect;
uint32 start = numBlocks <= kMaxDoubleIndirect ? 0
off_t start = numBlocks <= kMaxDoubleIndirect ? 0
: numBlocks - kMaxDoubleIndirect;
uint32 end = fNumBlocks - kMaxDoubleIndirect;
off_t end = fNumBlocks - kMaxDoubleIndirect;
bool freeAll = start == 0;
@@ -22,20 +22,20 @@ public:
off_t size);
~DataStream();
status_t Enlarge(Transaction& transaction, uint32& numBlocks);
status_t Shrink(Transaction& transaction, uint32& numBlocks);
status_t Enlarge(Transaction& transaction, off_t& numBlocks);
status_t Shrink(Transaction& transaction, off_t& numBlocks);
private:
uint32 _BlocksNeeded(uint32 end);
uint32 _BlocksNeeded(off_t end);
status_t _GetBlock(Transaction& transaction, uint32& block);
status_t _PrepareBlock(Transaction& transaction, uint32* pos,
uint32& blockNum, bool& clear);
status_t _AddBlocks(Transaction& transaction, uint32* block,
uint32 count);
off_t count);
status_t _AddBlocks(Transaction& transaction, uint32* block,
uint32 start, uint32 end, int recursion);
off_t start, off_t end, int recursion);
status_t _AddForDirectBlocks(Transaction& transaction,
uint32 numBlocks);
@@ -53,7 +53,7 @@ private:
status_t _FreeBlocks(Transaction& transaction, uint32* block,
uint32 count);
status_t _FreeBlocks(Transaction& transaction, uint32* block,
uint32 start, uint32 end, bool freeParent,
off_t start, off_t end, bool freeParent,
int recursion);
status_t _RemoveFromDirectBlocks(Transaction& transaction,
@@ -80,13 +80,13 @@ private:
uint32 fFirstBlock;
uint32 fAllocated;
uint32 fAllocatedPos;
off_t fAllocatedPos;
uint32 fWaiting;
uint32 fFreeStart;
uint32 fFreeCount;
uint32 fNumBlocks;
off_t fNumBlocks;
uint32 fRemovedBlocks;
};
+37 -40
View File
@@ -17,12 +17,16 @@
#include "Utility.h"
#undef ASSERT
//#define TRACE_EXT2
#ifdef TRACE_EXT2
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
# define ASSERT(x) { if (!(x)) kernel_debugger("ext2: assert failed: " #x "\n"); }
#else
# define TRACE(x...) ;
# define ASSERT(x) ;
#endif
#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
Inode::Inode(Volume* volume, ino_t id)
@@ -32,8 +36,7 @@ Inode::Inode(Volume* volume, ino_t id)
fCache(NULL),
fMap(NULL),
fCached(false),
fHasExtraAttributes(false),
fAttributesBlock(NULL)
fHasExtraAttributes(false)
{
rw_lock_init(&fLock, "ext2 inode");
recursive_lock_init(&fSmallDataLock, "ext2 inode small data");
@@ -68,7 +71,6 @@ Inode::Inode(Volume* volume)
fCache(NULL),
fMap(NULL),
fCached(false),
fAttributesBlock(NULL),
fInitStatus(B_NO_INIT)
{
rw_lock_init(&fLock, "ext2 inode");
@@ -91,12 +93,6 @@ Inode::~Inode()
file_map_delete(Map());
}
if (fAttributesBlock) {
TRACE("Returning the attributes block\n");
uint32 block = B_LENDIAN_TO_HOST_INT32(Node().file_access_control);
block_cache_put(fVolume->BlockCache(), block);
}
TRACE("Inode destructor: Done\n");
}
@@ -123,9 +119,9 @@ Inode::WriteLockInTransaction(Transaction& transaction)
status_t
Inode::WriteBack(Transaction& transaction)
{
uint32 inodeBlock;
off_t blockNum;
status_t status = fVolume->GetInodeBlock(fID, inodeBlock);
status_t status = fVolume->GetInodeBlock(fID, blockNum);
if (status != B_OK)
return status;
@@ -136,19 +132,19 @@ Inode::WriteBack(Transaction& transaction)
}
CachedBlock cached(fVolume);
uint8* inodeBlockData = cached.SetToWritable(transaction, inodeBlock);
uint8* inodeBlockData = cached.SetToWritable(transaction, blockNum);
if (inodeBlockData == NULL)
return B_IO_ERROR;
TRACE("Inode::WriteBack(): Inode ID: %d, inode block: %lu, data: %p, "
TRACE("Inode::WriteBack(): Inode ID: %lld, inode block: %llu, data: %p, "
"index: %lu, inode size: %lu, node size: %lu, this: %p, node: %p\n",
(int)fID, inodeBlock, inodeBlockData, fVolume->InodeBlockIndex(fID),
fID, blockNum, inodeBlockData, fVolume->InodeBlockIndex(fID),
fVolume->InodeSize(), fNodeSize, this, &fNode);
memcpy(inodeBlockData +
fVolume->InodeBlockIndex(fID) * fVolume->InodeSize(),
(uint8*)&fNode, fNodeSize);
TRACE("Inode::WriteBack() finished\n");
TRACE("Inode::WriteBack() finished %ld\n", Node().stream.direct[0]);
return B_OK;
}
@@ -157,16 +153,16 @@ Inode::WriteBack(Transaction& transaction)
status_t
Inode::UpdateNodeFromDisk()
{
uint32 block;
off_t blockNum;
status_t status = fVolume->GetInodeBlock(fID, block);
status_t status = fVolume->GetInodeBlock(fID, blockNum);
if (status != B_OK)
return status;
TRACE("inode %Ld at block %lu\n", fID, block);
TRACE("inode %lld at block %llu\n", fID, blockNum);
CachedBlock cached(fVolume);
const uint8* inodeBlock = cached.SetTo(block);
const uint8* inodeBlock = cached.SetTo(blockNum);
if (inodeBlock == NULL)
return B_IO_ERROR;
@@ -238,6 +234,7 @@ Inode::FindBlock(off_t offset, uint32& block)
if (index < EXT2_DIRECT_BLOCKS) {
// direct blocks
block = B_LENDIAN_TO_HOST_INT32(Node().stream.direct[index]);
ASSERT(block != 0);
} else if ((index -= EXT2_DIRECT_BLOCKS) < perBlock) {
// indirect blocks
CachedBlock cached(fVolume);
@@ -247,6 +244,7 @@ Inode::FindBlock(off_t offset, uint32& block)
return B_IO_ERROR;
block = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index]);
ASSERT(block != 0);
} else if ((index -= perBlock) < perIndirectBlock) {
// double indirect blocks
CachedBlock cached(fVolume);
@@ -268,6 +266,7 @@ Inode::FindBlock(off_t offset, uint32& block)
block = B_LENDIAN_TO_HOST_INT32(
indirectBlocks[index & (perBlock - 1)]);
}
ASSERT(block != 0);
} else if ((index -= perIndirectBlock) / perBlock < perIndirectBlock) {
// triple indirect blocks
CachedBlock cached(fVolume);
@@ -300,13 +299,14 @@ Inode::FindBlock(off_t offset, uint32& block)
indirectBlocks[index & (perBlock - 1)]);
}
}
ASSERT(block != 0);
} else {
// Outside of the possible data stream
dprintf("ext2: block outside datastream!\n");
return B_ERROR;
}
TRACE("inode %Ld: FindBlock(offset %Ld): %lu\n", ID(), offset, block);
TRACE("inode %Ld: FindBlock(offset %lld): %lu\n", ID(), offset, block);
return B_OK;
}
@@ -318,13 +318,13 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length)
// set/check boundaries for pos/length
if (pos < 0) {
TRACE("inode %Ld: ReadAt failed(pos %Ld, length %lu)\n", ID(), pos,
ERROR("inode %lld: ReadAt failed(pos %lld, length %lu)\n", ID(), pos,
length);
return B_BAD_VALUE;
}
if (pos >= Size() || length == 0) {
TRACE("inode %Ld: ReadAt 0 (pos %Ld, length %lu)\n", ID(), pos, length);
TRACE("inode %lld: ReadAt 0 (pos %lld, length %lu)\n", ID(), pos, length);
*_length = 0;
return B_NO_ERROR;
}
@@ -337,8 +337,8 @@ status_t
Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
size_t* _length)
{
TRACE("Inode::WriteAt(%lld, %p, *(%p) = %ld)\n", (long long)pos, buffer,
_length, (long)*_length);
TRACE("Inode::WriteAt(%lld, %p, *(%p) = %ld)\n", pos, buffer,
_length, *_length);
ReadLocker readLocker(fLock);
if (IsFileCacheDisabled())
@@ -398,8 +398,8 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
return B_OK;
}
TRACE("Inode::WriteAt(): Performing write: %p, %d, %p, %d\n",
FileCache(), (int)pos, buffer, (int)*_length);
TRACE("Inode::WriteAt(): Performing write: %p, %ld, %p, %ld\n",
FileCache(), pos, buffer, *_length);
status_t status = file_cache_write(FileCache(), NULL, pos, buffer, _length);
WriteLockInTransaction(transaction);
@@ -413,7 +413,7 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
status_t
Inode::FillGapWithZeros(off_t start, off_t end)
{
TRACE("Inode::FileGapWithZeros(%ld - %ld)\n", (long)start, (long)end);
TRACE("Inode::FileGapWithZeros(%lld - %lld)\n", start, end);
while (start < end) {
size_t size;
@@ -424,8 +424,7 @@ Inode::FillGapWithZeros(off_t start, off_t end)
size = end - start;
TRACE("Inode::FillGapWithZeros(): Calling file_cache_write(%p, NULL, "
"%ld, NULL, &(%ld) = %p)\n", fCache, (long)start, (long)size,
&size);
"%lld, NULL, &(%lld) = %p)\n", fCache, start, size, &size);
status_t status = file_cache_write(fCache, NULL, start, NULL,
&size);
if (status != B_OK)
@@ -441,7 +440,7 @@ Inode::FillGapWithZeros(off_t start, off_t end)
status_t
Inode::Resize(Transaction& transaction, off_t size)
{
TRACE("Inode::Resize(): size: %ld\n", (long)size);
TRACE("Inode::Resize() ID:%lld size: %lld\n", ID(), size);
if (size < 0)
return B_BAD_VALUE;
@@ -450,8 +449,7 @@ Inode::Resize(Transaction& transaction, off_t size)
if (size == oldSize)
return B_OK;
TRACE("Inode::Resize(): old size: %ld, new size: %ld\n", (long)oldSize,
(long)size);
TRACE("Inode::Resize(): old size: %lld, new size: %lld\n", oldSize, size);
status_t status;
if (size > oldSize) {
@@ -471,8 +469,7 @@ Inode::Resize(Transaction& transaction, off_t size)
file_cache_set_size(FileCache(), size);
file_map_set_size(Map(), size);
TRACE("Inode::Resize(): Writing back inode changes. Size: %ld\n",
(long)Size());
TRACE("Inode::Resize(): Writing back inode changes. Size: %lld\n", Size());
return WriteBack(transaction);
}
@@ -779,8 +776,8 @@ Inode::EnableFileCache()
return B_OK;
}
TRACE("Inode::EnableFileCache(): Creating the file cache: %d, %d, %d\n",
(int)fVolume->ID(), (int)ID(), (int)Size());
TRACE("Inode::EnableFileCache(): Creating file cache: %ld, %ld, %lld\n",
fVolume->ID(), ID(), Size());
fCache = file_cache_create(fVolume->ID(), ID(), Size());
fMap = file_map_create(fVolume->ID(), ID(), Size());
@@ -876,13 +873,13 @@ Inode::_EnlargeDataStream(Transaction& transaction, off_t size)
return B_OK;
}
uint32 end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1;
off_t end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1;
DataStream stream(fVolume, &fNode.stream, oldSize);
stream.Enlarge(transaction, end);
TRACE("Inode::_EnlargeDataStream(): Setting size to %Ld\n", size);
TRACE("Inode::_EnlargeDataStream(): Setting size to %lld\n", size);
fNode.SetSize(size);
TRACE("Inode::_EnlargeDataStream(): Setting allocated block count to %lu\n",
TRACE("Inode::_EnlargeDataStream(): Setting allocated block count to %llu\n",
end);
return _SetNumBlocks(_NumBlocks() + end * (fVolume->BlockSize() / 512));
}
@@ -910,7 +907,7 @@ Inode::_ShrinkDataStream(Transaction& transaction, off_t size)
return B_OK;
}
uint32 end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1;
off_t end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1;
DataStream stream(fVolume, &fNode.stream, oldSize);
stream.Shrink(transaction, end);
@@ -145,7 +145,6 @@ private:
uint32 fNodeSize;
// Inodes have a variable size, but the important
// information is always the same size (except in ext4)
ext2_xattr_header* fAttributesBlock;
status_t fInitStatus;
mutable recursive_lock fSmallDataLock;
@@ -68,15 +68,19 @@ InodeAllocator::Free(Transaction& transaction, ino_t id, bool isDirectory)
numInodes = fVolume->NumInodes() - blockGroup * numInodes;
TRACE("InodeAllocator::Free(): Updating block group data\n");
group->SetFreeInodes(group->FreeInodes() + 1);
group->SetFreeInodes(group->FreeInodes(fVolume->Has64bitFeature()) + 1,
fVolume->Has64bitFeature());
if (isDirectory)
group->SetUsedDirectories(group->UsedDirectories() - 1);
group->SetUsedDirectories(
group->UsedDirectories(fVolume->Has64bitFeature()) - 1,
fVolume->Has64bitFeature());
status = fVolume->WriteBlockGroup(transaction, blockGroup);
if (status != B_OK)
return status;
return _UnmarkInBitmap(transaction, group->InodeBitmap(), numInodes, id);
return _UnmarkInBitmap(transaction,
group->InodeBitmap(fVolume->Has64bitFeature()), numInodes, id);
}
@@ -97,17 +101,20 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup,
if (status != B_OK)
return status;
uint32 freeInodes = group->FreeInodes();
uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature());
if (freeInodes != 0) {
group->SetFreeInodes(freeInodes - 1);
group->SetFreeInodes(freeInodes - 1, fVolume->Has64bitFeature());
if (isDirectory)
group->SetUsedDirectories(group->UsedDirectories() + 1);
group->SetUsedDirectories(group->UsedDirectories(
fVolume->Has64bitFeature()) + 1,
fVolume->Has64bitFeature());
status = fVolume->WriteBlockGroup(transaction, blockGroup);
if (status != B_OK)
return status;
return _MarkInBitmap(transaction, group->InodeBitmap(),
return _MarkInBitmap(transaction,
group->InodeBitmap(fVolume->Has64bitFeature()),
blockGroup, fVolume->InodesPerGroup(), id);
}
}
@@ -119,11 +126,13 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup,
if (status != B_OK)
return status;
uint32 freeInodes = group->FreeInodes();
if (group->FreeInodes() != 0) {
group->SetFreeInodes(freeInodes - 1);
uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature());
if (freeInodes != 0) {
group->SetFreeInodes(freeInodes - 1,
fVolume->Has64bitFeature());
return _MarkInBitmap(transaction, group->InodeBitmap(),
return _MarkInBitmap(transaction,
group->InodeBitmap(fVolume->Has64bitFeature()),
blockGroup, fVolume->NumInodes()
- blockGroup * fVolume->InodesPerGroup(), id);
}
+26 -22
View File
@@ -231,9 +231,8 @@ Volume::~Volume()
if (fGroupBlocks != NULL) {
uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1)
/ fGroupsPerBlock;
for (uint32 i = 0; i < blockCount; i++) {
for (uint32 i = 0; i < blockCount; i++)
free(fGroupBlocks[i]);
}
free(fGroupBlocks);
}
@@ -303,16 +302,22 @@ Volume::Mount(const char* deviceName, uint32 flags)
fBlockSize = 1UL << fSuperBlock.BlockShift();
fFirstDataBlock = fSuperBlock.FirstDataBlock();
fFreeBlocks = fSuperBlock.FreeBlocks();
fFreeBlocks = fSuperBlock.FreeBlocks(Has64bitFeature());
fFreeInodes = fSuperBlock.FreeInodes();
uint32 numBlocks = fSuperBlock.NumBlocks() - fFirstDataBlock;
off_t numBlocks = fSuperBlock.NumBlocks(Has64bitFeature()) - fFirstDataBlock;
uint32 blocksPerGroup = fSuperBlock.BlocksPerGroup();
fNumGroups = numBlocks / blocksPerGroup;
if (numBlocks % blocksPerGroup != 0)
fNumGroups++;
fGroupsPerBlock = fBlockSize / sizeof(ext2_block_group);
if (Has64bitFeature()) {
fGroupDescriptorSize = fSuperBlock.GroupDescriptorSize();
if (fGroupDescriptorSize < sizeof(ext2_block_group))
return B_ERROR;
} else
fGroupDescriptorSize = EXT2_BLOCK_GROUP_NORMAL_SIZE;
fGroupsPerBlock = fBlockSize / fGroupDescriptorSize;
fNumInodes = fSuperBlock.NumInodes();
TRACE("block size %ld, num groups %ld, groups per block %ld, first %lu\n",
@@ -320,11 +325,11 @@ Volume::Mount(const char* deviceName, uint32 flags)
uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1) / fGroupsPerBlock;
fGroupBlocks = (ext2_block_group**)malloc(blockCount * sizeof(void*));
fGroupBlocks = (uint8**)malloc(blockCount * sizeof(uint8*));
if (fGroupBlocks == NULL)
return B_NO_MEMORY;
memset(fGroupBlocks, 0, blockCount * sizeof(void*));
memset(fGroupBlocks, 0, blockCount * sizeof(uint8*));
fInodesPerBlock = fBlockSize / InodeSize();
// check if the device size is large enough to hold the file system
@@ -452,7 +457,7 @@ Volume::Unmount()
status_t
Volume::GetInodeBlock(ino_t id, uint32& block)
Volume::GetInodeBlock(ino_t id, off_t& block)
{
ext2_block_group* group;
status_t status = GetBlockGroup((id - 1) / fSuperBlock.InodesPerGroup(),
@@ -460,7 +465,7 @@ Volume::GetInodeBlock(ino_t id, uint32& block)
if (status != B_OK)
return status;
block = group->InodeTable()
block = group->InodeTable(Has64bitFeature())
+ ((id - 1) % fSuperBlock.InodesPerGroup()) / fInodesPerBlock;
return B_OK;
}
@@ -544,19 +549,18 @@ Volume::GetBlockGroup(int32 index, ext2_block_group** _group)
if (block == NULL)
return B_IO_ERROR;
ext2_block_group* groupBlock = (ext2_block_group*)malloc(fBlockSize);
if (groupBlock == NULL)
fGroupBlocks[blockIndex] = (uint8*)malloc(fBlockSize);
if (fGroupBlocks[blockIndex] == NULL)
return B_NO_MEMORY;
memcpy((uint8*)groupBlock, block, fBlockSize);
fGroupBlocks[blockIndex] = groupBlock;
memcpy(fGroupBlocks[blockIndex], block, fBlockSize);
TRACE("group [%ld]: inode table %ld\n", index,
(fGroupBlocks[blockIndex] + index % fGroupsPerBlock)->InodeTable());
}
*_group = fGroupBlocks[blockIndex] + index % fGroupsPerBlock;
*_group = (ext2_block_group*)(fGroupBlocks[blockIndex]
+ (index % fGroupsPerBlock) * fGroupDescriptorSize);
return B_OK;
}
@@ -625,7 +629,7 @@ Volume::RemoveOrphan(Transaction& transaction, ino_t id)
CachedBlock cached(this);
uint32 blockNum;
off_t blockNum;
status_t status = GetInodeBlock(currentID, blockNum);
if (status != B_OK)
return status;
@@ -650,7 +654,7 @@ Volume::RemoveOrphan(Transaction& transaction, ino_t id)
return B_OK;
do {
uint32 lastBlockNum = blockNum;
off_t lastBlockNum = blockNum;
status = GetInodeBlock(currentID, blockNum);
if (status != B_OK)
return status;
@@ -720,7 +724,7 @@ Volume::FreeInode(Transaction& transaction, ino_t id, bool isDirectory)
status_t
Volume::AllocateBlocks(Transaction& transaction, uint32 minimum, uint32 maximum,
uint32& blockGroup, uint32& start, uint32& length)
uint32& blockGroup, off_t& start, uint32& length)
{
TRACE("Volume::AllocateBlocks()\n");
if (IsReadOnly())
@@ -742,9 +746,9 @@ Volume::AllocateBlocks(Transaction& transaction, uint32 minimum, uint32 maximum,
status_t
Volume::FreeBlocks(Transaction& transaction, uint32 start, uint32 length)
Volume::FreeBlocks(Transaction& transaction, off_t start, uint32 length)
{
TRACE("Volume::FreeBlocks(%lu, %lu)\n", start, length);
TRACE("Volume::FreeBlocks(%llu, %lu)\n", start, length);
if (IsReadOnly())
return B_READ_ONLY_DEVICE;
@@ -776,7 +780,7 @@ Volume::LoadSuperBlock()
else
memcpy(&fSuperBlock, block, sizeof(fSuperBlock));
fFreeBlocks = fSuperBlock.FreeBlocks();
fFreeBlocks = fSuperBlock.FreeBlocks(Has64bitFeature());
fFreeInodes = fSuperBlock.FreeInodes();
return B_OK;
@@ -787,7 +791,7 @@ status_t
Volume::WriteSuperBlock(Transaction& transaction)
{
TRACE("Volume::WriteSuperBlock()\n");
fSuperBlock.SetFreeBlocks(fFreeBlocks);
fSuperBlock.SetFreeBlocks(fFreeBlocks, Has64bitFeature());
fSuperBlock.SetFreeInodes(fFreeInodes);
// TODO: Rest of fields that can be modified
+13 -6
View File
@@ -49,7 +49,8 @@ public:
uint32 NumGroups() const
{ return fNumGroups; }
off_t NumBlocks() const
{ return fSuperBlock.NumBlocks(); }
{ return fSuperBlock.NumBlocks(
Has64bitFeature()); }
off_t NumFreeBlocks() const
{ return fFreeBlocks; }
uint32 FirstDataBlock() const
@@ -65,7 +66,7 @@ public:
{ return fSuperBlock.InodesPerGroup(); }
ext2_super_block& SuperBlock() { return fSuperBlock; }
status_t GetInodeBlock(ino_t id, uint32& block);
status_t GetInodeBlock(ino_t id, off_t& block);
uint32 InodeBlockIndex(ino_t id) const;
status_t GetBlockGroup(int32 index,
ext2_block_group** _group);
@@ -77,6 +78,9 @@ public:
bool IndexedDirectories() const
{ return (fSuperBlock.CompatibleFeatures()
& EXT2_FEATURE_DIRECTORY_INDEX) != 0; }
bool Has64bitFeature() const
{ return (fSuperBlock.CompatibleFeatures()
& EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; }
uint8 DefaultHashVersion() const
{ return fSuperBlock.default_hash_version; }
bool HugeFiles() const
@@ -96,10 +100,10 @@ public:
status_t AllocateBlocks(Transaction& transaction,
uint32 minimum, uint32 maximum,
uint32& blockGroup, uint32& start,
uint32& blockGroup, off_t& start,
uint32& length);
status_t FreeBlocks(Transaction& transaction,
uint32 start, uint32 length);
off_t start, uint32 length);
status_t LoadSuperBlock();
status_t WriteSuperBlock(Transaction& transaction);
@@ -122,6 +126,8 @@ private:
static uint32 _UnsupportedReadOnlyFeatures(
ext2_super_block& superBlock);
uint32 _GroupDescriptorBlock(uint32 blockIndex);
uint16 _GroupDescriptorSize()
{ return fGroupDescriptorSize; }
private:
mutex fLock;
@@ -142,11 +148,12 @@ private:
uint32 fNumInodes;
uint32 fNumGroups;
uint32 fFreeBlocks;
off_t fFreeBlocks;
uint32 fFreeInodes;
uint32 fGroupsPerBlock;
ext2_block_group** fGroupBlocks;
uint8** fGroupBlocks;
uint32 fInodesPerBlock;
uint16 fGroupDescriptorSize;
void* fBlockCache;
Inode* fRootNode;
+106 -27
View File
@@ -72,9 +72,9 @@ struct ext2_super_block {
uint32 journal_inode_backup[17];
// ext4 support
uint32 num_blocks_hi;
uint32 reserved_blocks_hi;
uint32 free_blocks_hi;
uint32 num_blocks_high;
uint32 reserved_blocks_high;
uint32 free_blocks_high;
uint16 min_inode_size;
uint16 want_inode_size;
uint32 flags;
@@ -92,9 +92,21 @@ struct ext2_super_block {
uint32 RevisionLevel() const { return B_LENDIAN_TO_HOST_INT16(revision_level); }
uint32 BlockShift() const { return B_LENDIAN_TO_HOST_INT32(block_shift) + 10; }
uint32 NumInodes() const { return B_LENDIAN_TO_HOST_INT32(num_inodes); }
uint32 NumBlocks() const { return B_LENDIAN_TO_HOST_INT32(num_blocks); }
uint64 NumBlocks(bool has64bits) const
{
uint64 blocks = B_LENDIAN_TO_HOST_INT32(num_blocks);
if (has64bits)
blocks |= ((uint64)B_LENDIAN_TO_HOST_INT32(num_blocks_high) << 32);
return blocks;
}
uint32 FreeInodes() const { return B_LENDIAN_TO_HOST_INT32(free_inodes); }
uint32 FreeBlocks() const { return B_LENDIAN_TO_HOST_INT32(free_blocks); }
uint64 FreeBlocks(bool has64bits) const
{
uint64 blocks = B_LENDIAN_TO_HOST_INT32(free_blocks);
if (has64bits)
blocks |= ((uint64)B_LENDIAN_TO_HOST_INT32(free_blocks_high) << 32);
return blocks;
}
uint16 InodeSize() const { return B_LENDIAN_TO_HOST_INT16(inode_size); }
uint32 FirstDataBlock() const
{ return B_LENDIAN_TO_HOST_INT32(first_data_block); }
@@ -121,8 +133,12 @@ struct ext2_super_block {
void SetFreeInodes(uint32 freeInodes)
{ free_inodes = B_HOST_TO_LENDIAN_INT32(freeInodes); }
void SetFreeBlocks(uint32 freeBlocks)
{ free_blocks = B_HOST_TO_LENDIAN_INT32(freeBlocks); }
void SetFreeBlocks(uint64 freeBlocks, bool has64bits)
{
free_blocks = B_HOST_TO_LENDIAN_INT32(freeBlocks & 0xffffffff);
if (has64bits)
free_blocks_high = B_HOST_TO_LENDIAN_INT32(freeBlocks >> 32);
}
void SetLastOrphan(ino_t id)
{ last_orphan = B_HOST_TO_LENDIAN_INT32((uint32)id); }
void SetReadOnlyFeatures(uint32 readOnlyFeatures) const
@@ -173,6 +189,8 @@ struct ext2_super_block {
#define EXT2_STATE_VALID 0x01
#define EXT2_STATE_INVALID 0x02
#define EXT2_BLOCK_GROUP_NORMAL_SIZE 32
struct ext2_block_group {
uint32 block_bitmap;
uint32 inode_bitmap;
@@ -180,30 +198,91 @@ struct ext2_block_group {
uint16 free_blocks;
uint16 free_inodes;
uint16 used_directories;
uint16 _padding;
uint32 _reserved[3];
uint16 flags;
uint32 _reserved[2];
uint16 unused_inodes;
uint16 checksum;
// ext4
uint32 block_bitmap_high;
uint32 inode_bitmap_high;
uint32 inode_table_high;
uint16 free_blocks_high;
uint16 free_inodes_high;
uint16 used_directories_high;
uint16 unused_inodes_high;
uint32 _reserved2[3];
uint32 BlockBitmap() const
{ return B_LENDIAN_TO_HOST_INT32(block_bitmap); }
uint32 InodeBitmap() const
{ return B_LENDIAN_TO_HOST_INT32(inode_bitmap); }
uint32 InodeTable() const
{ return B_LENDIAN_TO_HOST_INT32(inode_table); }
uint16 FreeBlocks() const
{ return B_LENDIAN_TO_HOST_INT16(free_blocks); }
uint16 FreeInodes() const
{ return B_LENDIAN_TO_HOST_INT16(free_inodes); }
uint16 UsedDirectories() const
{ return B_LENDIAN_TO_HOST_INT16(used_directories); }
uint64 BlockBitmap(bool has64bits) const
{
uint64 block = B_LENDIAN_TO_HOST_INT32(block_bitmap);
if (has64bits)
block |=
((uint64)B_LENDIAN_TO_HOST_INT32(block_bitmap_high) << 32);
return block;
}
uint64 InodeBitmap(bool has64bits) const
{
uint64 bitmap = B_LENDIAN_TO_HOST_INT32(inode_bitmap);
if (has64bits)
bitmap |=
((uint64)B_LENDIAN_TO_HOST_INT32(inode_bitmap_high) << 32);
return bitmap;
}
uint64 InodeTable(bool has64bits) const
{
uint64 table = B_LENDIAN_TO_HOST_INT32(inode_table);
if (has64bits)
table |= ((uint64)B_LENDIAN_TO_HOST_INT32(inode_table_high) << 32);
return table;
}
uint32 FreeBlocks(bool has64bits) const
{
uint32 blocks = B_LENDIAN_TO_HOST_INT16(free_blocks);
if (has64bits)
blocks |=
((uint32)B_LENDIAN_TO_HOST_INT16(free_blocks_high) << 16);
return blocks;
}
uint32 FreeInodes(bool has64bits) const
{
uint32 inodes = B_LENDIAN_TO_HOST_INT16(free_inodes);
if (has64bits)
inodes |=
((uint32)B_LENDIAN_TO_HOST_INT16(free_inodes_high) << 16);
return inodes;
}
uint32 UsedDirectories(bool has64bits) const
{
uint32 dirs = B_LENDIAN_TO_HOST_INT16(used_directories);
if (has64bits)
dirs |=
((uint32)B_LENDIAN_TO_HOST_INT16(used_directories_high) << 16);
return dirs;
}
void SetFreeBlocks(uint16 freeBlocks)
{ free_blocks = B_HOST_TO_LENDIAN_INT16(freeBlocks); }
void SetFreeInodes(uint16 freeInodes)
{ free_inodes = B_HOST_TO_LENDIAN_INT16(freeInodes); }
void SetFreeBlocks(uint32 freeBlocks, bool has64bits)
{
free_blocks = B_HOST_TO_LENDIAN_INT16(freeBlocks) & 0xffff;
if (has64bits)
free_blocks_high = B_HOST_TO_LENDIAN_INT16(freeBlocks >> 16);
}
void SetUsedDirectories(uint16 usedDirectories)
{ used_directories = B_HOST_TO_LENDIAN_INT16(usedDirectories); }
void SetFreeInodes(uint32 freeInodes, bool has64bits)
{
free_inodes = B_HOST_TO_LENDIAN_INT16(freeInodes) & 0xffff;
if (has64bits)
free_inodes_high = B_HOST_TO_LENDIAN_INT16(freeInodes >> 16);
}
void SetUsedDirectories(uint16 usedDirectories, bool has64bits)
{
used_directories = B_HOST_TO_LENDIAN_INT16(usedDirectories& 0xffff);
if (has64bits)
used_directories_high =
B_HOST_TO_LENDIAN_INT16(usedDirectories >> 16);
}
} _PACKED;
#define EXT2_DIRECT_BLOCKS 12
@@ -91,8 +91,10 @@ ext2_scan_partition(int fd, partition_data *partition, void *_cookie)
partition->status = B_PARTITION_VALID;
partition->flags |= B_PARTITION_FILE_SYSTEM;
partition->content_size = cookie->super_block.NumBlocks()
<< cookie->super_block.BlockShift();
partition->content_size = cookie->super_block.NumBlocks(
(cookie->super_block.CompatibleFeatures()
& EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0)
<< cookie->super_block.BlockShift();
partition->block_size = 1UL << cookie->super_block.BlockShift();
partition->content_name = strdup(cookie->super_block.name);
if (partition->content_name == NULL)
@@ -491,19 +493,19 @@ ext2_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd,
uint32 blocksPerGroup = volume->BlocksPerGroup();
uint32 blockSize = volume->BlockSize();
uint32 firstBlock = volume->FirstDataBlock();
uint32 start = 0;
off_t start = 0;
uint32 group = 0;
uint32 length;
TRACE("ioctl: blocks per group: %lu, block size: %lu, "
"first block: %lu, start: %lu, group: %lu\n", blocksPerGroup,
"first block: %lu, start: %llu, group: %lu\n", blocksPerGroup,
blockSize, firstBlock, start, group);
while (volume->AllocateBlocks(transaction, 1, 2048, group, start,
length) == B_OK) {
TRACE("ioctl: Allocated blocks in group %lu: %lu-%lu\n", group,
TRACE("ioctl: Allocated blocks in group %lu: %llu-%llu\n", group,
start, start + length);
uint32 blockNum = start + group * blocksPerGroup - firstBlock;
off_t blockNum = start + group * blocksPerGroup - firstBlock;
for (uint32 i = 0; i < length; ++i) {
uint8* block = cached.SetToWritable(transaction, blockNum);