]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - mm/memory_hotplug.c
drivers, usb: convert dev_data.count from atomic_t to refcount_t
[karo-tx-linux.git] / mm / memory_hotplug.c
index d67787d10ff0e9c4e068beb819daf4761947be04..295479b792ec488b6d984ef98e7e715f6ac162b4 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/stddef.h>
 #include <linux/mm.h>
+#include <linux/sched/signal.h>
 #include <linux/swap.h>
 #include <linux/interrupt.h>
 #include <linux/pagemap.h>
@@ -126,6 +127,8 @@ void put_online_mems(void)
 
 void mem_hotplug_begin(void)
 {
+       assert_held_device_hotplug();
+
        mem_hotplug.active_writer = current;
 
        memhp_lock_acquire();
@@ -862,7 +865,6 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(__remove_pages);
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
 int set_online_page_callback(online_page_callback_t callback)
@@ -1336,7 +1338,7 @@ int zone_for_memory(int nid, u64 start, u64 size, int zone_default,
 
 static int online_memory_block(struct memory_block *mem, void *arg)
 {
-       return memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
+       return device_online(&mem->dev);
 }
 
 /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
@@ -1508,7 +1510,7 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
                        while ((i < MAX_ORDER_NR_PAGES) &&
                                !pfn_valid_within(pfn + i))
                                i++;
-                       if (i == MAX_ORDER_NR_PAGES)
+                       if (i == MAX_ORDER_NR_PAGES || pfn + i >= end_pfn)
                                continue;
                        page = pfn_to_page(pfn + i);
                        if (zone && page_zone(page) != zone)
@@ -1522,7 +1524,7 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
 
        if (zone) {
                *valid_start = start;
-               *valid_end = end;
+               *valid_end = min(end, end_pfn);
                return 1;
        } else {
                return 0;
@@ -1530,10 +1532,10 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
 }
 
 /*
- * Scan pfn range [start,end) to find movable/migratable pages (LRU pages
- * and hugepages). We scan pfn because it's much easier than scanning over
- * linked list. This function returns the pfn of the first found movable
- * page if it's found, otherwise 0.
+ * Scan pfn range [start,end) to find movable/migratable pages (LRU pages,
+ * non-lru movable pages and hugepages). We scan pfn because it's much
+ * easier than scanning over linked list. This function returns the pfn
+ * of the first found movable page if it's found, otherwise 0.
  */
 static unsigned long scan_movable_pages(unsigned long start, unsigned long end)
 {
@@ -1544,6 +1546,8 @@ static unsigned long scan_movable_pages(unsigned long start, unsigned long end)
                        page = pfn_to_page(pfn);
                        if (PageLRU(page))
                                return pfn;
+                       if (__PageMovable(page))
+                               return pfn;
                        if (PageHuge(page)) {
                                if (page_huge_active(page))
                                        return pfn;
@@ -1620,21 +1624,25 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                if (!get_page_unless_zero(page))
                        continue;
                /*
-                * We can skip free pages. And we can only deal with pages on
-                * LRU.
+                * We can skip free pages. And we can deal with pages on
+                * LRU and non-lru movable pages.
                 */
-               ret = isolate_lru_page(page);
+               if (PageLRU(page))
+                       ret = isolate_lru_page(page);
+               else
+                       ret = isolate_movable_page(page, ISOLATE_UNEVICTABLE);
                if (!ret) { /* Success */
                        put_page(page);
                        list_add_tail(&page->lru, &source);
                        move_pages--;
-                       inc_node_page_state(page, NR_ISOLATED_ANON +
-                                           page_is_file_cache(page));
+                       if (!__PageMovable(page))
+                               inc_node_page_state(page, NR_ISOLATED_ANON +
+                                                   page_is_file_cache(page));
 
                } else {
 #ifdef CONFIG_DEBUG_VM
-                       pr_alert("removing pfn %lx from LRU failed\n", pfn);
-                       dump_page(page, "failed to remove from LRU");
+                       pr_alert("failed to isolate pfn %lx\n", pfn);
+                       dump_page(page, "isolation failed");
 #endif
                        put_page(page);
                        /* Because we don't have big zone->lock. we should