Commit:     dc386d4d1e98bb39fb967ee156cd456c802fc692
Parent:     098284020c47c1212d211e39ae2b41c21182e056
Author:     KAMEZAWA Hiroyuki <[EMAIL PROTECTED]>
AuthorDate: Thu Jul 26 10:41:07 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Thu Jul 26 11:35:17 2007 -0700

    memory unplug: migration by kernel
    In usual, migrate_pages(page,,) is called with holding mm->sem by system 
    (mm here is a mm_struct which maps the migration target page.)
    This semaphore helps avoiding some race conditions.
    But, if we want to migrate a page by some kernel codes, we have to avoid
    some races. This patch adds check code for following race condition.
    1. A page which page->mapping==NULL can be target of migration. Then, we 
       to check page->mapping before calling try_to_unmap().
    2. anon_vma can be freed while page is unmapped, but page->mapping remains 
       it was. We drop page->mapcount to be 0. Then we cannot trust 
       So, use rcu_read_lock() to prevent anon_vma pointed by page->mapping from
       being freed during migration.
    Signed-off-by: KAMEZAWA Hiroyuki <[EMAIL PROTECTED]>
    Acked-by: Christoph Lameter <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
 mm/migrate.c |   21 +++++++++++++++++++--
 1 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/mm/migrate.c b/mm/migrate.c
index 34d8ada..c8d8722 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -632,18 +632,35 @@ static int unmap_and_move(new_page_t get_new_page, 
unsigned long private,
                        goto unlock;
-        * Establish migration ptes or remove ptes
+        * By try_to_unmap(), page->mapcount goes down to 0 here. In this case,
+        * we cannot notice that anon_vma is freed while we migrates a page.
+        * This rcu_read_lock() delays freeing anon_vma pointer until the end
+        * of migration. File cache pages are no problem because of page_lock()
+        */
+       rcu_read_lock();
+       /*
+        * This is a corner case handling.
+        * When a new swap-cache is read into, it is linked to LRU
+        * and treated as swapcache but has no rmap yet.
+        * Calling try_to_unmap() against a page->mapping==NULL page is
+        * BUG. So handle it here.
+       if (!page->mapping)
+               goto rcu_unlock;
+       /* Establish migration ptes or remove ptes */
        try_to_unmap(page, 1);
        if (!page_mapped(page))
                rc = move_to_new_page(newpage, page);
        if (rc)
                remove_migration_ptes(page, page);
+       rcu_read_unlock();
        if (rc != -EAGAIN) {
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to