From 4f2d40ec1b865fbd9d33d5b57cab61e4520f66f7 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 21 Aug 2008 03:28:35 +0000 Subject: [PATCH] * The callback object created in WriteAsync() was never deleted. Thus eventually the VIP heap would be exhausted. * WriteAsync() didn't call the provided callback when an error occurred before invoking vfs_asynchronous_write_pages(). The page writer would get stuck in those cases. * The object cache used for the swap blocks does now use the asynchronous resizing feature to avoid deadlocks. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27101 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/vm/VMAnonymousCache.cpp | 25 ++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/system/kernel/vm/VMAnonymousCache.cpp b/src/system/kernel/vm/VMAnonymousCache.cpp index 9521314ed9..593fefacd3 100644 --- a/src/system/kernel/vm/VMAnonymousCache.cpp +++ b/src/system/kernel/vm/VMAnonymousCache.cpp @@ -45,6 +45,10 @@ # define TRACE(x) ; #endif + +// number of free swap blocks the object cache shall minimally have +#define MIN_SWAP_BLOCK_RESERVE 4096 + #define SWAP_BLOCK_PAGES 32 #define SWAP_BLOCK_SHIFT 5 /* 1 << SWAP_BLOCK_SHIFT == SWAP_BLOCK_PAGES */ #define SWAP_BLOCK_MASK (SWAP_BLOCK_PAGES - 1) @@ -349,6 +353,13 @@ public: } fNextCallback->IOFinished(status, partialTransfer, bytesTransferred); + + delete this; + } + + void operator delete(void* address, size_t size) + { + io_request_free(address); } private: @@ -531,8 +542,10 @@ VMAnonymousCache::WriteAsync(off_t offset, const iovec* vecs, size_t count, // If the page doesn't have any swap space yet, allocate it. if (newSlot) { AutoLocker locker(this); - if (fAllocatedSwapSize + B_PAGE_SIZE > fCommittedSwapSize) + if (fAllocatedSwapSize + B_PAGE_SIZE > fCommittedSwapSize) { + _callback->IOFinished(B_ERROR, true, 0); return B_ERROR; + } fAllocatedSwapSize += B_PAGE_SIZE; @@ -551,6 +564,7 @@ VMAnonymousCache::WriteAsync(off_t offset, const iovec* vecs, size_t count, swap_slot_dealloc(slotIndex, 1); } + _callback->IOFinished(B_NO_MEMORY, true, 0); return B_NO_MEMORY; } // TODO: If the page already had swap space assigned, we don't need an own @@ -917,9 +931,18 @@ swap_init(void) if (sSwapBlockCache == NULL) panic("swap_init(): can't create object cache for swap blocks\n"); + status_t error = object_cache_set_minimum_reserve(sSwapBlockCache, + MIN_SWAP_BLOCK_RESERVE); + if (error != B_OK) { + panic("swap_init(): object_cache_set_minimum_reserve() failed: %s", + strerror(error)); + } + // init swap hash table sSwapHashTable.Init(); mutex_init(&sSwapHashLock, "swaphash"); +// TODO: The hash table needs a special resizing strategy. Otherwise we could +// deadlock while trying swap pages out. // init swap file list mutex_init(&sSwapFileListLock, "swaplist");