aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_isolation.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_isolation.c')
-rw-r--r--mm/page_isolation.c53
1 files changed, 22 insertions, 31 deletions
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index f2f5b4818e94..383bdbb98b04 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -8,29 +8,7 @@
8#include <linux/memory.h> 8#include <linux/memory.h>
9#include "internal.h" 9#include "internal.h"
10 10
11/* called while holding zone->lock */ 11int set_migratetype_isolate(struct page *page, bool skip_hwpoisoned_pages)
12static void set_pageblock_isolate(struct page *page)
13{
14 if (get_pageblock_migratetype(page) == MIGRATE_ISOLATE)
15 return;
16
17 set_pageblock_migratetype(page, MIGRATE_ISOLATE);
18 page_zone(page)->nr_pageblock_isolate++;
19}
20
21/* called while holding zone->lock */
22static void restore_pageblock_isolate(struct page *page, int migratetype)
23{
24 struct zone *zone = page_zone(page);
25 if (WARN_ON(get_pageblock_migratetype(page) != MIGRATE_ISOLATE))
26 return;
27
28 BUG_ON(zone->nr_pageblock_isolate <= 0);
29 set_pageblock_migratetype(page, migratetype);
30 zone->nr_pageblock_isolate--;
31}
32
33int set_migratetype_isolate(struct page *page)
34{ 12{
35 struct zone *zone; 13 struct zone *zone;
36 unsigned long flags, pfn; 14 unsigned long flags, pfn;
@@ -66,7 +44,8 @@ int set_migratetype_isolate(struct page *page)
66 * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. 44 * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
67 * We just check MOVABLE pages. 45 * We just check MOVABLE pages.
68 */ 46 */
69 if (!has_unmovable_pages(zone, page, arg.pages_found)) 47 if (!has_unmovable_pages(zone, page, arg.pages_found,
48 skip_hwpoisoned_pages))
70 ret = 0; 49 ret = 0;
71 50
72 /* 51 /*
@@ -79,7 +58,7 @@ out:
79 unsigned long nr_pages; 58 unsigned long nr_pages;
80 int migratetype = get_pageblock_migratetype(page); 59 int migratetype = get_pageblock_migratetype(page);
81 60
82 set_pageblock_isolate(page); 61 set_pageblock_migratetype(page, MIGRATE_ISOLATE);
83 nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE); 62 nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE);
84 63
85 __mod_zone_freepage_state(zone, -nr_pages, migratetype); 64 __mod_zone_freepage_state(zone, -nr_pages, migratetype);
@@ -102,7 +81,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
102 goto out; 81 goto out;
103 nr_pages = move_freepages_block(zone, page, migratetype); 82 nr_pages = move_freepages_block(zone, page, migratetype);
104 __mod_zone_freepage_state(zone, nr_pages, migratetype); 83 __mod_zone_freepage_state(zone, nr_pages, migratetype);
105 restore_pageblock_isolate(page, migratetype); 84 set_pageblock_migratetype(page, migratetype);
106out: 85out:
107 spin_unlock_irqrestore(&zone->lock, flags); 86 spin_unlock_irqrestore(&zone->lock, flags);
108} 87}
@@ -134,7 +113,7 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages)
134 * Returns 0 on success and -EBUSY if any part of range cannot be isolated. 113 * Returns 0 on success and -EBUSY if any part of range cannot be isolated.
135 */ 114 */
136int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, 115int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
137 unsigned migratetype) 116 unsigned migratetype, bool skip_hwpoisoned_pages)
138{ 117{
139 unsigned long pfn; 118 unsigned long pfn;
140 unsigned long undo_pfn; 119 unsigned long undo_pfn;
@@ -147,7 +126,8 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
147 pfn < end_pfn; 126 pfn < end_pfn;
148 pfn += pageblock_nr_pages) { 127 pfn += pageblock_nr_pages) {
149 page = __first_valid_page(pfn, pageblock_nr_pages); 128 page = __first_valid_page(pfn, pageblock_nr_pages);
150 if (page && set_migratetype_isolate(page)) { 129 if (page &&
130 set_migratetype_isolate(page, skip_hwpoisoned_pages)) {
151 undo_pfn = pfn; 131 undo_pfn = pfn;
152 goto undo; 132 goto undo;
153 } 133 }
@@ -190,7 +170,8 @@ int undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
190 * Returns 1 if all pages in the range are isolated. 170 * Returns 1 if all pages in the range are isolated.
191 */ 171 */
192static int 172static int
193__test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn) 173__test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn,
174 bool skip_hwpoisoned_pages)
194{ 175{
195 struct page *page; 176 struct page *page;
196 177
@@ -220,6 +201,14 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
220 else if (page_count(page) == 0 && 201 else if (page_count(page) == 0 &&
221 get_freepage_migratetype(page) == MIGRATE_ISOLATE) 202 get_freepage_migratetype(page) == MIGRATE_ISOLATE)
222 pfn += 1; 203 pfn += 1;
204 else if (skip_hwpoisoned_pages && PageHWPoison(page)) {
205 /*
206 * The HWPoisoned page may be not in buddy
207 * system, and page_count() is not 0.
208 */
209 pfn++;
210 continue;
211 }
223 else 212 else
224 break; 213 break;
225 } 214 }
@@ -228,7 +217,8 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
228 return 1; 217 return 1;
229} 218}
230 219
231int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn) 220int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
221 bool skip_hwpoisoned_pages)
232{ 222{
233 unsigned long pfn, flags; 223 unsigned long pfn, flags;
234 struct page *page; 224 struct page *page;
@@ -251,7 +241,8 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
251 /* Check all pages are free or Marked as ISOLATED */ 241 /* Check all pages are free or Marked as ISOLATED */
252 zone = page_zone(page); 242 zone = page_zone(page);
253 spin_lock_irqsave(&zone->lock, flags); 243 spin_lock_irqsave(&zone->lock, flags);
254 ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn); 244 ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn,
245 skip_hwpoisoned_pages);
255 spin_unlock_irqrestore(&zone->lock, flags); 246 spin_unlock_irqrestore(&zone->lock, flags);
256 return ret ? 0 : -EBUSY; 247 return ret ? 0 : -EBUSY;
257} 248}