]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.arch/mm-avoid-bad-page-on-lru
Add a patch to fix Intel E100 wake-on-lan problems.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / mm-avoid-bad-page-on-lru
1 From: Russ Anderson <rja@sgi.com>
2 Subject: mm: Avoid putting a bad page back on the LRU v8
3 References: 415829
4 Acked-by: schwab@suse.de
5
6 Prevent a page with a physical memory error from being placed back
7 on the LRU. A new page flag (PG_memerror) is added if
8 CONFIG_PAGEFLAGS_EXTENDED is defined.
9
10 Version 8 change: Removed hot path check for pages with memory
11 errors on the free list.
12
13 Signed-off-by: Russ Anderson <rja@sgi.com>
14 Reviewed-by: Christoph Lameter <cl@linux-foundation.org>
15
16 ---
17 include/linux/page-flags.h | 15 ++++++++++++++-
18 mm/migrate.c | 36 +++++++++++++++++++++++++++++++++++-
19 2 files changed, 49 insertions(+), 2 deletions(-)
20
21 Index: linux/mm/migrate.c
22 ===================================================================
23 --- linux.orig/mm/migrate.c 2008-07-29 13:18:23.000000000 -0500
24 +++ linux/mm/migrate.c 2008-07-29 13:21:03.000000000 -0500
25 @@ -65,6 +65,7 @@ int isolate_lru_page(struct page *page,
26 }
27 return ret;
28 }
29 +EXPORT_SYMBOL(isolate_lru_page);
30
31 /*
32 * migrate_prep() needs to be called before we start compiling a list of pages
33 @@ -82,6 +83,7 @@ int migrate_prep(void)
34
35 return 0;
36 }
37 +EXPORT_SYMBOL(migrate_prep);
38
39 static inline void move_to_lru(struct page *page)
40 {
41 @@ -116,6 +118,7 @@ int putback_lru_pages(struct list_head *
42 }
43 return count;
44 }
45 +EXPORT_SYMBOL(putback_lru_pages);
46
47 /*
48 * Restore a potential migration pte to a working pte entry
49 @@ -741,7 +744,26 @@ unlock:
50 * restored.
51 */
52 list_del(&page->lru);
53 - move_to_lru(page);
54 + if (PageMemError(page)) {
55 + if (rc == 0)
56 + /*
57 + * A page with a memory error that has
58 + * been migrated will not be moved to
59 + * the LRU.
60 + */
61 + goto move_newpage;
62 + else
63 + /*
64 + * The page failed to migrate and will not
65 + * be added to the bad page list. Clearing
66 + * the error bit will allow another attempt
67 + * to migrate if it gets another correctable
68 + * error.
69 + */
70 + ClearPageMemError(page);
71 + }
72 +
73 + move_to_lru(page);
74 }
75
76 move_newpage:
77 @@ -813,6 +835,17 @@ int migrate_pages(struct list_head *from
78 }
79 }
80 }
81 +
82 + if (rc != 0)
83 + list_for_each_entry_safe(page, page2, from, lru)
84 + if (PageMemError(page))
85 + /*
86 + * The page failed to migrate. Clearing
87 + * the error bit will allow another attempt
88 + * to migrate if it gets another correctable
89 + * error.
90 + */
91 + ClearPageMemError(page);
92 rc = 0;
93 out:
94 if (!swapwrite)
95 @@ -825,6 +858,7 @@ out:
96
97 return nr_failed + retry;
98 }
99 +EXPORT_SYMBOL(migrate_pages);
100
101 #ifdef CONFIG_NUMA
102 /*
103 Index: linux/include/linux/page-flags.h
104 ===================================================================
105 --- linux.orig/include/linux/page-flags.h 2008-07-29 13:18:23.000000000 -0500
106 +++ linux/include/linux/page-flags.h 2008-07-29 13:21:03.000000000 -0500
107 @@ -84,6 +84,7 @@ enum pageflags {
108 PG_private, /* If pagecache, has fs-private data */
109 PG_writeback, /* Page is under writeback */
110 #ifdef CONFIG_PAGEFLAGS_EXTENDED
111 + PG_memerror, /* Page has a physical memory error */
112 PG_head, /* A head page */
113 PG_tail, /* A tail page */
114 #else
115 @@ -147,15 +148,21 @@ static inline int TestSetPage##uname(str
116 static inline int TestClearPage##uname(struct page *page) \
117 { return test_and_clear_bit(PG_##lname, &page->flags); }
118
119 +#define PAGEFLAGMASK(uname, lname) \
120 +static inline int PAGEMASK_##uname(void) \
121 + { return (1 << PG_##lname); }
122
123 #define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
124 - SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
125 + SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname) \
126 + PAGEFLAGMASK(uname, lname)
127
128 #define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
129 __SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname)
130
131 #define PAGEFLAG_FALSE(uname) \
132 static inline int Page##uname(struct page *page) \
133 + { return 0; } \
134 +static inline int PAGEMASK_##uname(void) \
135 { return 0; }
136
137 #define TESTSCFLAG(uname, lname) \
138 @@ -325,6 +332,12 @@ static inline void __ClearPageTail(struc
139 }
140
141 #endif /* !PAGEFLAGS_EXTENDED */
142 +
143 +#ifdef CONFIG_PAGEFLAGS_EXTENDED
144 +PAGEFLAG(MemError, memerror)
145 +#else
146 +PAGEFLAG_FALSE(MemError)
147 +#endif
148
149 #define PAGE_FLAGS (1 << PG_lru | 1 << PG_private | 1 << PG_locked | \
150 1 << PG_buddy | 1 << PG_writeback | \