Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 198240
b: refs/heads/master
c: 3fe2011
h: refs/heads/master
v: v3
  • Loading branch information
Mel Gorman authored and Linus Torvalds committed May 25, 2010
1 parent d83e277 commit d751e53
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 18 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 67b9509b2c68ae38cecb83a239881cb0ddf087dc
refs/heads/master: 3fe2011ff51e92500010a495df4be86745fbbda9
53 changes: 36 additions & 17 deletions trunk/mm/migrate.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,8 @@ static int fallback_migrate_page(struct address_space *mapping,
* < 0 - error code
* == 0 - success
*/
static int move_to_new_page(struct page *newpage, struct page *page)
static int move_to_new_page(struct page *newpage, struct page *page,
int remap_swapcache)
{
struct address_space *mapping;
int rc;
Expand Down Expand Up @@ -520,10 +521,12 @@ static int move_to_new_page(struct page *newpage, struct page *page)
else
rc = fallback_migrate_page(mapping, newpage, page);

if (!rc)
remove_migration_ptes(page, newpage);
else
if (rc) {
newpage->mapping = NULL;
} else {
if (remap_swapcache)
remove_migration_ptes(page, newpage);
}

unlock_page(newpage);

Expand All @@ -540,6 +543,7 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
int rc = 0;
int *result = NULL;
struct page *newpage = get_new_page(page, private, &result);
int remap_swapcache = 1;
int rcu_locked = 0;
int charge = 0;
struct mem_cgroup *mem = NULL;
Expand Down Expand Up @@ -601,18 +605,33 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
rcu_read_lock();
rcu_locked = 1;

/*
* If the page has no mappings any more, just bail. An
* unmapped anon page is likely to be freed soon but worse,
* it's possible its anon_vma disappeared between when
* the page was isolated and when we reached here while
* the RCU lock was not held
*/
if (!page_mapped(page))
goto rcu_unlock;
/* Determine how to safely use anon_vma */
if (!page_mapped(page)) {
if (!PageSwapCache(page))
goto rcu_unlock;

anon_vma = page_anon_vma(page);
atomic_inc(&anon_vma->external_refcount);
/*
* We cannot be sure that the anon_vma of an unmapped
* swapcache page is safe to use because we don't
* know in advance if the VMA that this page belonged
* to still exists. If the VMA and others sharing the
* data have been freed, then the anon_vma could
* already be invalid.
*
* To avoid this possibility, swapcache pages get
* migrated but are not remapped when migration
* completes
*/
remap_swapcache = 0;
} else {
/*
* Take a reference count on the anon_vma if the
* page is mapped so that it is guaranteed to
* exist when the page is remapped later
*/
anon_vma = page_anon_vma(page);
atomic_inc(&anon_vma->external_refcount);
}
}

/*
Expand Down Expand Up @@ -647,9 +666,9 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,

skip_unmap:
if (!page_mapped(page))
rc = move_to_new_page(newpage, page);
rc = move_to_new_page(newpage, page, remap_swapcache);

if (rc)
if (rc && remap_swapcache)
remove_migration_ptes(page, page);
rcu_unlock:

Expand Down

0 comments on commit d751e53

Please sign in to comment.