Skip to content

Commit

Permalink
[PATCH] Direct Migration V9: PageSwapCache checks
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Lameter authored and Linus Torvalds committed Feb 1, 2006
1 parent 2a16e3f commit b16664e
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 0 deletions.
7 changes: 7 additions & 0 deletions mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
goto out;

entry = pte_to_swp_entry(orig_pte);
again:
page = lookup_swap_cache(entry);
if (!page) {
swapin_readahead(entry, address, vma);
Expand All @@ -1894,6 +1895,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,

mark_page_accessed(page);
lock_page(page);
if (!PageSwapCache(page)) {
/* Page migration has occured */
unlock_page(page);
page_cache_release(page);
goto again;
}

/*
* Back out if somebody else already faulted in this pte.
Expand Down
8 changes: 8 additions & 0 deletions mm/shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,14 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
page_cache_release(swappage);
goto repeat;
}
if (!PageSwapCache(swappage)) {
/* Page migration has occured */
shmem_swp_unmap(entry);
spin_unlock(&info->lock);
unlock_page(swappage);
page_cache_release(swappage);
goto repeat;
}
if (PageWriteback(swappage)) {
shmem_swp_unmap(entry);
spin_unlock(&info->lock);
Expand Down
7 changes: 7 additions & 0 deletions mm/swapfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ static int try_to_unuse(unsigned int type)
*/
swap_map = &si->swap_map[i];
entry = swp_entry(type, i);
again:
page = read_swap_cache_async(entry, NULL, 0);
if (!page) {
/*
Expand Down Expand Up @@ -680,6 +681,12 @@ static int try_to_unuse(unsigned int type)
wait_on_page_locked(page);
wait_on_page_writeback(page);
lock_page(page);
if (!PageSwapCache(page)) {
/* Page migration has occured */
unlock_page(page);
page_cache_release(page);
goto again;
}
wait_on_page_writeback(page);

/*
Expand Down

0 comments on commit b16664e

Please sign in to comment.