aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2006-02-01 06:05:36 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-01 11:53:16 -0500
commitb16664e44c54525be89dc07ad15a13b4eeec5634 (patch)
tree1844d193009c1e55e3c26256feb14bc622ec9af3
parent2a16e3f4b0c408b9e50297d2ec27e295d490267a (diff)
[PATCH] Direct Migration V9: PageSwapCache checks
Check for PageSwapCache after looking up and locking a swap page. The page migration code may change a swap pte to point to a different page under lock_page(). If that happens then the vm must retry the lookup operation in the swap space to find the correct page number. There are a couple of locations in the VM where a lock_page() is done on a swap page. In these locations we need to check afterwards if the page was migrated. If the page was migrated then the old page that was looked up before was freed and no longer has the PageSwapCache bit set. Signed-off-by: Hirokazu Takahashi <taka@valinux.co.jp> Signed-off-by: Dave Hansen <haveblue@us.ibm.com> Signed-off-by: Christoph Lameter <clameter@@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--mm/memory.c7
-rw-r--r--mm/shmem.c8
-rw-r--r--mm/swapfile.c7
3 files changed, 22 insertions, 0 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 7a11ddd5060f..2bee1f21aa8a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1871,6 +1871,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
1871 goto out; 1871 goto out;
1872 1872
1873 entry = pte_to_swp_entry(orig_pte); 1873 entry = pte_to_swp_entry(orig_pte);
1874again:
1874 page = lookup_swap_cache(entry); 1875 page = lookup_swap_cache(entry);
1875 if (!page) { 1876 if (!page) {
1876 swapin_readahead(entry, address, vma); 1877 swapin_readahead(entry, address, vma);
@@ -1894,6 +1895,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
1894 1895
1895 mark_page_accessed(page); 1896 mark_page_accessed(page);
1896 lock_page(page); 1897 lock_page(page);
1898 if (!PageSwapCache(page)) {
1899 /* Page migration has occured */
1900 unlock_page(page);
1901 page_cache_release(page);
1902 goto again;
1903 }
1897 1904
1898 /* 1905 /*
1899 * Back out if somebody else already faulted in this pte. 1906 * Back out if somebody else already faulted in this pte.
diff --git a/mm/shmem.c b/mm/shmem.c
index ce501bce1c2e..f7ac7b812f92 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1028,6 +1028,14 @@ repeat:
1028 page_cache_release(swappage); 1028 page_cache_release(swappage);
1029 goto repeat; 1029 goto repeat;
1030 } 1030 }
1031 if (!PageSwapCache(swappage)) {
1032 /* Page migration has occured */
1033 shmem_swp_unmap(entry);
1034 spin_unlock(&info->lock);
1035 unlock_page(swappage);
1036 page_cache_release(swappage);
1037 goto repeat;
1038 }
1031 if (PageWriteback(swappage)) { 1039 if (PageWriteback(swappage)) {
1032 shmem_swp_unmap(entry); 1040 shmem_swp_unmap(entry);
1033 spin_unlock(&info->lock); 1041 spin_unlock(&info->lock);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index f1e69c30d203..9678182e0eef 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -646,6 +646,7 @@ static int try_to_unuse(unsigned int type)
646 */ 646 */
647 swap_map = &si->swap_map[i]; 647 swap_map = &si->swap_map[i];
648 entry = swp_entry(type, i); 648 entry = swp_entry(type, i);
649again:
649 page = read_swap_cache_async(entry, NULL, 0); 650 page = read_swap_cache_async(entry, NULL, 0);
650 if (!page) { 651 if (!page) {
651 /* 652 /*
@@ -680,6 +681,12 @@ static int try_to_unuse(unsigned int type)
680 wait_on_page_locked(page); 681 wait_on_page_locked(page);
681 wait_on_page_writeback(page); 682 wait_on_page_writeback(page);
682 lock_page(page); 683 lock_page(page);
684 if (!PageSwapCache(page)) {
685 /* Page migration has occured */
686 unlock_page(page);
687 page_cache_release(page);
688 goto again;
689 }
683 wait_on_page_writeback(page); 690 wait_on_page_writeback(page);
684 691
685 /* 692 /*