--- linux-2.4.2-0.1.42/mm/vmscan.c.~1~ Wed Mar 28 18:07:20 2001 +++ linux-2.4.2-0.1.42/mm/vmscan.c Wed Mar 28 19:34:35 2001 @@ -704,6 +704,32 @@ return freed_pages + flushed_pages; } +/* Check to see if a given page is a swap cache page with no further + * references to the swap entry nor to the page in memory. Clear all of + * the aging information for such pages to force them immediately onto + * the inactive_clean list for page reclamation. */ + +static void check_orphaned_swap(struct page *page) +{ + spinlock_t *pg_lock = PAGECACHE_LOCK(page); + + if (spin_trylock(pg_lock)) { + /* Re-test the page state under protection of the proper + * spinlock */ + if (PageSwapCache(page) && atomic_read(&page->count) == 1) { + if (!TryLockPage(page)) { + if (swap_count(page) == 1) { + ClearPageDirty(page); + ClearPageReferenced(page); + page->age = 0; + } + UnlockPage(page); + } + } + spin_unlock(pg_lock); + } +} + /** * refill_inactive_scan - scan the active list and find pages to deactivate * @priority: the priority at which to scan @@ -728,6 +754,12 @@ /* Wrong page on list?! (list corruption, should not happen) */ if (!PageActive(page)) BUG(); + + /* Special case: orphaned swap cache pages should be + * reclaimed as quickly as possible, regardless of their + * age or whether they are dirty or not. */ + if (PageSwapCache(page) && atomic_read(&page->count) == 1) + check_orphaned_swap(page); /* Do aging on the pages. */ if (PageTestandClearReferenced(page)) {