mm: add_to_swap_cache() must not sleep
[safe/jmp/linux-2.6] / mm / migrate.c
index 5a24923..b535a2c 100644 (file)
@@ -67,6 +67,8 @@ int putback_lru_pages(struct list_head *l)
 
        list_for_each_entry_safe(page, page2, l, lru) {
                list_del(&page->lru);
+               dec_zone_page_state(page, NR_ISOLATED_ANON +
+                                   !!page_is_file_cache(page));
                putback_lru_page(page);
                count++;
        }
@@ -147,7 +149,7 @@ out:
 static void remove_file_migration_ptes(struct page *old, struct page *new)
 {
        struct vm_area_struct *vma;
-       struct address_space *mapping = page_mapping(new);
+       struct address_space *mapping = new->mapping;
        struct prio_tree_iter iter;
        pgoff_t pgoff = new->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
 
@@ -312,7 +314,10 @@ static int migrate_page_move_mapping(struct address_space *mapping,
         */
        __dec_zone_page_state(page, NR_FILE_PAGES);
        __inc_zone_page_state(newpage, NR_FILE_PAGES);
-
+       if (PageSwapBacked(page)) {
+               __dec_zone_page_state(page, NR_SHMEM);
+               __inc_zone_page_state(newpage, NR_SHMEM);
+       }
        spin_unlock_irq(&mapping->tree_lock);
 
        return 0;
@@ -664,13 +669,15 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
                         *    needs to be effective.
                         */
                        try_to_free_buffers(page);
+                       goto rcu_unlock;
                }
-               goto rcu_unlock;
+               goto skip_unmap;
        }
 
        /* Establish migration ptes or remove ptes */
        try_to_unmap(page, 1);
 
+skip_unmap:
        if (!page_mapped(page))
                rc = move_to_new_page(newpage, page);
 
@@ -693,6 +700,8 @@ unlock:
                 * restored.
                 */
                list_del(&page->lru);
+               dec_zone_page_state(page, NR_ISOLATED_ANON +
+                                   !!page_is_file_cache(page));
                putback_lru_page(page);
        }
 
@@ -737,6 +746,13 @@ int migrate_pages(struct list_head *from,
        struct page *page2;
        int swapwrite = current->flags & PF_SWAPWRITE;
        int rc;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       list_for_each_entry(page, from, lru)
+               __inc_zone_page_state(page, NR_ISOLATED_ANON +
+                                     !!page_is_file_cache(page));
+       local_irq_restore(flags);
 
        if (!swapwrite)
                current->flags |= PF_SWAPWRITE;
@@ -820,7 +836,6 @@ static int do_move_page_to_node_array(struct mm_struct *mm,
        struct page_to_node *pp;
        LIST_HEAD(pagelist);
 
-       migrate_prep();
        down_read(&mm->mmap_sem);
 
        /*
@@ -907,6 +922,9 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
        pm = (struct page_to_node *)__get_free_page(GFP_KERNEL);
        if (!pm)
                goto out;
+
+       migrate_prep();
+
        /*
         * Store a chunk of page_to_node array in a page,
         * but keep the last one as a marker