summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:29:58 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:29:58 -0800
commit22a160fb095ca694e9f7ee29f131382e1faec889 (patch)
treea9df773ad9c22327533fc5937546937a33fbee76
parentf97f22cb0b9dca2a797feccc580b3b8fdb238ac3 (diff)
v2.4.13.4 -> v2.4.13.5
- Andrew Morton: remove stale UnlockPage - me: swap cache page locking update
-rw-r--r--include/linux/mm.h15
-rw-r--r--include/linux/pagemap.h2
-rw-r--r--mm/memory.c13
-rw-r--r--mm/swap_state.c5
-rw-r--r--mm/swapfile.c48
5 files changed, 55 insertions, 28 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6cbd7ed4c464..f865aafd1445 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -466,20 +466,7 @@ static inline int is_page_cache_freeable(struct page * page)
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);
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 1fda6fa35b24..5da8ca6af63b 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -29,7 +29,7 @@
#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)
{
diff --git a/mm/memory.c b/mm/memory.c
index df6ffe94f5ff..43316f253583 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -939,9 +939,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
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;
@@ -965,7 +963,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
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
@@ -981,7 +979,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
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:
@@ -989,7 +987,7 @@ 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;
}
@@ -1150,7 +1148,6 @@ static int do_swap_page(struct mm_struct * mm,
*/
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;
@@ -1283,7 +1280,7 @@ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
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;
}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 30d0c085cd6d..4f7b9d6a17e2 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -137,11 +137,10 @@ void free_page_and_swap_cache(struct page *page)
* - 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);
}
/*
diff --git a/mm/swapfile.c b/mm/swapfile.c
index e1f34979e747..002f9849a122 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -224,6 +224,50 @@ void swap_free(swp_entry_t entry)
}
/*
+ * 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.
*/
@@ -242,7 +286,7 @@ void free_swap_and_cache(swp_entry_t entry)
page_cache_get(page);
delete_from_swap_cache(page);
UnlockPage(page);
- free_lru_page(page);
+ page_cache_release(page);
}
}
@@ -582,7 +626,7 @@ static int try_to_unuse(unsigned int type)
*/
SetPageDirty(page);
UnlockPage(page);
- free_lru_page(page);
+ page_cache_release(page);
/*
* Make sure that we aren't completely killing