--- linux/mm/filemap.c.orig Mon Apr 23 13:35:06 2001 +++ linux/mm/filemap.c Mon Apr 23 13:37:09 2001 @@ -710,6 +710,34 @@ } /* + * Find a swapcache page (and get a reference) or return NULL. + * The SwapCache check is protected by the pagecache lock. + */ +struct page * __find_get_swapcache_page(struct address_space *mapping, + unsigned long offset, struct page **hash) +{ + struct page *page; + + /* + * We need the LRU lock to protect against page_launder(). + */ + spin_lock(&pagecache_lock); + spin_lock(&pagemap_lru_lock); + + page = __find_page_nolock(mapping, offset, *hash); + if (page) { + if (PageSwapCache(page)) + page_cache_get(page); + else + page = NULL; + } + spin_unlock(&pagemap_lru_lock); + spin_unlock(&pagecache_lock); + + return page; +} + +/* * Same as the above, but lock the page too, verifying that * it's still valid once we own it. */ --- linux/mm/swap_state.c.orig Mon Apr 23 13:35:06 2001 +++ linux/mm/swap_state.c Mon Apr 23 13:37:01 2001 @@ -163,37 +163,18 @@ /* * Right now the pagecache is 32-bit only. But it's a 32 bit index. =) */ -repeat: - found = find_lock_page(&swapper_space, entry.val); + found = find_get_swapcache_page(&swapper_space, entry.val); if (!found) return 0; - /* - * Though the "found" page was in the swap cache an instant - * earlier, it might have been removed by refill_inactive etc. - * Re search ... Since find_lock_page grabs a reference on - * the page, it can not be reused for anything else, namely - * it can not be associated with another swaphandle, so it - * is enough to check whether the page is still in the scache. - */ - if (!PageSwapCache(found)) { - UnlockPage(found); - page_cache_release(found); - goto repeat; - } + if (!PageSwapCache(found)) + BUG(); if (found->mapping != &swapper_space) - goto out_bad; + BUG(); #ifdef SWAP_CACHE_INFO swap_cache_find_success++; #endif - UnlockPage(found); return found; } - -out_bad: - printk (KERN_ERR "VM: Found a non-swapper swap page!\n"); - UnlockPage(found); - page_cache_release(found); - return 0; } /* --- linux/include/linux/pagemap.h.orig Mon Apr 23 13:35:05 2001 +++ linux/include/linux/pagemap.h Mon Apr 23 13:37:01 2001 @@ -77,7 +77,12 @@ unsigned long index, struct page **hash); extern void lock_page(struct page *page); #define find_lock_page(mapping, index) \ - __find_lock_page(mapping, index, page_hash(mapping, index)) + __find_lock_page(mapping, index, page_hash(mapping, index)) + +extern struct page * __find_get_swapcache_page (struct address_space * mapping, + unsigned long index, struct page **hash); +#define find_get_swapcache_page(mapping, index) \ + __find_get_swapcache_page(mapping, index, page_hash(mapping, index)) extern void __add_page_to_hash_queue(struct page * page, struct page **p);