Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8351a6e4 authored by Christoph Lameter's avatar Christoph Lameter Committed by Linus Torvalds
Browse files

[PATCH] page migration cleanup: move fallback handling into special function



Move the fallback code into a new fallback function and make the function
behave like any other migration function.  This requires retaking the lock if
pageout() drops it.

Signed-off-by: default avatarChristoph Lameter <clameter@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2d1db3b1
Loading
Loading
Loading
Loading
+39 −51
Original line number Diff line number Diff line
@@ -349,6 +349,42 @@ int buffer_migrate_page(struct address_space *mapping,
}
EXPORT_SYMBOL(buffer_migrate_page);

static int fallback_migrate_page(struct address_space *mapping,
	struct page *newpage, struct page *page)
{
	/*
	 * Default handling if a filesystem does not provide
	 * a migration function. We can only migrate clean
	 * pages so try to write out any dirty pages first.
	 */
	if (PageDirty(page)) {
		switch (pageout(page, mapping)) {
		case PAGE_KEEP:
		case PAGE_ACTIVATE:
			return -EAGAIN;

		case PAGE_SUCCESS:
			/* Relock since we lost the lock */
			lock_page(page);
			/* Must retry since page state may have changed */
			return -EAGAIN;

		case PAGE_CLEAN:
			; /* try to migrate the page below */
		}
	}

	/*
	 * Buffers may be managed in a filesystem specific way.
	 * We must have no buffers or drop them.
	 */
	if (page_has_buffers(page) &&
	    !try_to_release_page(page, GFP_KERNEL))
		return -EAGAIN;

	return migrate_page(mapping, newpage, page);
}

/*
 * migrate_pages
 *
@@ -478,7 +514,7 @@ int migrate_pages(struct list_head *from, struct list_head *to,
		if (!mapping)
			goto unlock_both;

		if (mapping->a_ops->migratepage) {
		if (mapping->a_ops->migratepage)
			/*
			 * Most pages have a mapping and most filesystems
			 * should provide a migration function. Anonymous
@@ -488,56 +524,8 @@ int migrate_pages(struct list_head *from, struct list_head *to,
			 */
			rc = mapping->a_ops->migratepage(mapping,
							newpage, page);
			goto unlock_both;
                }

		/*
		 * Default handling if a filesystem does not provide
		 * a migration function. We can only migrate clean
		 * pages so try to write out any dirty pages first.
		 */
		if (PageDirty(page)) {
			switch (pageout(page, mapping)) {
			case PAGE_KEEP:
			case PAGE_ACTIVATE:
				goto unlock_both;

			case PAGE_SUCCESS:
				unlock_page(newpage);
				goto next;

			case PAGE_CLEAN:
				; /* try to migrate the page below */
			}
                }

		/*
		 * Buffers are managed in a filesystem specific way.
		 * We must have no buffers or drop them.
		 */
		if (!page_has_buffers(page) ||
		    try_to_release_page(page, GFP_KERNEL)) {
			rc = migrate_page(mapping, newpage, page);
			goto unlock_both;
		}

		/*
		 * On early passes with mapped pages simply
		 * retry. There may be a lock held for some
		 * buffers that may go away. Later
		 * swap them out.
		 */
		if (pass > 4) {
			/*
			 * Persistently unable to drop buffers..... As a
			 * measure of last resort we fall back to
			 * swap_page().
			 */
			unlock_page(newpage);
			newpage = NULL;
			rc = swap_page(page);
			goto next;
		}
		else
			rc = fallback_migrate_page(mapping, newpage, page);

unlock_both:
		unlock_page(newpage);