diff options
Diffstat (limited to 'mm/page_isolation.c')
-rw-r--r-- | mm/page_isolation.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/mm/page_isolation.c b/mm/page_isolation.c index c9f04774f2b8..fb482cf438da 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c | |||
@@ -5,8 +5,79 @@ | |||
5 | #include <linux/mm.h> | 5 | #include <linux/mm.h> |
6 | #include <linux/page-isolation.h> | 6 | #include <linux/page-isolation.h> |
7 | #include <linux/pageblock-flags.h> | 7 | #include <linux/pageblock-flags.h> |
8 | #include <linux/memory.h> | ||
8 | #include "internal.h" | 9 | #include "internal.h" |
9 | 10 | ||
11 | int set_migratetype_isolate(struct page *page) | ||
12 | { | ||
13 | struct zone *zone; | ||
14 | unsigned long flags, pfn; | ||
15 | struct memory_isolate_notify arg; | ||
16 | int notifier_ret; | ||
17 | int ret = -EBUSY; | ||
18 | |||
19 | zone = page_zone(page); | ||
20 | |||
21 | spin_lock_irqsave(&zone->lock, flags); | ||
22 | |||
23 | pfn = page_to_pfn(page); | ||
24 | arg.start_pfn = pfn; | ||
25 | arg.nr_pages = pageblock_nr_pages; | ||
26 | arg.pages_found = 0; | ||
27 | |||
28 | /* | ||
29 | * It may be possible to isolate a pageblock even if the | ||
30 | * migratetype is not MIGRATE_MOVABLE. The memory isolation | ||
31 | * notifier chain is used by balloon drivers to return the | ||
32 | * number of pages in a range that are held by the balloon | ||
33 | * driver to shrink memory. If all the pages are accounted for | ||
34 | * by balloons, are free, or on the LRU, isolation can continue. | ||
35 | * Later, for example, when memory hotplug notifier runs, these | ||
36 | * pages reported as "can be isolated" should be isolated(freed) | ||
37 | * by the balloon driver through the memory notifier chain. | ||
38 | */ | ||
39 | notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); | ||
40 | notifier_ret = notifier_to_errno(notifier_ret); | ||
41 | if (notifier_ret) | ||
42 | goto out; | ||
43 | /* | ||
44 | * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. | ||
45 | * We just check MOVABLE pages. | ||
46 | */ | ||
47 | if (!has_unmovable_pages(zone, page, arg.pages_found)) | ||
48 | ret = 0; | ||
49 | |||
50 | /* | ||
51 | * immobile means "not-on-lru" paes. If immobile is larger than | ||
52 | * removable-by-driver pages reported by notifier, we'll fail. | ||
53 | */ | ||
54 | |||
55 | out: | ||
56 | if (!ret) { | ||
57 | set_pageblock_migratetype(page, MIGRATE_ISOLATE); | ||
58 | move_freepages_block(zone, page, MIGRATE_ISOLATE); | ||
59 | } | ||
60 | |||
61 | spin_unlock_irqrestore(&zone->lock, flags); | ||
62 | if (!ret) | ||
63 | drain_all_pages(); | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | void unset_migratetype_isolate(struct page *page, unsigned migratetype) | ||
68 | { | ||
69 | struct zone *zone; | ||
70 | unsigned long flags; | ||
71 | zone = page_zone(page); | ||
72 | spin_lock_irqsave(&zone->lock, flags); | ||
73 | if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE) | ||
74 | goto out; | ||
75 | set_pageblock_migratetype(page, migratetype); | ||
76 | move_freepages_block(zone, page, migratetype); | ||
77 | out: | ||
78 | spin_unlock_irqrestore(&zone->lock, flags); | ||
79 | } | ||
80 | |||
10 | static inline struct page * | 81 | static inline struct page * |
11 | __first_valid_page(unsigned long pfn, unsigned long nr_pages) | 82 | __first_valid_page(unsigned long pfn, unsigned long nr_pages) |
12 | { | 83 | { |