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