* 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:
+59
-23
@@ -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 */
|
/*! Allocates a new block for \a blockNumber, ready for use */
|
||||||
cached_block *
|
cached_block *
|
||||||
block_cache::NewBlock(off_t blockNumber)
|
block_cache::NewBlock(off_t blockNumber)
|
||||||
{
|
{
|
||||||
cached_block *block = new(nothrow) cached_block;
|
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) {
|
if (block == NULL) {
|
||||||
FATAL(("could not allocate block!\n"));
|
dprintf("block allocation failed, unused list is %sempty.\n",
|
||||||
return NULL;
|
unused_blocks.IsEmpty() ? "" : "not ");
|
||||||
}
|
|
||||||
|
|
||||||
block_range *range = GetFreeRange();
|
// allocation failed, try to reuse an unused block
|
||||||
if (range == NULL) {
|
block = _GetUnusedBlock();
|
||||||
FATAL(("could not get range!\n"));
|
if (block == NULL) {
|
||||||
delete block;
|
FATAL(("could not allocate block!\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
range->Allocate(this, block);
|
|
||||||
|
|
||||||
block->block_number = blockNumber;
|
block->block_number = blockNumber;
|
||||||
block->ref_count = 0;
|
block->ref_count = 0;
|
||||||
block->accessed = 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));
|
TRACE(("block_cache: remove up to %ld unused blocks\n", count));
|
||||||
|
|
||||||
for (block_list::Iterator it = unused_blocks.GetIterator();
|
for (block_list::Iterator iterator = unused_blocks.GetIterator();
|
||||||
cached_block *block = it.Next();) {
|
cached_block *block = iterator.Next();) {
|
||||||
|
|
||||||
if (maxAccessed < block->accessed)
|
if (maxAccessed < block->accessed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -518,7 +544,7 @@ block_cache::RemoveUnusedBlocks(int32 maxAccessed, int32 count)
|
|||||||
write_cached_block(this, block, false);
|
write_cached_block(this, block, false);
|
||||||
|
|
||||||
// remove block from lists
|
// remove block from lists
|
||||||
it.Remove();
|
iterator.Remove();
|
||||||
hash_remove(hash, block);
|
hash_remove(hash, block);
|
||||||
|
|
||||||
FreeBlock(block);
|
FreeBlock(block);
|
||||||
@@ -946,27 +972,37 @@ dump_cache(int argc, char **argv)
|
|||||||
|
|
||||||
if (showBlocks) {
|
if (showBlocks) {
|
||||||
kprintf(" blocks:\n");
|
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 count = 0;
|
||||||
|
uint32 dirty = 0;
|
||||||
hash_iterator iterator;
|
hash_iterator iterator;
|
||||||
hash_open(cache->hash, &iterator);
|
hash_open(cache->hash, &iterator);
|
||||||
cached_block *block;
|
cached_block *block;
|
||||||
while ((block = (cached_block *)hash_next(cache->hash, &iterator)) != NULL) {
|
while ((block = (cached_block *)hash_next(cache->hash, &iterator)) != NULL) {
|
||||||
if (showBlocks) {
|
if (showBlocks) {
|
||||||
kprintf("%08lx %9Ld %08lx %08lx %08lx %5ld %6ld %c%c%c%c%c %08lx %08lx\n",
|
kprintf("%08lx %9Ld %08lx %08lx %08lx %5ld %6ld %c%c%c%c%c %08lx "
|
||||||
(addr_t)block, block->block_number, (addr_t)block->current_data,
|
"%08lx\n", (addr_t)block, block->block_number,
|
||||||
(addr_t)block->original_data, (addr_t)block->parent_data,
|
(addr_t)block->current_data, (addr_t)block->original_data,
|
||||||
block->ref_count, block->accessed, block->busy ? 'B' : '-',
|
(addr_t)block->parent_data, block->ref_count, block->accessed,
|
||||||
block->is_writing ? 'W' : '-', block->is_dirty ? 'B' : '-',
|
block->busy ? 'B' : '-', block->is_writing ? 'W' : '-',
|
||||||
block->unused ? 'U' : '-', block->unmapped ? 'M' : '-',
|
block->is_dirty ? 'B' : '-', block->unused ? 'U' : '-',
|
||||||
(addr_t)block->transaction, (addr_t)block->previous_transaction);
|
block->unmapped ? 'M' : '-', (addr_t)block->transaction,
|
||||||
|
(addr_t)block->previous_transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (block->is_dirty)
|
||||||
|
dirty++;
|
||||||
|
if (block->ref_count)
|
||||||
|
referenced++;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf(" %ld blocks.\n", count);
|
kprintf(" %ld blocks total, %ld dirty, %ld referenced.\n", count, dirty,
|
||||||
|
referenced);
|
||||||
|
|
||||||
hash_close(cache->hash, &iterator, false);
|
hash_close(cache->hash, &iterator, false);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+6
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004-2006, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2004-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef BLOCK_CACHE_PRIVATE_H
|
#ifndef BLOCK_CACHE_PRIVATE_H
|
||||||
@@ -125,13 +125,17 @@ struct block_cache : DoublyLinkedListLinkImpl<block_cache> {
|
|||||||
|
|
||||||
block_range *GetFreeRange();
|
block_range *GetFreeRange();
|
||||||
block_range *GetRange(void *address);
|
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);
|
void FreeBlock(cached_block *block);
|
||||||
cached_block *NewBlock(off_t blockNumber);
|
cached_block *NewBlock(off_t blockNumber);
|
||||||
void Free(void *address);
|
void Free(void *address);
|
||||||
void *Allocate();
|
void *Allocate();
|
||||||
|
|
||||||
static void LowMemoryHandler(void *data, int32 level);
|
static void LowMemoryHandler(void *data, int32 level);
|
||||||
|
|
||||||
|
private:
|
||||||
|
cached_block *_GetUnusedBlock();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user