* 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
This commit is contained in:
Ingo Weinhold 2008-08-21 03:28:35 +00:00
parent 1cda5944ad
commit 4f2d40ec1b

View File

@ -45,6 +45,10 @@
# define TRACE(x) ; # define TRACE(x) ;
#endif #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_PAGES 32
#define SWAP_BLOCK_SHIFT 5 /* 1 << SWAP_BLOCK_SHIFT == SWAP_BLOCK_PAGES */ #define SWAP_BLOCK_SHIFT 5 /* 1 << SWAP_BLOCK_SHIFT == SWAP_BLOCK_PAGES */
#define SWAP_BLOCK_MASK (SWAP_BLOCK_PAGES - 1) #define SWAP_BLOCK_MASK (SWAP_BLOCK_PAGES - 1)
@ -349,6 +353,13 @@ public:
} }
fNextCallback->IOFinished(status, partialTransfer, bytesTransferred); fNextCallback->IOFinished(status, partialTransfer, bytesTransferred);
delete this;
}
void operator delete(void* address, size_t size)
{
io_request_free(address);
} }
private: 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 the page doesn't have any swap space yet, allocate it.
if (newSlot) { if (newSlot) {
AutoLocker<VMCache> locker(this); AutoLocker<VMCache> locker(this);
if (fAllocatedSwapSize + B_PAGE_SIZE > fCommittedSwapSize) if (fAllocatedSwapSize + B_PAGE_SIZE > fCommittedSwapSize) {
_callback->IOFinished(B_ERROR, true, 0);
return B_ERROR; return B_ERROR;
}
fAllocatedSwapSize += B_PAGE_SIZE; fAllocatedSwapSize += B_PAGE_SIZE;
@ -551,6 +564,7 @@ VMAnonymousCache::WriteAsync(off_t offset, const iovec* vecs, size_t count,
swap_slot_dealloc(slotIndex, 1); swap_slot_dealloc(slotIndex, 1);
} }
_callback->IOFinished(B_NO_MEMORY, true, 0);
return B_NO_MEMORY; return B_NO_MEMORY;
} }
// TODO: If the page already had swap space assigned, we don't need an own // 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) if (sSwapBlockCache == NULL)
panic("swap_init(): can't create object cache for swap blocks\n"); 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 // init swap hash table
sSwapHashTable.Init(); sSwapHashTable.Init();
mutex_init(&sSwapHashLock, "swaphash"); 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 // init swap file list
mutex_init(&sSwapFileListLock, "swaplist"); mutex_init(&sSwapFileListLock, "swaplist");