{
struct page **radix_pointer;
+ if (!mapping) {
+ /* Anonymous page */
+ if (page_count(page) != 1)
+ return -EAGAIN;
+ return 0;
+ }
+
write_lock_irq(&mapping->tree_lock);
radix_pointer = (struct page **)radix_tree_lookup_slot(
&mapping->page_tree,
page_index(page));
- if (!page_mapping(page) ||
- page_count(page) != 2 + !!PagePrivate(page) ||
+ if (page_count(page) != 2 + !!PagePrivate(page) ||
*radix_pointer != page) {
write_unlock_irq(&mapping->tree_lock);
return -EAGAIN;
* Now we know that no one else is looking at the page.
*/
get_page(newpage);
+#ifdef CONFIG_SWAP
if (PageSwapCache(page)) {
SetPageSwapCache(newpage);
set_page_private(newpage, page_private(page));
}
+#endif
*radix_pointer = newpage;
__put_page(page);
set_page_dirty(newpage);
}
+#ifdef CONFIG_SWAP
ClearPageSwapCache(page);
+#endif
ClearPageActive(page);
ClearPagePrivate(page);
set_page_private(page, 0);
return rc;
migrate_page_copy(newpage, page);
-
- /*
- * Remove auxiliary swap entries and replace
- * them with real ptes.
- *
- * Note that a real pte entry will allow processes that are not
- * waiting on the page lock to use the new page via the page tables
- * before the new page is unlocked.
- */
- remove_from_swap(newpage);
return 0;
}
EXPORT_SYMBOL(migrate_page);
goto unlock_page;
/*
- * Establish swap ptes for anonymous pages or destroy pte
- * maps for files.
- *
- * In order to reestablish file backed mappings the fault handlers
- * will take the radix tree_lock which may then be used to stop
- * processses from accessing this page until the new page is ready.
- *
- * A process accessing via a swap pte (an anonymous page) will take a
- * page_lock on the old page which will block the process until the
- * migration attempt is complete. At that time the PageSwapCache bit
- * will be examined. If the page was migrated then the PageSwapCache
- * bit will be clear and the operation to retrieve the page will be
- * retried which will find the new page in the radix tree. Then a new
- * direct mapping may be generated based on the radix tree contents.
- *
- * If the page was not migrated then the PageSwapCache bit
- * is still set and the operation may continue.
+ * Establish migration ptes or remove ptes
*/
rc = -EPERM;
if (try_to_unmap(page, 1) == SWAP_FAIL)
*/
mapping = page_mapping(page);
if (!mapping)
- goto unlock_both;
+ rc = migrate_page(mapping, newpage, page);
- if (mapping->a_ops->migratepage)
+ else if (mapping->a_ops->migratepage)
/*
* Most pages have a mapping and most filesystems
* should provide a migration function. Anonymous
else
rc = fallback_migrate_page(mapping, newpage, page);
-unlock_both:
+ if (!rc)
+ remove_migration_ptes(page, newpage);
+
unlock_page(newpage);
unlock_page:
+ if (rc)
+ remove_migration_ptes(page, page);
+
unlock_page(page);
next: