|
@@ -344,7 +344,7 @@ int can_share_swap_page(struct page *page)
|
|
* Work out if there are any other processes sharing this
|
|
* Work out if there are any other processes sharing this
|
|
* swap cache page. Free it if you can. Return success.
|
|
* swap cache page. Free it if you can. Return success.
|
|
*/
|
|
*/
|
|
-int remove_exclusive_swap_page(struct page *page)
|
|
|
|
|
|
+static int remove_exclusive_swap_page_count(struct page *page, int count)
|
|
{
|
|
{
|
|
int retval;
|
|
int retval;
|
|
struct swap_info_struct * p;
|
|
struct swap_info_struct * p;
|
|
@@ -357,7 +357,7 @@ int remove_exclusive_swap_page(struct page *page)
|
|
return 0;
|
|
return 0;
|
|
if (PageWriteback(page))
|
|
if (PageWriteback(page))
|
|
return 0;
|
|
return 0;
|
|
- if (page_count(page) != 2) /* 2: us + cache */
|
|
|
|
|
|
+ if (page_count(page) != count) /* us + cache + ptes */
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
entry.val = page_private(page);
|
|
entry.val = page_private(page);
|
|
@@ -370,7 +370,7 @@ int remove_exclusive_swap_page(struct page *page)
|
|
if (p->swap_map[swp_offset(entry)] == 1) {
|
|
if (p->swap_map[swp_offset(entry)] == 1) {
|
|
/* Recheck the page count with the swapcache lock held.. */
|
|
/* Recheck the page count with the swapcache lock held.. */
|
|
spin_lock_irq(&swapper_space.tree_lock);
|
|
spin_lock_irq(&swapper_space.tree_lock);
|
|
- if ((page_count(page) == 2) && !PageWriteback(page)) {
|
|
|
|
|
|
+ if ((page_count(page) == count) && !PageWriteback(page)) {
|
|
__delete_from_swap_cache(page);
|
|
__delete_from_swap_cache(page);
|
|
SetPageDirty(page);
|
|
SetPageDirty(page);
|
|
retval = 1;
|
|
retval = 1;
|
|
@@ -387,6 +387,25 @@ int remove_exclusive_swap_page(struct page *page)
|
|
return retval;
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Most of the time the page should have two references: one for the
|
|
|
|
+ * process and one for the swap cache.
|
|
|
|
+ */
|
|
|
|
+int remove_exclusive_swap_page(struct page *page)
|
|
|
|
+{
|
|
|
|
+ return remove_exclusive_swap_page_count(page, 2);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * The pageout code holds an extra reference to the page. That raises
|
|
|
|
+ * the reference count to test for to 2 for a page that is only in the
|
|
|
|
+ * swap cache plus 1 for each process that maps the page.
|
|
|
|
+ */
|
|
|
|
+int remove_exclusive_swap_page_ref(struct page *page)
|
|
|
|
+{
|
|
|
|
+ return remove_exclusive_swap_page_count(page, 2 + page_mapcount(page));
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Free the swap entry like above, but also try to
|
|
* Free the swap entry like above, but also try to
|
|
* free the page cache entry if it is the last user.
|
|
* free the page cache entry if it is the last user.
|