* 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:
parent
86914dfa8e
commit
8264ebf6b7
82
src/system/kernel/cache/block_cache.cpp
vendored
82
src/system/kernel/cache/block_cache.cpp
vendored
@ -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;
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user