Patch by Zhao Shuai with small changes by myself:

* Some renaming: A location in a swap file where a page can be stored is
  now called "slot" instead of "page" or "swap page".
* swap_slot_alloc(): Update the hint more correctly after allocating
  slots at the hint.
* swap_space_reserve(): When less than the requested space could be
  reserved, it always returned 0 and leaked the remaining pages.
* swap_file_delete(): sSwapFileListLock wasn't unlocked in error cases.
  Use MutexLocker now.
* swap_free_page_swap_space(): sAvailSwapSpace wasn't updated.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27057 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2008-08-19 00:32:54 +00:00
parent 2a79a7686f
commit 7fd3b44794
2 changed files with 114 additions and 104 deletions

View File

@ -25,6 +25,7 @@
#include <heap.h> #include <heap.h>
#include <slab/Slab.h> #include <slab/Slab.h>
#include <syscalls.h> #include <syscalls.h>
#include <util/AutoLock.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h> #include <util/OpenHashTable.h>
#include <vfs.h> #include <vfs.h>
@ -46,7 +47,7 @@
#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)
#define SWAP_PAGE_NONE (~(swap_addr_t)0) #define SWAP_SLOT_NONE (~(swap_addr_t)0)
// bitmap allocation macros // bitmap allocation macros
#define NUM_BYTES_PER_WORD 4 #define NUM_BYTES_PER_WORD 4
@ -67,11 +68,11 @@
struct swap_file : DoublyLinkedListLinkImpl<swap_file> { struct swap_file : DoublyLinkedListLinkImpl<swap_file> {
struct vnode *vnode; struct vnode *vnode;
swap_addr_t first_page; swap_addr_t first_slot;
swap_addr_t last_page; swap_addr_t last_slot;
swap_addr_t used; // # of pages used swap_addr_t used; // # of slots used
uint32 *maps; // bitmap for the pages uint32 *maps; // bitmap for the slots
swap_addr_t hint; // next free page swap_addr_t hint; // next free slot
}; };
struct swap_hash_key { struct swap_hash_key {
@ -83,7 +84,7 @@ struct swap_hash_key {
struct swap_block : HashTableLink<swap_block> { struct swap_block : HashTableLink<swap_block> {
swap_hash_key key; swap_hash_key key;
uint32 used; uint32 used;
swap_addr_t swap_pages[SWAP_BLOCK_PAGES]; swap_addr_t swap_slots[SWAP_BLOCK_PAGES];
}; };
struct SwapHashTableDefinition { struct SwapHashTableDefinition {
@ -135,26 +136,26 @@ static object_cache *sSwapBlockCache;
static swap_addr_t static swap_addr_t
swap_page_alloc(uint32 npages) swap_slot_alloc(uint32 count)
{ {
mutex_lock(&sSwapFileListLock); mutex_lock(&sSwapFileListLock);
if (sSwapFileList.IsEmpty()) { if (sSwapFileList.IsEmpty()) {
mutex_unlock(&sSwapFileListLock); mutex_unlock(&sSwapFileListLock);
panic("swap_page_alloc(): no swap file in the system\n"); panic("swap_slot_alloc(): no swap file in the system\n");
return SWAP_PAGE_NONE; return SWAP_SLOT_NONE;
} }
// compute how many pages are free in all swap files // compute how many pages are free in all swap files
uint32 freeSwapPages = 0; uint32 freeSwapPages = 0;
for (SwapFileList::Iterator it = sSwapFileList.GetIterator(); for (SwapFileList::Iterator it = sSwapFileList.GetIterator();
swap_file *file = it.Next();) swap_file *file = it.Next();)
freeSwapPages += file->last_page - file->first_page - file->used; freeSwapPages += file->last_slot - file->first_slot - file->used;
if (freeSwapPages < npages) { if (freeSwapPages < count) {
mutex_unlock(&sSwapFileListLock); mutex_unlock(&sSwapFileListLock);
panic("swap_page_alloc(): swap space exhausted!\n"); panic("swap_slot_alloc(): swap space exhausted!\n");
return SWAP_PAGE_NONE; return SWAP_SLOT_NONE;
} }
swap_addr_t hint = 0; swap_addr_t hint = 0;
@ -164,11 +165,11 @@ swap_page_alloc(uint32 npages)
sSwapFileAlloc = sSwapFileList.First(); sSwapFileAlloc = sSwapFileList.First();
hint = sSwapFileAlloc->hint; hint = sSwapFileAlloc->hint;
swap_addr_t pageCount = sSwapFileAlloc->last_page swap_addr_t pageCount = sSwapFileAlloc->last_slot
- sSwapFileAlloc->first_page; - sSwapFileAlloc->first_slot;
swap_addr_t i = 0; swap_addr_t i = 0;
while (i < npages && (hint + npages) <= pageCount) { while (i < count && (hint + count) <= pageCount) {
if (TESTBIT(sSwapFileAlloc->maps, hint + i)) { if (TESTBIT(sSwapFileAlloc->maps, hint + i)) {
hint++; hint++;
i = 0; i = 0;
@ -176,74 +177,81 @@ swap_page_alloc(uint32 npages)
i++; i++;
} }
if (i == npages) if (i == count)
break; break;
// this swap_file is full, find another // this swap_file is full, find another
sSwapFileAlloc = sSwapFileList.GetNext(sSwapFileAlloc); sSwapFileAlloc = sSwapFileList.GetNext(sSwapFileAlloc);
} }
// no swap file can alloc so many pages, we return SWAP_PAGE_NONE // no swap file can alloc so many pages, we return SWAP_SLOT_NONE
// and VMAnonymousCache::Write() will adjust allocation amount // and VMAnonymousCache::Write() will adjust allocation amount
if (j == sSwapFileCount) { if (j == sSwapFileCount) {
mutex_unlock(&sSwapFileListLock); mutex_unlock(&sSwapFileListLock);
return SWAP_PAGE_NONE; return SWAP_SLOT_NONE;
} }
swap_addr_t swapAddress = sSwapFileAlloc->first_page + hint; swap_addr_t slotIndex = sSwapFileAlloc->first_slot + hint;
for (uint32 i = 0; i < npages; i++) for (uint32 i = 0; i < count; i++)
SETBIT(sSwapFileAlloc->maps, hint + i); SETBIT(sSwapFileAlloc->maps, hint + i);
if (hint == sSwapFileAlloc->hint) if (hint == sSwapFileAlloc->hint) {
sSwapFileAlloc->hint += npages; sSwapFileAlloc->hint += count;
swap_addr_t pageCount = sSwapFileAlloc->last_slot
- sSwapFileAlloc->first_slot;
while (TESTBIT(sSwapFileAlloc->maps, sSwapFileAlloc->hint)
&& sSwapFileAlloc->hint < pageCount) {
sSwapFileAlloc->hint++;
}
}
sSwapFileAlloc->used += npages; sSwapFileAlloc->used += count;
// if this swap file has used more than 90% percent of its pages // if this swap file has used more than 90% percent of its slots
// switch to another // switch to another
if (sSwapFileAlloc->used if (sSwapFileAlloc->used
> 9 * (sSwapFileAlloc->last_page - sSwapFileAlloc->first_page) / 10) > 9 * (sSwapFileAlloc->last_slot - sSwapFileAlloc->first_slot) / 10)
sSwapFileAlloc = sSwapFileList.GetNext(sSwapFileAlloc); sSwapFileAlloc = sSwapFileList.GetNext(sSwapFileAlloc);
mutex_unlock(&sSwapFileListLock); mutex_unlock(&sSwapFileListLock);
return swapAddress; return slotIndex;
} }
static swap_file * static swap_file *
find_swap_file(swap_addr_t swapAddress) find_swap_file(swap_addr_t slotIndex)
{ {
for (SwapFileList::Iterator it = sSwapFileList.GetIterator(); for (SwapFileList::Iterator it = sSwapFileList.GetIterator();
swap_file *swapFile = it.Next();) { swap_file *swapFile = it.Next();) {
if (swapAddress >= swapFile->first_page if (slotIndex >= swapFile->first_slot
&& swapAddress < swapFile->last_page) && slotIndex < swapFile->last_slot)
return swapFile; return swapFile;
} }
panic("find_swap_file(): can't find swap file for %ld\n", swapAddress); panic("find_swap_file(): can't find swap file for slot %ld\n", slotIndex);
return NULL; return NULL;
} }
static void static void
swap_page_dealloc(swap_addr_t swapAddress, uint32 npages) swap_slot_dealloc(swap_addr_t slotIndex, uint32 count)
{ {
if (swapAddress == SWAP_PAGE_NONE) if (slotIndex == SWAP_SLOT_NONE)
return; return;
mutex_lock(&sSwapFileListLock); mutex_lock(&sSwapFileListLock);
swap_file *swapFile = find_swap_file(swapAddress); swap_file *swapFile = find_swap_file(slotIndex);
swapAddress -= swapFile->first_page; slotIndex -= swapFile->first_slot;
for (uint32 i = 0; i < npages; i++) for (uint32 i = 0; i < count; i++)
CLEARBIT(swapFile->maps, swapAddress + i); CLEARBIT(swapFile->maps, slotIndex + i);
if (swapFile->hint > swapAddress) if (swapFile->hint > slotIndex)
swapFile->hint = swapAddress; swapFile->hint = slotIndex;
swapFile->used -= npages; swapFile->used -= count;
mutex_unlock(&sSwapFileListLock); mutex_unlock(&sSwapFileListLock);
} }
@ -255,8 +263,8 @@ swap_space_reserve(off_t amount)
if (sAvailSwapSpace >= amount) if (sAvailSwapSpace >= amount)
sAvailSwapSpace -= amount; sAvailSwapSpace -= amount;
else { else {
sAvailSwapSpace = 0;
amount = sAvailSwapSpace; amount = sAvailSwapSpace;
sAvailSwapSpace = 0;
} }
mutex_unlock(&sAvailSwapSpaceLock); mutex_unlock(&sAvailSwapSpaceLock);
@ -281,11 +289,11 @@ VMAnonymousCache::~VMAnonymousCache()
// free allocated swap space and swap block // free allocated swap space and swap block
for (off_t offset = virtual_base, toFree = fAllocatedSwapSize; for (off_t offset = virtual_base, toFree = fAllocatedSwapSize;
offset < virtual_end && toFree > 0; offset += B_PAGE_SIZE) { offset < virtual_end && toFree > 0; offset += B_PAGE_SIZE) {
swap_addr_t swapAddr = _SwapBlockGetAddress(offset >> PAGE_SHIFT); swap_addr_t slotIndex = _SwapBlockGetAddress(offset >> PAGE_SHIFT);
if (swapAddr == SWAP_PAGE_NONE) if (slotIndex == SWAP_SLOT_NONE)
continue; continue;
swap_page_dealloc(swapAddr, 1); swap_slot_dealloc(slotIndex, 1);
_SwapBlockFree(offset >> PAGE_SHIFT, 1); _SwapBlockFree(offset >> PAGE_SHIFT, 1);
toFree -= B_PAGE_SIZE; toFree -= B_PAGE_SIZE;
} }
@ -339,7 +347,7 @@ VMAnonymousCache::Commit(off_t size)
bool bool
VMAnonymousCache::HasPage(off_t offset) VMAnonymousCache::HasPage(off_t offset)
{ {
if (_SwapBlockGetAddress(offset >> PAGE_SHIFT) != SWAP_PAGE_NONE) if (_SwapBlockGetAddress(offset >> PAGE_SHIFT) != SWAP_SLOT_NONE)
return true; return true;
return false; return false;
@ -353,16 +361,16 @@ VMAnonymousCache::Read(off_t offset, const iovec *vecs, size_t count,
off_t pageIndex = offset >> PAGE_SHIFT; off_t pageIndex = offset >> PAGE_SHIFT;
for (uint32 i = 0, j = 0; i < count; i = j) { for (uint32 i = 0, j = 0; i < count; i = j) {
swap_addr_t startSwapAddr = _SwapBlockGetAddress(pageIndex + i); swap_addr_t startSlotIndex = _SwapBlockGetAddress(pageIndex + i);
for (j = i + 1; j < count; j++) { for (j = i + 1; j < count; j++) {
swap_addr_t swapAddr = _SwapBlockGetAddress(pageIndex + j); swap_addr_t slotIndex = _SwapBlockGetAddress(pageIndex + j);
if (swapAddr != startSwapAddr + j - i) if (slotIndex != startSlotIndex + j - i)
break; break;
} }
swap_file *swapFile = find_swap_file(startSwapAddr); swap_file *swapFile = find_swap_file(startSlotIndex);
off_t pos = (startSwapAddr - swapFile->first_page) * PAGE_SIZE; off_t pos = (startSlotIndex - swapFile->first_slot) * B_PAGE_SIZE;
status_t status = vfs_read_pages(swapFile->vnode, NULL, pos, vecs + i, status_t status = vfs_read_pages(swapFile->vnode, NULL, pos, vecs + i,
j - i, 0, _numBytes); j - i, 0, _numBytes);
@ -382,9 +390,9 @@ VMAnonymousCache::Write(off_t offset, const iovec *vecs, size_t count,
Lock(); Lock();
for (uint32 i = 0; i < count; i++) { for (uint32 i = 0; i < count; i++) {
swap_addr_t swapAddr = _SwapBlockGetAddress(pageIndex + i); swap_addr_t slotIndex = _SwapBlockGetAddress(pageIndex + i);
if (swapAddr != SWAP_PAGE_NONE) { if (slotIndex != SWAP_SLOT_NONE) {
swap_page_dealloc(swapAddr, 1); swap_slot_dealloc(slotIndex, 1);
_SwapBlockFree(pageIndex + i, 1); _SwapBlockFree(pageIndex + i, 1);
fAllocatedSwapSize -= B_PAGE_SIZE; fAllocatedSwapSize -= B_PAGE_SIZE;
} }
@ -398,16 +406,16 @@ VMAnonymousCache::Write(off_t offset, const iovec *vecs, size_t count,
uint32 n = count; uint32 n = count;
for (uint32 i = 0; i < count; i += n) { for (uint32 i = 0; i < count; i += n) {
swap_addr_t swapAddr; swap_addr_t slotIndex;
// try to allocate n pages, if fail, try to allocate n/2 // try to allocate n slots, if fail, try to allocate n/2
while ((swapAddr = swap_page_alloc(n)) == SWAP_PAGE_NONE && n >= 2) while ((slotIndex = swap_slot_alloc(n)) == SWAP_SLOT_NONE && n >= 2)
n >>= 1; n >>= 1;
if (swapAddr == SWAP_PAGE_NONE) if (slotIndex == SWAP_SLOT_NONE)
panic("VMAnonymousCache::Write(): can't allocate swap space\n"); panic("VMAnonymousCache::Write(): can't allocate swap space\n");
swap_file *swapFile = find_swap_file(swapAddr); swap_file *swapFile = find_swap_file(slotIndex);
off_t pos = (swapAddr - swapFile->first_page) * B_PAGE_SIZE; off_t pos = (slotIndex - swapFile->first_slot) * B_PAGE_SIZE;
status_t status = vfs_write_pages(swapFile->vnode, NULL, pos, vecs + i, status_t status = vfs_write_pages(swapFile->vnode, NULL, pos, vecs + i,
n, flags, _numBytes); n, flags, _numBytes);
@ -416,11 +424,11 @@ VMAnonymousCache::Write(off_t offset, const iovec *vecs, size_t count,
fAllocatedSwapSize -= n * B_PAGE_SIZE; fAllocatedSwapSize -= n * B_PAGE_SIZE;
Unlock(); Unlock();
swap_page_dealloc(swapAddr, n); swap_slot_dealloc(slotIndex, n);
return status; return status;
} }
_SwapBlockBuild(pageIndex + i, swapAddr, n); _SwapBlockBuild(pageIndex + i, slotIndex, n);
} }
return B_OK; return B_OK;
@ -451,8 +459,8 @@ VMAnonymousCache::Fault(struct vm_address_space *aspace, off_t offset)
if (fPrecommittedPages == 0) { if (fPrecommittedPages == 0) {
// try to commit additional swap space/memory // try to commit additional swap space/memory
if (swap_space_reserve(PAGE_SIZE) == PAGE_SIZE) if (swap_space_reserve(B_PAGE_SIZE) == B_PAGE_SIZE)
fCommittedSwapSize += PAGE_SIZE; fCommittedSwapSize += B_PAGE_SIZE;
else if (vm_try_reserve_memory(B_PAGE_SIZE, 0) != B_OK) else if (vm_try_reserve_memory(B_PAGE_SIZE, 0) != B_OK)
return B_NO_MEMORY; return B_NO_MEMORY;
@ -487,29 +495,29 @@ VMAnonymousCache::MergeStore(VMCache* _source)
_Commit(actualSize); _Commit(actualSize);
for (off_t offset = source->virtual_base; offset < source->virtual_end; for (off_t offset = source->virtual_base; offset < source->virtual_end;
offset += PAGE_SIZE) { offset += B_PAGE_SIZE) {
off_t pageIndex = offset >> PAGE_SHIFT; off_t pageIndex = offset >> PAGE_SHIFT;
swap_addr_t sourceSwapIndex = source->_SwapBlockGetAddress(pageIndex); swap_addr_t sourceSlotIndex = source->_SwapBlockGetAddress(pageIndex);
if (sourceSwapIndex == SWAP_PAGE_NONE) if (sourceSlotIndex == SWAP_SLOT_NONE)
// this page is not swapped out // this page is not swapped out
continue; continue;
if (LookupPage(offset)) { if (LookupPage(offset)) {
// this page is shadowed and we can find it in the new cache, // this page is shadowed and we can find it in the new cache,
// free the swap space // free the swap space
swap_page_dealloc(sourceSwapIndex, 1); swap_slot_dealloc(sourceSlotIndex, 1);
} else { } else {
swap_addr_t swapIndex = _SwapBlockGetAddress(pageIndex); swap_addr_t slotIndex = _SwapBlockGetAddress(pageIndex);
if (swapIndex == SWAP_PAGE_NONE) { if (slotIndex == SWAP_SLOT_NONE) {
// the page is not shadowed, // the page is not shadowed,
// assign the swap address to the new cache // assign the swap address to the new cache
_SwapBlockBuild(pageIndex, sourceSwapIndex, 1); _SwapBlockBuild(pageIndex, sourceSlotIndex, 1);
fAllocatedSwapSize += B_PAGE_SIZE; fAllocatedSwapSize += B_PAGE_SIZE;
} else { } else {
// the page is shadowed and is also swapped out // the page is shadowed and is also swapped out
swap_page_dealloc(sourceSwapIndex, 1); swap_slot_dealloc(sourceSlotIndex, 1);
} }
} }
source->fAllocatedSwapSize -= B_PAGE_SIZE; source->fAllocatedSwapSize -= B_PAGE_SIZE;
@ -520,13 +528,13 @@ VMAnonymousCache::MergeStore(VMCache* _source)
void void
VMAnonymousCache::_SwapBlockBuild(off_t startPageIndex, VMAnonymousCache::_SwapBlockBuild(off_t startPageIndex,
swap_addr_t startSwapAddress, uint32 count) swap_addr_t startSlotIndex, uint32 count)
{ {
mutex_lock(&sSwapHashLock); mutex_lock(&sSwapHashLock);
for (uint32 i = 0; i < count; i++) { for (uint32 i = 0; i < count; i++) {
off_t pageIndex = startPageIndex + i; off_t pageIndex = startPageIndex + i;
swap_addr_t swapAddress = startSwapAddress + i; swap_addr_t slotIndex = startSlotIndex + i;
swap_hash_key key = { this, pageIndex }; swap_hash_key key = { this, pageIndex };
@ -544,13 +552,13 @@ VMAnonymousCache::_SwapBlockBuild(off_t startPageIndex,
swap->key.page_index = pageIndex & ~(off_t)SWAP_BLOCK_MASK; swap->key.page_index = pageIndex & ~(off_t)SWAP_BLOCK_MASK;
swap->used = 0; swap->used = 0;
for (uint32 i = 0; i < SWAP_BLOCK_PAGES; i++) for (uint32 i = 0; i < SWAP_BLOCK_PAGES; i++)
swap->swap_pages[i] = SWAP_PAGE_NONE; swap->swap_slots[i] = SWAP_SLOT_NONE;
sSwapHashTable.Insert(swap); sSwapHashTable.Insert(swap);
} }
swap_addr_t blockIndex = pageIndex & SWAP_BLOCK_MASK; swap_addr_t blockIndex = pageIndex & SWAP_BLOCK_MASK;
swap->swap_pages[blockIndex] = swapAddress; swap->swap_slots[blockIndex] = slotIndex;
swap->used++; swap->used++;
} }
@ -569,9 +577,9 @@ VMAnonymousCache::_SwapBlockFree(off_t startPageIndex, uint32 count)
swap_hash_key key = { this, pageIndex }; swap_hash_key key = { this, pageIndex };
swap_block *swap = sSwapHashTable.Lookup(key); swap_block *swap = sSwapHashTable.Lookup(key);
if (swap != NULL) { if (swap != NULL) {
swap_addr_t swapAddr = swap->swap_pages[pageIndex & SWAP_BLOCK_MASK]; swap_addr_t swapAddr = swap->swap_slots[pageIndex & SWAP_BLOCK_MASK];
if (swapAddr != SWAP_PAGE_NONE) { if (swapAddr != SWAP_SLOT_NONE) {
swap->swap_pages[pageIndex & SWAP_BLOCK_MASK] = SWAP_PAGE_NONE; swap->swap_slots[pageIndex & SWAP_BLOCK_MASK] = SWAP_SLOT_NONE;
swap->used--; swap->used--;
if (swap->used == 0) { if (swap->used == 0) {
sSwapHashTable.Remove(swap); sSwapHashTable.Remove(swap);
@ -592,16 +600,16 @@ VMAnonymousCache::_SwapBlockGetAddress(off_t pageIndex)
swap_hash_key key = { this, pageIndex }; swap_hash_key key = { this, pageIndex };
swap_block *swap = sSwapHashTable.Lookup(key); swap_block *swap = sSwapHashTable.Lookup(key);
swap_addr_t swapAddress = SWAP_PAGE_NONE; swap_addr_t slotIndex = SWAP_SLOT_NONE;
if (swap != NULL) { if (swap != NULL) {
swap_addr_t blockIndex = pageIndex & SWAP_BLOCK_MASK; swap_addr_t blockIndex = pageIndex & SWAP_BLOCK_MASK;
swapAddress = swap->swap_pages[blockIndex]; slotIndex = swap->swap_slots[blockIndex];
} }
mutex_unlock(&sSwapHashLock); mutex_unlock(&sSwapHashLock);
return swapAddress; return slotIndex;
} }
@ -702,23 +710,22 @@ swap_file_add(char *path)
memset(swap->maps, 0, (pageCount + 7) / 8); memset(swap->maps, 0, (pageCount + 7) / 8);
swap->hint = 0; swap->hint = 0;
// set start page index and add this file to swap file list // set slot index and add this file to swap file list
mutex_lock(&sSwapFileListLock); mutex_lock(&sSwapFileListLock);
if (sSwapFileList.IsEmpty()) { if (sSwapFileList.IsEmpty()) {
swap->first_page = 0; swap->first_slot = 0;
swap->last_page = pageCount; swap->last_slot = pageCount;
} } else {
else {
// leave one page gap between two swap files // leave one page gap between two swap files
swap->first_page = sSwapFileList.Last()->last_page + 1; swap->first_slot = sSwapFileList.Last()->last_slot + 1;
swap->last_page = swap->first_page + pageCount; swap->last_slot = swap->first_slot + pageCount;
} }
sSwapFileList.Add(swap); sSwapFileList.Add(swap);
sSwapFileCount++; sSwapFileCount++;
mutex_unlock(&sSwapFileListLock); mutex_unlock(&sSwapFileListLock);
mutex_lock(&sAvailSwapSpaceLock); mutex_lock(&sAvailSwapSpaceLock);
sAvailSwapSpace += pageCount * PAGE_SIZE; sAvailSwapSpace += pageCount * B_PAGE_SIZE;
mutex_unlock(&sAvailSwapSpaceLock); mutex_unlock(&sAvailSwapSpaceLock);
return B_OK; return B_OK;
@ -730,12 +737,10 @@ swap_file_delete(char *path)
{ {
vnode *node = NULL; vnode *node = NULL;
status_t status = vfs_get_vnode_from_path(path, true, &node); status_t status = vfs_get_vnode_from_path(path, true, &node);
if (status != B_OK) { if (status != B_OK)
vfs_put_vnode(node);
return status; return status;
}
mutex_lock(&sSwapFileListLock); MutexLocker locker(sSwapFileListLock);
swap_file *swapFile = NULL; swap_file *swapFile = NULL;
for (SwapFileList::Iterator it = sSwapFileList.GetIterator(); for (SwapFileList::Iterator it = sSwapFileList.GetIterator();
@ -757,10 +762,10 @@ swap_file_delete(char *path)
sSwapFileList.Remove(swapFile); sSwapFileList.Remove(swapFile);
sSwapFileCount--; sSwapFileCount--;
mutex_unlock(&sSwapFileListLock); locker.Unlock();
mutex_lock(&sAvailSwapSpaceLock); mutex_lock(&sAvailSwapSpaceLock);
sAvailSwapSpace -= (swapFile->last_page - swapFile->first_page) * PAGE_SIZE; sAvailSwapSpace -= (swapFile->last_slot - swapFile->first_slot) * PAGE_SIZE;
mutex_unlock(&sAvailSwapSpaceLock); mutex_unlock(&sAvailSwapSpaceLock);
vfs_put_vnode(swapFile->vnode); vfs_put_vnode(swapFile->vnode);
@ -847,14 +852,19 @@ swap_free_page_swap_space(vm_page *page)
if (cache == NULL) if (cache == NULL)
return false; return false;
swap_addr_t swapAddress = cache->_SwapBlockGetAddress(page->cache_offset); swap_addr_t slotIndex = cache->_SwapBlockGetAddress(page->cache_offset);
if (swapAddress == SWAP_PAGE_NONE) if (slotIndex == SWAP_SLOT_NONE)
return false; return false;
swap_page_dealloc(swapAddress, 1); swap_slot_dealloc(slotIndex, 1);
cache->fAllocatedSwapSize -= B_PAGE_SIZE; cache->fAllocatedSwapSize -= B_PAGE_SIZE;
cache->_SwapBlockFree(page->cache_offset, 1); cache->_SwapBlockFree(page->cache_offset, 1);
return true;
mutex_lock(&sAvailSwapSpaceLock);
sAvailSwapSpace += B_PAGE_SIZE;
mutex_unlock(&sAvailSwapSpaceLock);
return true;
} }
@ -874,14 +884,14 @@ swap_total_swap_pages()
{ {
mutex_lock(&sSwapFileListLock); mutex_lock(&sSwapFileListLock);
uint32 totalSwapPages = 0; uint32 totalSwapSlots = 0;
for (SwapFileList::Iterator it = sSwapFileList.GetIterator(); for (SwapFileList::Iterator it = sSwapFileList.GetIterator();
swap_file *swapFile = it.Next();) swap_file *swapFile = it.Next();)
totalSwapPages += swapFile->last_page - swapFile->first_page; totalSwapSlots += swapFile->last_slot - swapFile->first_slot;
mutex_unlock(&sSwapFileListLock); mutex_unlock(&sSwapFileListLock);
return totalSwapPages; return totalSwapSlots;
} }
#endif // ENABLE_SWAP_SUPPORT #endif // ENABLE_SWAP_SUPPORT

View File

@ -47,7 +47,7 @@ public:
private: private:
void _SwapBlockBuild(off_t pageIndex, void _SwapBlockBuild(off_t pageIndex,
swap_addr_t swapAddress, uint32 count); swap_addr_t slotIndex, uint32 count);
void _SwapBlockFree(off_t pageIndex, uint32 count); void _SwapBlockFree(off_t pageIndex, uint32 count);
swap_addr_t _SwapBlockGetAddress(off_t pageIndex); swap_addr_t _SwapBlockGetAddress(off_t pageIndex);
status_t _Commit(off_t size); status_t _Commit(off_t size);