* Improved block allocation.

* Made the block_cache KDL command dump a bit more useful info (number of
  referenced and dirty blocks).
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23540 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-01-15 18:03:33 +00:00
parent 86914dfa8e
commit 8264ebf6b7
2 changed files with 65 additions and 25 deletions

View File

@ -463,25 +463,52 @@ block_cache::FreeBlock(cached_block *block)
}
cached_block *
block_cache::_GetUnusedBlock()
{
TRACE(("block_cache: get unused block\n"));
for (block_list::Iterator iterator = unused_blocks.GetIterator();
cached_block *block = iterator.Next();) {
// this can only happen if no transactions are used
if (block->is_dirty)
write_cached_block(this, block, false);
// remove block from lists
iterator.Remove();
hash_remove(hash, block);
return block;
}
return NULL;
}
/*! Allocates a new block for \a blockNumber, ready for use */
cached_block *
block_cache::NewBlock(off_t blockNumber)
{
cached_block *block = new(nothrow) cached_block;
if (block != NULL) {
block_range *range = GetFreeRange();
if (range == NULL) {
delete block;
block = NULL;
} else
range->Allocate(this, block);
}
if (block == NULL) {
FATAL(("could not allocate block!\n"));
return NULL;
}
dprintf("block allocation failed, unused list is %sempty.\n",
unused_blocks.IsEmpty() ? "" : "not ");
block_range *range = GetFreeRange();
if (range == NULL) {
FATAL(("could not get range!\n"));
delete block;
return NULL;
// allocation failed, try to reuse an unused block
block = _GetUnusedBlock();
if (block == NULL) {
FATAL(("could not allocate block!\n"));
return NULL;
}
}
range->Allocate(this, block);
block->block_number = blockNumber;
block->ref_count = 0;
block->accessed = 0;
@ -504,9 +531,8 @@ block_cache::RemoveUnusedBlocks(int32 maxAccessed, int32 count)
{
TRACE(("block_cache: remove up to %ld unused blocks\n", count));
for (block_list::Iterator it = unused_blocks.GetIterator();
cached_block *block = it.Next();) {
for (block_list::Iterator iterator = unused_blocks.GetIterator();
cached_block *block = iterator.Next();) {
if (maxAccessed < block->accessed)
continue;
@ -518,7 +544,7 @@ block_cache::RemoveUnusedBlocks(int32 maxAccessed, int32 count)
write_cached_block(this, block, false);
// remove block from lists
it.Remove();
iterator.Remove();
hash_remove(hash, block);
FreeBlock(block);
@ -946,27 +972,37 @@ dump_cache(int argc, char **argv)
if (showBlocks) {
kprintf(" blocks:\n");
kprintf("address block no. current original parent refs access flags transact prev. trans\n");
kprintf("address block no. current original parent refs access "
"flags transact prev. trans\n");
}
uint32 referenced = 0;
uint32 count = 0;
uint32 dirty = 0;
hash_iterator iterator;
hash_open(cache->hash, &iterator);
cached_block *block;
while ((block = (cached_block *)hash_next(cache->hash, &iterator)) != NULL) {
if (showBlocks) {
kprintf("%08lx %9Ld %08lx %08lx %08lx %5ld %6ld %c%c%c%c%c %08lx %08lx\n",
(addr_t)block, block->block_number, (addr_t)block->current_data,
(addr_t)block->original_data, (addr_t)block->parent_data,
block->ref_count, block->accessed, block->busy ? 'B' : '-',
block->is_writing ? 'W' : '-', block->is_dirty ? 'B' : '-',
block->unused ? 'U' : '-', block->unmapped ? 'M' : '-',
(addr_t)block->transaction, (addr_t)block->previous_transaction);
kprintf("%08lx %9Ld %08lx %08lx %08lx %5ld %6ld %c%c%c%c%c %08lx "
"%08lx\n", (addr_t)block, block->block_number,
(addr_t)block->current_data, (addr_t)block->original_data,
(addr_t)block->parent_data, block->ref_count, block->accessed,
block->busy ? 'B' : '-', block->is_writing ? 'W' : '-',
block->is_dirty ? 'B' : '-', block->unused ? 'U' : '-',
block->unmapped ? 'M' : '-', (addr_t)block->transaction,
(addr_t)block->previous_transaction);
}
if (block->is_dirty)
dirty++;
if (block->ref_count)
referenced++;
count++;
}
kprintf(" %ld blocks.\n", count);
kprintf(" %ld blocks total, %ld dirty, %ld referenced.\n", count, dirty,
referenced);
hash_close(cache->hash, &iterator, false);
return 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef BLOCK_CACHE_PRIVATE_H
@ -125,13 +125,17 @@ struct block_cache : DoublyLinkedListLinkImpl<block_cache> {
block_range *GetFreeRange();
block_range *GetRange(void *address);
void RemoveUnusedBlocks(int32 maxAccessed = LONG_MAX, int32 count = LONG_MAX);
void RemoveUnusedBlocks(int32 maxAccessed = LONG_MAX,
int32 count = LONG_MAX);
void FreeBlock(cached_block *block);
cached_block *NewBlock(off_t blockNumber);
void Free(void *address);
void *Allocate();
static void LowMemoryHandler(void *data, int32 level);
private:
cached_block *_GetUnusedBlock();
};