--- /dev/null
+From: Russ Anderson <rja@sgi.com>
+Subject: mm: Avoid putting a bad page back on the LRU v8
+References: 415829
+Acked-by: schwab@suse.de
+
+Prevent a page with a physical memory error from being placed back
+on the LRU. A new page flag (PG_memerror) is added if
+CONFIG_PAGEFLAGS_EXTENDED is defined.
+
+Version 8 change: Removed hot path check for pages with memory
+errors on the free list.
+
+Signed-off-by: Russ Anderson <rja@sgi.com>
+Reviewed-by: Christoph Lameter <cl@linux-foundation.org>
+
+---
+ include/linux/page-flags.h | 15 ++++++++++++++-
+ mm/migrate.c | 36 +++++++++++++++++++++++++++++++++++-
+ 2 files changed, 49 insertions(+), 2 deletions(-)
+
+Index: linux/mm/migrate.c
+===================================================================
+--- linux.orig/mm/migrate.c 2008-07-29 13:18:23.000000000 -0500
++++ linux/mm/migrate.c 2008-07-29 13:21:03.000000000 -0500
+@@ -65,6 +65,7 @@ int isolate_lru_page(struct page *page,
+ }
+ return ret;
+ }
++EXPORT_SYMBOL(isolate_lru_page);
+
+ /*
+ * migrate_prep() needs to be called before we start compiling a list of pages
+@@ -82,6 +83,7 @@ int migrate_prep(void)
+
+ return 0;
+ }
++EXPORT_SYMBOL(migrate_prep);
+
+ static inline void move_to_lru(struct page *page)
+ {
+@@ -116,6 +118,7 @@ int putback_lru_pages(struct list_head *
+ }
+ return count;
+ }
++EXPORT_SYMBOL(putback_lru_pages);
+
+ /*
+ * Restore a potential migration pte to a working pte entry
+@@ -741,7 +744,26 @@ unlock:
+ * restored.
+ */
+ list_del(&page->lru);
+- move_to_lru(page);
++ if (PageMemError(page)) {
++ if (rc == 0)
++ /*
++ * A page with a memory error that has
++ * been migrated will not be moved to
++ * the LRU.
++ */
++ goto move_newpage;
++ else
++ /*
++ * The page failed to migrate and will not
++ * be added to the bad page list. Clearing
++ * the error bit will allow another attempt
++ * to migrate if it gets another correctable
++ * error.
++ */
++ ClearPageMemError(page);
++ }
++
++ move_to_lru(page);
+ }
+
+ move_newpage:
+@@ -813,6 +835,17 @@ int migrate_pages(struct list_head *from
+ }
+ }
+ }
++
++ if (rc != 0)
++ list_for_each_entry_safe(page, page2, from, lru)
++ if (PageMemError(page))
++ /*
++ * The page failed to migrate. Clearing
++ * the error bit will allow another attempt
++ * to migrate if it gets another correctable
++ * error.
++ */
++ ClearPageMemError(page);
+ rc = 0;
+ out:
+ if (!swapwrite)
+@@ -825,6 +858,7 @@ out:
+
+ return nr_failed + retry;
+ }
++EXPORT_SYMBOL(migrate_pages);
+
+ #ifdef CONFIG_NUMA
+ /*
+Index: linux/include/linux/page-flags.h
+===================================================================
+--- linux.orig/include/linux/page-flags.h 2008-07-29 13:18:23.000000000 -0500
++++ linux/include/linux/page-flags.h 2008-07-29 13:21:03.000000000 -0500
+@@ -84,6 +84,7 @@ enum pageflags {
+ PG_private, /* If pagecache, has fs-private data */
+ PG_writeback, /* Page is under writeback */
+ #ifdef CONFIG_PAGEFLAGS_EXTENDED
++ PG_memerror, /* Page has a physical memory error */
+ PG_head, /* A head page */
+ PG_tail, /* A tail page */
+ #else
+@@ -147,15 +148,21 @@ static inline int TestSetPage##uname(str
+ static inline int TestClearPage##uname(struct page *page) \
+ { return test_and_clear_bit(PG_##lname, &page->flags); }
+
++#define PAGEFLAGMASK(uname, lname) \
++static inline int PAGEMASK_##uname(void) \
++ { return (1 << PG_##lname); }
+
+ #define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
+- SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
++ SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname) \
++ PAGEFLAGMASK(uname, lname)
+
+ #define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
+ __SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname)
+
+ #define PAGEFLAG_FALSE(uname) \
+ static inline int Page##uname(struct page *page) \
++ { return 0; } \
++static inline int PAGEMASK_##uname(void) \
+ { return 0; }
+
+ #define TESTSCFLAG(uname, lname) \
+@@ -325,6 +332,12 @@ static inline void __ClearPageTail(struc
+ }
+
+ #endif /* !PAGEFLAGS_EXTENDED */
++
++#ifdef CONFIG_PAGEFLAGS_EXTENDED
++PAGEFLAG(MemError, memerror)
++#else
++PAGEFLAG_FALSE(MemError)
++#endif
+
+ #define PAGE_FLAGS (1 << PG_lru | 1 << PG_private | 1 << PG_locked | \
+ 1 << PG_buddy | 1 << PG_writeback | \