From 529bf1c6d767f08bf5f84d80b132119441a67085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 28 Dec 2005 16:40:05 +0000 Subject: [PATCH] block_range::Delete() did not remove the block_range from the free list, and thus, it could be used again which led to a crash. Changed the free ranges list from a singly linked list to a doubly linked list so that not all free ranges have to be searched for the one to be freed anymore. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15696 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/cache/block_allocator.cpp | 25 +++++-------------- src/system/kernel/cache/block_cache.cpp | 7 +++--- src/system/kernel/cache/block_cache_private.h | 10 ++++++-- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/system/kernel/cache/block_allocator.cpp b/src/system/kernel/cache/block_allocator.cpp index de6de70ea0..17da1330df 100644 --- a/src/system/kernel/cache/block_allocator.cpp +++ b/src/system/kernel/cache/block_allocator.cpp @@ -201,8 +201,7 @@ block_range::New(block_cache *cache, block_range **_range) range->base = address; // insert into free ranges list in cache - range->free_next = cache->free_ranges; - cache->free_ranges = range; + cache->free_ranges.Add(range); *_range = range; return B_OK; @@ -236,6 +235,9 @@ block_range::Delete(block_cache *cache, block_range *range) vm_page_set_state(range->pages[i], PAGE_STATE_FREE); } + // remove from cache free list + cache->free_ranges.Remove(range); + free(range); } @@ -376,21 +378,7 @@ block_range::Allocate(block_cache *cache, block_chunk **_chunk) if (used_mask == cache->range_mask) { // range is full, remove it from the free list - - // usually, the first entry will be ourself, but we don't count on it - block_range *last = NULL, *range = cache->free_ranges; - while (range != NULL && range != this) { - last = range; - range = range->free_next; - } - if (range == NULL) { - panic("block_range %p was free but not in the free list\n", this); - } else { - if (last) - last->free_next = free_next; - else - cache->free_ranges = free_next; - } + cache->free_ranges.Remove(this); } } TRACE(("Allocate: used masks: chunk = %x, range = %lx\n", chunks[chunk].used_mask, used_mask)); @@ -409,8 +397,7 @@ block_range::Free(block_cache *cache, void *address) if (chunks[chunk].used_mask == cache->chunk_mask) { if (used_mask == cache->range_mask) { // range was full before, add it to the free list - free_next = cache->free_ranges; - cache->free_ranges = this; + cache->free_ranges.Add(this); } // chunk was full before, propagate usage bit to range used_mask &= ~(1UL << chunk); diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp index edd3c07a95..1b2df13ebe 100644 --- a/src/system/kernel/cache/block_cache.cpp +++ b/src/system/kernel/cache/block_cache.cpp @@ -153,8 +153,7 @@ block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize) next_transaction_id(1), last_transaction(NULL), transaction_hash(NULL), - ranges_hash(NULL), - free_ranges(NULL) + ranges_hash(NULL) { hash = hash_init(32, 0, &cached_block::Compare, &cached_block::Hash); if (hash == NULL) @@ -208,8 +207,8 @@ block_cache::InitCheck() block_range * block_cache::GetFreeRange() { - if (free_ranges != NULL) - return free_ranges; + if (!free_ranges.IsEmpty()) + return free_ranges.First(); // we need to allocate a new range block_range *range; diff --git a/src/system/kernel/cache/block_cache_private.h b/src/system/kernel/cache/block_cache_private.h index 965806044f..f3d368b96b 100644 --- a/src/system/kernel/cache/block_cache_private.h +++ b/src/system/kernel/cache/block_cache_private.h @@ -25,7 +25,9 @@ struct cache_transaction; struct cached_block; struct block_chunk; struct block_cache; +struct block_range; typedef DoublyLinkedListLink block_link; +typedef DoublyLinkedListLink range_link; struct cached_block { @@ -66,7 +68,7 @@ struct block_chunk { struct block_range { block_range *next; // next in hash - block_range *free_next; + range_link link; addr_t base; uint32 used_mask; vm_page *pages[kNumBlockRangePages]; @@ -91,6 +93,10 @@ struct block_range { static uint32 Hash(void *_blockRange, const void *_address, uint32 range); }; +typedef DoublyLinkedList > range_list; + struct block_cache { hash_table *hash; benaphore lock; @@ -102,7 +108,7 @@ struct block_cache { hash_table *transaction_hash; hash_table *ranges_hash; - block_range *free_ranges; + range_list free_ranges; uint32 chunks_per_range; size_t chunk_size; uint32 range_mask;