* Fixed bug in the BlockAllocator::Allocate() function which did not
compute the bit offsets correctly if the last block of the whole bitmap was only a partial block. * Added new bfs_allocator KDL command. * Renamed the KDL command bfsinode to bfs_inode. * Added "--help" argument to bfs_inode and bfs KDL commands. * Added more tracing in the block allocator. * Turned on the ASSERT() macro in non-debug builds. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23534 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
36a3ef573d
commit
09c46ea8bd
@ -95,10 +95,12 @@ checksum(const uint8 *data, size_t size)
|
||||
class Block : public AbstractTraceEntry {
|
||||
public:
|
||||
Block(const char *label, off_t blockNumber, const uint8 *data,
|
||||
size_t size)
|
||||
size_t size, uint32 start = 0, uint32 length = 0)
|
||||
:
|
||||
fBlock(blockNumber),
|
||||
fData(data)
|
||||
fData(data),
|
||||
fStart(start),
|
||||
fLength(length)
|
||||
{
|
||||
strlcpy(fLabel, label, sizeof(fLabel));
|
||||
fSum = checksum(data, size);
|
||||
@ -109,7 +111,8 @@ class Block : public AbstractTraceEntry {
|
||||
virtual void AddDump(char *buffer, size_t size)
|
||||
{
|
||||
uint32 length = snprintf(buffer, size, "%s: block %Ld (%p), sum %lu,"
|
||||
" bytes ", fLabel, fBlock, fData, fSum);
|
||||
" s/l %lu/%lu, bytes ", fLabel, fBlock, fData, fSum, fStart,
|
||||
fLength);
|
||||
for (uint32 i = 0; length < size - 1 && i < sizeof(fBytes); i++) {
|
||||
length += snprintf(buffer + length, size - length, "%02x",
|
||||
fBytes[i]);
|
||||
@ -119,6 +122,8 @@ class Block : public AbstractTraceEntry {
|
||||
private:
|
||||
off_t fBlock;
|
||||
const uint8 *fData;
|
||||
uint32 fStart;
|
||||
uint32 fLength;
|
||||
uint32 fSum;
|
||||
char fLabel[12];
|
||||
uint8 fBytes[32];
|
||||
@ -215,7 +220,8 @@ AllocationBlock::SetTo(AllocationGroup &group, uint16 block)
|
||||
|
||||
|
||||
status_t
|
||||
AllocationBlock::SetToWritable(Transaction &transaction, AllocationGroup &group, uint16 block)
|
||||
AllocationBlock::SetToWritable(Transaction &transaction, AllocationGroup &group,
|
||||
uint16 block)
|
||||
{
|
||||
// 8 blocks per byte
|
||||
fNumBits = fVolume->BlockSize() << 3;
|
||||
@ -226,8 +232,8 @@ AllocationBlock::SetToWritable(Transaction &transaction, AllocationGroup &group,
|
||||
#ifdef DEBUG
|
||||
fWritable = true;
|
||||
#endif
|
||||
return CachedBlock::SetToWritable(transaction, group.Start() + block) != NULL
|
||||
? B_OK : B_ERROR;
|
||||
return CachedBlock::SetToWritable(transaction, group.Start() + block)
|
||||
!= NULL ? B_OK : B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@ -256,13 +262,15 @@ AllocationBlock::Allocate(uint16 start, uint16 numBlocks)
|
||||
DIE(("Allocation::Allocate(): tried to allocate too many blocks"));
|
||||
}
|
||||
|
||||
T(Block("b-alloc-in", fBlockNumber, fBlock, fVolume->BlockSize(),
|
||||
start, numBlocks));
|
||||
|
||||
int32 block = start >> 5;
|
||||
|
||||
while (numBlocks > 0) {
|
||||
uint32 mask = 0;
|
||||
for (int32 i = start % 32; i < 32 && numBlocks; i++, numBlocks--)
|
||||
mask |= 1UL << (i % 32);
|
||||
|
||||
mask |= 1UL << i;
|
||||
#ifdef DEBUG
|
||||
// check for already set blocks
|
||||
if (HOST_ENDIAN_TO_BFS_INT32(mask) & ((uint32 *)fBlock)[block]) {
|
||||
@ -273,6 +281,8 @@ AllocationBlock::Allocate(uint16 start, uint16 numBlocks)
|
||||
Block(block++) |= HOST_ENDIAN_TO_BFS_INT32(mask);
|
||||
start = 0;
|
||||
}
|
||||
T(Block("b-alloc-out", fBlockNumber, fBlock, fVolume->BlockSize(),
|
||||
start, numBlocks));
|
||||
}
|
||||
|
||||
|
||||
@ -306,11 +316,10 @@ AllocationBlock::Free(uint16 start, uint16 numBlocks)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
/** The allocation groups are created and initialized in
|
||||
* BlockAllocator::Initialize() and BlockAllocator::InitializeAndClearBitmap()
|
||||
* respectively.
|
||||
*/
|
||||
|
||||
/*! The allocation groups are created and initialized in
|
||||
BlockAllocator::Initialize() and BlockAllocator::InitializeAndClearBitmap()
|
||||
respectively.
|
||||
*/
|
||||
AllocationGroup::AllocationGroup()
|
||||
:
|
||||
fFirstFree(-1),
|
||||
@ -339,15 +348,12 @@ AllocationGroup::AddFreeRange(int32 start, int32 blocks)
|
||||
}
|
||||
|
||||
|
||||
/** Allocates the specified run in the allocation group.
|
||||
* Doesn't check if the run is valid or already allocated
|
||||
* partially, nor does it maintain the free ranges hints
|
||||
* or the volume's used blocks count.
|
||||
* It only does the low-level work of allocating some bits
|
||||
* in the block bitmap.
|
||||
* Assumes that the block bitmap lock is hold.
|
||||
*/
|
||||
|
||||
/*! Allocates the specified run in the allocation group.
|
||||
Doesn't check if the run is valid or already allocated partially, nor
|
||||
does it maintain the free ranges hints or the volume's used blocks count.
|
||||
It only does the low-level work of allocating some bits in the block bitmap.
|
||||
Assumes that the block bitmap lock is hold.
|
||||
*/
|
||||
status_t
|
||||
AllocationGroup::Allocate(Transaction &transaction, uint16 start, int32 length)
|
||||
{
|
||||
@ -389,15 +395,12 @@ AllocationGroup::Allocate(Transaction &transaction, uint16 start, int32 length)
|
||||
}
|
||||
|
||||
|
||||
/** Frees the specified run in the allocation group.
|
||||
* Doesn't check if the run is valid or was not completely
|
||||
* allocated, nor does it maintain the free ranges hints
|
||||
* or the volume's used blocks count.
|
||||
* It only does the low-level work of freeing some bits
|
||||
* in the block bitmap.
|
||||
* Assumes that the block bitmap lock is hold.
|
||||
*/
|
||||
|
||||
/*! Frees the specified run in the allocation group.
|
||||
Doesn't check if the run is valid or was not completely allocated, nor
|
||||
does it maintain the free ranges hints or the volume's used blocks count.
|
||||
It only does the low-level work of freeing some bits in the block bitmap.
|
||||
Assumes that the block bitmap lock is hold.
|
||||
*/
|
||||
status_t
|
||||
AllocationGroup::Free(Transaction &transaction, uint16 start, int32 length)
|
||||
{
|
||||
@ -642,10 +645,11 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
|
||||
AllocationBlock cached(fVolume);
|
||||
Locker lock(fLock);
|
||||
|
||||
// the first scan through all allocation groups will look for the
|
||||
// The first scan through all allocation groups will look for the
|
||||
// wanted maximum of blocks, the second scan will just look to
|
||||
// satisfy the minimal requirement
|
||||
uint16 numBlocks = maximum;
|
||||
uint32 bitsPerFullBlock = fVolume->BlockSize() << 3;
|
||||
|
||||
for (int32 i = 0; i < fNumGroups * 2; i++, group++, start = 0) {
|
||||
group = group % fNumGroups;
|
||||
@ -654,7 +658,7 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
|
||||
continue;
|
||||
|
||||
if (i >= fNumGroups) {
|
||||
// if the minimum is the same as the maximum, it's not necessary to
|
||||
// If the minimum is the same as the maximum, it's not necessary to
|
||||
// search for in the allocation groups a second time
|
||||
if (maximum == minimum)
|
||||
return B_DEVICE_FULL;
|
||||
@ -662,8 +666,8 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
|
||||
numBlocks = minimum;
|
||||
}
|
||||
|
||||
// The wanted maximum is smaller than the largest free block in the group
|
||||
// or already smaller than the minimum
|
||||
// The wanted maximum is smaller than the largest free block in the
|
||||
// group or already smaller than the minimum
|
||||
// ToDo: disabled because it's currently not maintained after the first allocation
|
||||
//if (numBlocks > fGroups[group].fLargest)
|
||||
// continue;
|
||||
@ -671,7 +675,7 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
|
||||
if (start < fGroups[group].fFirstFree)
|
||||
start = fGroups[group].fFirstFree;
|
||||
|
||||
// there may be more than one block per allocation group - and
|
||||
// There may be more than one block per allocation group - and
|
||||
// we iterate through it to find a place for the allocation.
|
||||
// (one allocation can't exceed one allocation group)
|
||||
|
||||
@ -682,15 +686,15 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
|
||||
if (cached.SetTo(fGroups[group], block) < B_OK)
|
||||
RETURN_ERROR(B_ERROR);
|
||||
|
||||
T(Block("alloc-in", block, cached.Block(), fVolume->BlockSize()));
|
||||
T(Block("alloc-in", fGroups[group].Start() + block, cached.Block(), fVolume->BlockSize(), group, rangeStart));
|
||||
|
||||
// find a block large enough to hold the allocation
|
||||
for (uint32 bit = start % cached.NumBlockBits();
|
||||
for (uint32 bit = start % bitsPerFullBlock;
|
||||
bit < cached.NumBlockBits(); bit++) {
|
||||
if (!cached.IsUsed(bit)) {
|
||||
if (range == 0) {
|
||||
// start new range
|
||||
rangeStart = block * cached.NumBlockBits() + bit;
|
||||
rangeStart = block * bitsPerFullBlock + bit;
|
||||
}
|
||||
|
||||
// have we found a range large enough to hold numBlocks?
|
||||
@ -733,7 +737,7 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
|
||||
|
||||
T(Allocate(run));
|
||||
T(Block("alloc-out", block, cached.Block(),
|
||||
fVolume->BlockSize()));
|
||||
fVolume->BlockSize(), group, rangeStart));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -746,8 +750,8 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
|
||||
|
||||
|
||||
status_t
|
||||
BlockAllocator::AllocateForInode(Transaction &transaction, const block_run *parent,
|
||||
mode_t type, block_run &run)
|
||||
BlockAllocator::AllocateForInode(Transaction &transaction,
|
||||
const block_run *parent, mode_t type, block_run &run)
|
||||
{
|
||||
// apply some allocation policies here (AllocateBlocks() will break them
|
||||
// if necessary) - we will start with those described in Dominic Giampaolo's
|
||||
@ -1407,3 +1411,48 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - debugger commands
|
||||
|
||||
|
||||
#ifdef BFS_DEBUGGER_COMMANDS
|
||||
|
||||
|
||||
void
|
||||
BlockAllocator::Dump()
|
||||
{
|
||||
kprintf("allocation groups: %ld\n", fNumGroups);
|
||||
kprintf("blocks per group: %ld\n", fBlocksPerGroup);
|
||||
|
||||
for (int32 i = 0; i < fNumGroups; i++) {
|
||||
AllocationGroup& group = fGroups[i];
|
||||
|
||||
kprintf("[%3ld] num bits: %lu\n", i, group.NumBits());
|
||||
kprintf(" num blocks: %lu\n", group.NumBlocks());
|
||||
kprintf(" start: %ld\n", group.Start());
|
||||
kprintf(" first free: %ld\n", group.fFirstFree);
|
||||
kprintf(" largest: %ld\n", group.fLargest);
|
||||
kprintf(" largest first: %ld\n", group.fLargestFirst);
|
||||
kprintf(" free bits: %ld\n", group.fFreeBits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dump_block_allocator(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2 || !strcmp(argv[1], "--help")) {
|
||||
kprintf("usage: %s <ptr-to-volume>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Volume *volume = (Volume *)parse_expression(argv[1]);
|
||||
BlockAllocator &allocator = volume->Allocator();
|
||||
|
||||
allocator.Dump();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif // BFS_DEBUGGER_COMMANDS
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* BlockAllocator - block bitmap handling and allocation policies
|
||||
*
|
||||
* Copyright 2001-2006, Axel Dörfler, axeld@pinc-software.de.
|
||||
/*
|
||||
* Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BLOCK_ALLOCATOR_H
|
||||
@ -46,6 +45,10 @@ class BlockAllocator {
|
||||
|
||||
size_t BitmapSize() const;
|
||||
|
||||
#ifdef BFS_DEBUGGER_COMMANDS
|
||||
void Dump();
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool _IsValidCheckControl(check_control *control);
|
||||
bool _CheckBitmapIsUsedAt(off_t block) const;
|
||||
@ -63,4 +66,8 @@ class BlockAllocator {
|
||||
check_cookie *fCheckCookie;
|
||||
};
|
||||
|
||||
#ifdef BFS_DEBUGGER_COMMANDS
|
||||
int dump_block_allocator(int argc, char **argv);
|
||||
#endif
|
||||
|
||||
#endif /* BLOCK_ALLOCATOR_H */
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
#include "Debug.h"
|
||||
#include "BlockAllocator.h"
|
||||
#include "BPlusTree.h"
|
||||
#include "Inode.h"
|
||||
|
||||
@ -247,7 +248,7 @@ dump_bplustree_node(const bplustree_node *node, const bplustree_header *header,
|
||||
static int
|
||||
dump_inode(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
if (argc != 2 || !strcmp(argv[1], "--help")) {
|
||||
kprintf("usage: bfsinode <ptr-to-inode>\n");
|
||||
return 0;
|
||||
}
|
||||
@ -262,7 +263,7 @@ dump_inode(int argc, char **argv)
|
||||
static int
|
||||
dump_volume(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
if (argc != 2 || !strcmp(argv[1], "--help")) {
|
||||
kprintf("usage: bfs <ptr-to-volume>\n");
|
||||
return 0;
|
||||
}
|
||||
@ -281,7 +282,8 @@ dump_volume(int argc, char **argv)
|
||||
void
|
||||
remove_debugger_commands()
|
||||
{
|
||||
remove_debugger_command("bfsinode", dump_inode);
|
||||
remove_debugger_command("bfs_inode", dump_inode);
|
||||
remove_debugger_command("bfs_allocator", dump_block_allocator);
|
||||
remove_debugger_command("bfs", dump_volume);
|
||||
}
|
||||
|
||||
@ -289,7 +291,9 @@ remove_debugger_commands()
|
||||
void
|
||||
add_debugger_commands()
|
||||
{
|
||||
add_debugger_command("bfsinode", dump_inode, "dump an Inode object");
|
||||
add_debugger_command("bfs_inode", dump_inode, "dump an Inode object");
|
||||
add_debugger_command("bfs_allocator", dump_block_allocator,
|
||||
"dump a BFS block allocator.");
|
||||
add_debugger_command("bfs", dump_volume, "dump a BFS volume");
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,8 @@
|
||||
#define FUNCTION_START(x) ;
|
||||
#define D(x) ;
|
||||
#ifndef ASSERT
|
||||
# define ASSERT(x) ;
|
||||
# define ASSERT(x) { if (!(x)) DEBUGGER(("bfs: assert failed: " #x "\n")); }
|
||||
// # define ASSERT(x) ;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user