return page_count(page) - !!page->buffers == 1;
}
-/*
- * Work out if there are any other processes sharing this
- * swap cache page. Never mind the buffers.
- */
-static inline int exclusive_swap_page(struct page *page)
-{
- if (!PageLocked(page))
- BUG();
- if (!PageSwapCache(page))
- return 0;
- if (page_count(page) - !!page->buffers != 2) /* 2: us + cache */
- return 0;
- return swap_count(page) == 1; /* 1: just cache */
-}
+extern int remove_exclusive_swap_page(struct page *);
extern void __free_pte(pte_t);
#define PAGE_CACHE_ALIGN(addr) (((addr)+PAGE_CACHE_SIZE-1)&PAGE_CACHE_MASK)
#define page_cache_get(x) get_page(x)
-#define page_cache_release(x) __free_page(x)
+#define page_cache_release(x) free_lru_page(x)
static inline struct page *page_cache_alloc(struct address_space *x)
{
if (TryLockPage(old_page))
break;
/* Recheck swapcachedness once the page is locked */
- can_reuse = exclusive_swap_page(old_page);
- if (can_reuse)
- delete_from_swap_cache(old_page);
+ can_reuse = remove_exclusive_swap_page(old_page);
UnlockPage(old_page);
if (!can_reuse)
break;
if (!new_page)
goto no_mem;
copy_cow_page(old_page,new_page,address);
- free_lru_page(old_page);
+ page_cache_release(old_page);
/*
* Re-check the pte - we dropped the lock
new_page = old_page;
}
spin_unlock(&mm->page_table_lock);
- free_lru_page(new_page);
+ page_cache_release(new_page);
return 1; /* Minor fault */
bad_wp_page:
printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page);
return -1;
no_mem:
- free_lru_page(old_page);
+ page_cache_release(old_page);
return -1;
}
*/
spin_lock(&mm->page_table_lock);
if (!pte_same(*page_table, orig_pte)) {
- UnlockPage(page);
page_cache_release(page);
spin_unlock(&mm->page_table_lock);
return 1;
set_pte(page_table, entry);
} else {
/* One of our sibling threads was faster, back out. */
- free_lru_page(new_page);
+ page_cache_release(new_page);
spin_unlock(&mm->page_table_lock);
return 1;
}
* - Marcelo
*/
if (PageSwapCache(page) && !TryLockPage(page)) {
- if (exclusive_swap_page(page))
- delete_from_swap_cache(page);
+ remove_exclusive_swap_page(page);
UnlockPage(page);
}
- free_lru_page(page);
+ page_cache_release(page);
}
/*
}
}
+/*
+ * Work out if there are any other processes sharing this
+ * swap cache page. Free it if you can. Return success.
+ */
+int remove_exclusive_swap_page(struct page *page)
+{
+ int retval;
+ struct swap_info_struct * p;
+ swp_entry_t entry;
+
+ if (!PageLocked(page))
+ BUG();
+ if (!PageSwapCache(page))
+ return 0;
+ if (page_count(page) - !!page->buffers != 2) /* 2: us + cache */
+ return 0;
+
+ entry.val = page->index;
+ p = swap_info_get(entry);
+ if (!p)
+ return 0;
+
+ /* Is the only swap cache user the cache itself? */
+ retval = 0;
+ if (p->swap_map[SWP_OFFSET(entry)] == 1) {
+ /* Recheck the page count with the pagecache lock held.. */
+ spin_lock(&pagecache_lock);
+ if (page_count(page) - !!page->buffers == 2) {
+ __delete_from_swap_cache(page);
+ retval = 1;
+ }
+ spin_unlock(&pagecache_lock);
+ }
+ swap_info_put(p);
+
+ if (retval) {
+ block_flushpage(page, 0);
+ swap_free(entry);
+ page_cache_release(page);
+ }
+
+ return retval;
+}
+
/*
* Free the swap entry like above, but also try to
* free the page cache entry if it is the last user.
page_cache_get(page);
delete_from_swap_cache(page);
UnlockPage(page);
- free_lru_page(page);
+ page_cache_release(page);
}
}
*/
SetPageDirty(page);
UnlockPage(page);
- free_lru_page(page);
+ page_cache_release(page);
/*
* Make sure that we aren't completely killing