aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Davydov <vdavydov@parallels.com>2014-06-04 19:07:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-04 19:53:59 -0400
commitbfc8c90139ebd049b9801a951db3b9a4a00bed9c (patch)
tree30d900d7f71dec56c0ae5b9e6ba279db3a92e8dd
parente8d9df3abac5d02dd4e6a0041cb62e69189b2c8e (diff)
mem-hotplug: implement get/put_online_mems
kmem_cache_{create,destroy,shrink} need to get a stable value of cpu/node online mask, because they init/destroy/access per-cpu/node kmem_cache parts, which can be allocated or destroyed on cpu/mem hotplug. To protect against cpu hotplug, these functions use {get,put}_online_cpus. However, they do nothing to synchronize with memory hotplug - taking the slab_mutex does not eliminate the possibility of race as described in patch 2. What we need there is something like get_online_cpus, but for memory. We already have lock_memory_hotplug, which serves for the purpose, but it's a bit of a hammer right now, because it's backed by a mutex. As a result, it imposes some limitations to locking order, which are not desirable, and can't be used just like get_online_cpus. That's why in patch 1 I substitute it with get/put_online_mems, which work exactly like get/put_online_cpus except they block not cpu, but memory hotplug. [ v1 can be found at https://lkml.org/lkml/2014/4/6/68. I NAK'ed it by myself, because it used an rw semaphore for get/put_online_mems, making them dead lock prune. ] This patch (of 2): {un}lock_memory_hotplug, which is used to synchronize against memory hotplug, is currently backed by a mutex, which makes it a bit of a hammer - threads that only want to get a stable value of online nodes mask won't be able to proceed concurrently. Also, it imposes some strong locking ordering rules on it, which narrows down the set of its usage scenarios. This patch introduces get/put_online_mems, which are the same as get/put_online_cpus, but for memory hotplug, i.e. executing a code inside a get/put_online_mems section will guarantee a stable value of online nodes, present pages, etc. lock_memory_hotplug()/unlock_memory_hotplug() are removed altogether. Signed-off-by: Vladimir Davydov <vdavydov@parallels.com> Cc: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: Tang Chen <tangchen@cn.fujitsu.com> Cc: Zhang Yanfei <zhangyanfei@cn.fujitsu.com> Cc: Toshi Kani <toshi.kani@hp.com> Cc: Xishi Qiu <qiuxishi@huawei.com> Cc: Jiang Liu <liuj97@gmail.com> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Cc: David Rientjes <rientjes@google.com> Cc: Wen Congyang <wency@cn.fujitsu.com> Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/memory_hotplug.h14
-rw-r--r--include/linux/mmzone.h8
-rw-r--r--mm/kmemleak.c4
-rw-r--r--mm/memory-failure.c8
-rw-r--r--mm/memory_hotplug.c142
-rw-r--r--mm/slub.c4
-rw-r--r--mm/vmscan.c2
7 files changed, 116 insertions, 66 deletions
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 4ca3d951fe91..010d125bffbf 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -187,14 +187,8 @@ extern void put_page_bootmem(struct page *page);
187extern void get_page_bootmem(unsigned long ingo, struct page *page, 187extern void get_page_bootmem(unsigned long ingo, struct page *page,
188 unsigned long type); 188 unsigned long type);
189 189
190/* 190void get_online_mems(void);
191 * Lock for memory hotplug guarantees 1) all callbacks for memory hotplug 191void put_online_mems(void);
192 * notifier will be called under this. 2) offline/online/add/remove memory
193 * will not run simultaneously.
194 */
195
196void lock_memory_hotplug(void);
197void unlock_memory_hotplug(void);
198 192
199#else /* ! CONFIG_MEMORY_HOTPLUG */ 193#else /* ! CONFIG_MEMORY_HOTPLUG */
200/* 194/*
@@ -232,8 +226,8 @@ static inline int try_online_node(int nid)
232 return 0; 226 return 0;
233} 227}
234 228
235static inline void lock_memory_hotplug(void) {} 229static inline void get_online_mems(void) {}
236static inline void unlock_memory_hotplug(void) {} 230static inline void put_online_mems(void) {}
237 231
238#endif /* ! CONFIG_MEMORY_HOTPLUG */ 232#endif /* ! CONFIG_MEMORY_HOTPLUG */
239 233
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index c1dbe0ba9f82..ae693e1ad0f9 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -481,9 +481,8 @@ struct zone {
481 * give them a chance of being in the same cacheline. 481 * give them a chance of being in the same cacheline.
482 * 482 *
483 * Write access to present_pages at runtime should be protected by 483 * Write access to present_pages at runtime should be protected by
484 * lock_memory_hotplug()/unlock_memory_hotplug(). Any reader who can't 484 * mem_hotplug_begin/end(). Any reader who can't tolerant drift of
485 * tolerant drift of present_pages should hold memory hotplug lock to 485 * present_pages should get_online_mems() to get a stable value.
486 * get a stable value.
487 * 486 *
488 * Read access to managed_pages should be safe because it's unsigned 487 * Read access to managed_pages should be safe because it's unsigned
489 * long. Write access to zone->managed_pages and totalram_pages are 488 * long. Write access to zone->managed_pages and totalram_pages are
@@ -765,7 +764,8 @@ typedef struct pglist_data {
765 int node_id; 764 int node_id;
766 wait_queue_head_t kswapd_wait; 765 wait_queue_head_t kswapd_wait;
767 wait_queue_head_t pfmemalloc_wait; 766 wait_queue_head_t pfmemalloc_wait;
768 struct task_struct *kswapd; /* Protected by lock_memory_hotplug() */ 767 struct task_struct *kswapd; /* Protected by
768 mem_hotplug_begin/end() */
769 int kswapd_max_order; 769 int kswapd_max_order;
770 enum zone_type classzone_idx; 770 enum zone_type classzone_idx;
771#ifdef CONFIG_NUMA_BALANCING 771#ifdef CONFIG_NUMA_BALANCING
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 8d2fcdfeff7f..736ade31d1dc 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1300,7 +1300,7 @@ static void kmemleak_scan(void)
1300 /* 1300 /*
1301 * Struct page scanning for each node. 1301 * Struct page scanning for each node.
1302 */ 1302 */
1303 lock_memory_hotplug(); 1303 get_online_mems();
1304 for_each_online_node(i) { 1304 for_each_online_node(i) {
1305 unsigned long start_pfn = node_start_pfn(i); 1305 unsigned long start_pfn = node_start_pfn(i);
1306 unsigned long end_pfn = node_end_pfn(i); 1306 unsigned long end_pfn = node_end_pfn(i);
@@ -1318,7 +1318,7 @@ static void kmemleak_scan(void)
1318 scan_block(page, page + 1, NULL, 1); 1318 scan_block(page, page + 1, NULL, 1);
1319 } 1319 }
1320 } 1320 }
1321 unlock_memory_hotplug(); 1321 put_online_mems();
1322 1322
1323 /* 1323 /*
1324 * Scanning the task stacks (may introduce false negatives). 1324 * Scanning the task stacks (may introduce false negatives).
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 9ccef39a9de2..6917f799412b 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1664,11 +1664,7 @@ int soft_offline_page(struct page *page, int flags)
1664 } 1664 }
1665 } 1665 }
1666 1666
1667 /* 1667 get_online_mems();
1668 * The lock_memory_hotplug prevents a race with memory hotplug.
1669 * This is a big hammer, a better would be nicer.
1670 */
1671 lock_memory_hotplug();
1672 1668
1673 /* 1669 /*
1674 * Isolate the page, so that it doesn't get reallocated if it 1670 * Isolate the page, so that it doesn't get reallocated if it
@@ -1679,7 +1675,7 @@ int soft_offline_page(struct page *page, int flags)
1679 set_migratetype_isolate(page, true); 1675 set_migratetype_isolate(page, true);
1680 1676
1681 ret = get_any_page(page, pfn, flags); 1677 ret = get_any_page(page, pfn, flags);
1682 unlock_memory_hotplug(); 1678 put_online_mems();
1683 if (ret > 0) { /* for in-use pages */ 1679 if (ret > 0) { /* for in-use pages */
1684 if (PageHuge(page)) 1680 if (PageHuge(page))
1685 ret = soft_offline_huge_page(page, flags); 1681 ret = soft_offline_huge_page(page, flags);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index a650db29606f..2906873a1502 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -46,19 +46,84 @@
46static void generic_online_page(struct page *page); 46static void generic_online_page(struct page *page);
47 47
48static online_page_callback_t online_page_callback = generic_online_page; 48static online_page_callback_t online_page_callback = generic_online_page;
49static DEFINE_MUTEX(online_page_callback_lock);
49 50
50DEFINE_MUTEX(mem_hotplug_mutex); 51/* The same as the cpu_hotplug lock, but for memory hotplug. */
52static struct {
53 struct task_struct *active_writer;
54 struct mutex lock; /* Synchronizes accesses to refcount, */
55 /*
56 * Also blocks the new readers during
57 * an ongoing mem hotplug operation.
58 */
59 int refcount;
60
61#ifdef CONFIG_DEBUG_LOCK_ALLOC
62 struct lockdep_map dep_map;
63#endif
64} mem_hotplug = {
65 .active_writer = NULL,
66 .lock = __MUTEX_INITIALIZER(mem_hotplug.lock),
67 .refcount = 0,
68#ifdef CONFIG_DEBUG_LOCK_ALLOC
69 .dep_map = {.name = "mem_hotplug.lock" },
70#endif
71};
72
73/* Lockdep annotations for get/put_online_mems() and mem_hotplug_begin/end() */
74#define memhp_lock_acquire_read() lock_map_acquire_read(&mem_hotplug.dep_map)
75#define memhp_lock_acquire() lock_map_acquire(&mem_hotplug.dep_map)
76#define memhp_lock_release() lock_map_release(&mem_hotplug.dep_map)
77
78void get_online_mems(void)
79{
80 might_sleep();
81 if (mem_hotplug.active_writer == current)
82 return;
83 memhp_lock_acquire_read();
84 mutex_lock(&mem_hotplug.lock);
85 mem_hotplug.refcount++;
86 mutex_unlock(&mem_hotplug.lock);
87
88}
51 89
52void lock_memory_hotplug(void) 90void put_online_mems(void)
53{ 91{
54 mutex_lock(&mem_hotplug_mutex); 92 if (mem_hotplug.active_writer == current)
93 return;
94 mutex_lock(&mem_hotplug.lock);
95
96 if (WARN_ON(!mem_hotplug.refcount))
97 mem_hotplug.refcount++; /* try to fix things up */
98
99 if (!--mem_hotplug.refcount && unlikely(mem_hotplug.active_writer))
100 wake_up_process(mem_hotplug.active_writer);
101 mutex_unlock(&mem_hotplug.lock);
102 memhp_lock_release();
103
55} 104}
56 105
57void unlock_memory_hotplug(void) 106static void mem_hotplug_begin(void)
58{ 107{
59 mutex_unlock(&mem_hotplug_mutex); 108 mem_hotplug.active_writer = current;
109
110 memhp_lock_acquire();
111 for (;;) {
112 mutex_lock(&mem_hotplug.lock);
113 if (likely(!mem_hotplug.refcount))
114 break;
115 __set_current_state(TASK_UNINTERRUPTIBLE);
116 mutex_unlock(&mem_hotplug.lock);
117 schedule();
118 }
60} 119}
61 120
121static void mem_hotplug_done(void)
122{
123 mem_hotplug.active_writer = NULL;
124 mutex_unlock(&mem_hotplug.lock);
125 memhp_lock_release();
126}
62 127
63/* add this memory to iomem resource */ 128/* add this memory to iomem resource */
64static struct resource *register_memory_resource(u64 start, u64 size) 129static struct resource *register_memory_resource(u64 start, u64 size)
@@ -727,14 +792,16 @@ int set_online_page_callback(online_page_callback_t callback)
727{ 792{
728 int rc = -EINVAL; 793 int rc = -EINVAL;
729 794
730 lock_memory_hotplug(); 795 get_online_mems();
796 mutex_lock(&online_page_callback_lock);
731 797
732 if (online_page_callback == generic_online_page) { 798 if (online_page_callback == generic_online_page) {
733 online_page_callback = callback; 799 online_page_callback = callback;
734 rc = 0; 800 rc = 0;
735 } 801 }
736 802
737 unlock_memory_hotplug(); 803 mutex_unlock(&online_page_callback_lock);
804 put_online_mems();
738 805
739 return rc; 806 return rc;
740} 807}
@@ -744,14 +811,16 @@ int restore_online_page_callback(online_page_callback_t callback)
744{ 811{
745 int rc = -EINVAL; 812 int rc = -EINVAL;
746 813
747 lock_memory_hotplug(); 814 get_online_mems();
815 mutex_lock(&online_page_callback_lock);
748 816
749 if (online_page_callback == callback) { 817 if (online_page_callback == callback) {
750 online_page_callback = generic_online_page; 818 online_page_callback = generic_online_page;
751 rc = 0; 819 rc = 0;
752 } 820 }
753 821
754 unlock_memory_hotplug(); 822 mutex_unlock(&online_page_callback_lock);
823 put_online_mems();
755 824
756 return rc; 825 return rc;
757} 826}
@@ -899,7 +968,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
899 int ret; 968 int ret;
900 struct memory_notify arg; 969 struct memory_notify arg;
901 970
902 lock_memory_hotplug(); 971 mem_hotplug_begin();
903 /* 972 /*
904 * This doesn't need a lock to do pfn_to_page(). 973 * This doesn't need a lock to do pfn_to_page().
905 * The section can't be removed here because of the 974 * The section can't be removed here because of the
@@ -907,23 +976,18 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
907 */ 976 */
908 zone = page_zone(pfn_to_page(pfn)); 977 zone = page_zone(pfn_to_page(pfn));
909 978
979 ret = -EINVAL;
910 if ((zone_idx(zone) > ZONE_NORMAL || online_type == ONLINE_MOVABLE) && 980 if ((zone_idx(zone) > ZONE_NORMAL || online_type == ONLINE_MOVABLE) &&
911 !can_online_high_movable(zone)) { 981 !can_online_high_movable(zone))
912 unlock_memory_hotplug(); 982 goto out;
913 return -EINVAL;
914 }
915 983
916 if (online_type == ONLINE_KERNEL && zone_idx(zone) == ZONE_MOVABLE) { 984 if (online_type == ONLINE_KERNEL && zone_idx(zone) == ZONE_MOVABLE) {
917 if (move_pfn_range_left(zone - 1, zone, pfn, pfn + nr_pages)) { 985 if (move_pfn_range_left(zone - 1, zone, pfn, pfn + nr_pages))
918 unlock_memory_hotplug(); 986 goto out;
919 return -EINVAL;
920 }
921 } 987 }
922 if (online_type == ONLINE_MOVABLE && zone_idx(zone) == ZONE_MOVABLE - 1) { 988 if (online_type == ONLINE_MOVABLE && zone_idx(zone) == ZONE_MOVABLE - 1) {
923 if (move_pfn_range_right(zone, zone + 1, pfn, pfn + nr_pages)) { 989 if (move_pfn_range_right(zone, zone + 1, pfn, pfn + nr_pages))
924 unlock_memory_hotplug(); 990 goto out;
925 return -EINVAL;
926 }
927 } 991 }
928 992
929 /* Previous code may changed the zone of the pfn range */ 993 /* Previous code may changed the zone of the pfn range */
@@ -939,8 +1003,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
939 ret = notifier_to_errno(ret); 1003 ret = notifier_to_errno(ret);
940 if (ret) { 1004 if (ret) {
941 memory_notify(MEM_CANCEL_ONLINE, &arg); 1005 memory_notify(MEM_CANCEL_ONLINE, &arg);
942 unlock_memory_hotplug(); 1006 goto out;
943 return ret;
944 } 1007 }
945 /* 1008 /*
946 * If this zone is not populated, then it is not in zonelist. 1009 * If this zone is not populated, then it is not in zonelist.
@@ -964,8 +1027,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
964 (((unsigned long long) pfn + nr_pages) 1027 (((unsigned long long) pfn + nr_pages)
965 << PAGE_SHIFT) - 1); 1028 << PAGE_SHIFT) - 1);
966 memory_notify(MEM_CANCEL_ONLINE, &arg); 1029 memory_notify(MEM_CANCEL_ONLINE, &arg);
967 unlock_memory_hotplug(); 1030 goto out;
968 return ret;
969 } 1031 }
970 1032
971 zone->present_pages += onlined_pages; 1033 zone->present_pages += onlined_pages;
@@ -995,9 +1057,9 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
995 1057
996 if (onlined_pages) 1058 if (onlined_pages)
997 memory_notify(MEM_ONLINE, &arg); 1059 memory_notify(MEM_ONLINE, &arg);
998 unlock_memory_hotplug(); 1060out:
999 1061 mem_hotplug_done();
1000 return 0; 1062 return ret;
1001} 1063}
1002#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ 1064#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
1003 1065
@@ -1055,7 +1117,7 @@ int try_online_node(int nid)
1055 if (node_online(nid)) 1117 if (node_online(nid))
1056 return 0; 1118 return 0;
1057 1119
1058 lock_memory_hotplug(); 1120 mem_hotplug_begin();
1059 pgdat = hotadd_new_pgdat(nid, 0); 1121 pgdat = hotadd_new_pgdat(nid, 0);
1060 if (!pgdat) { 1122 if (!pgdat) {
1061 pr_err("Cannot online node %d due to NULL pgdat\n", nid); 1123 pr_err("Cannot online node %d due to NULL pgdat\n", nid);
@@ -1073,7 +1135,7 @@ int try_online_node(int nid)
1073 } 1135 }
1074 1136
1075out: 1137out:
1076 unlock_memory_hotplug(); 1138 mem_hotplug_done();
1077 return ret; 1139 return ret;
1078} 1140}
1079 1141
@@ -1117,7 +1179,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
1117 new_pgdat = !p; 1179 new_pgdat = !p;
1118 } 1180 }
1119 1181
1120 lock_memory_hotplug(); 1182 mem_hotplug_begin();
1121 1183
1122 new_node = !node_online(nid); 1184 new_node = !node_online(nid);
1123 if (new_node) { 1185 if (new_node) {
@@ -1158,7 +1220,7 @@ error:
1158 release_memory_resource(res); 1220 release_memory_resource(res);
1159 1221
1160out: 1222out:
1161 unlock_memory_hotplug(); 1223 mem_hotplug_done();
1162 return ret; 1224 return ret;
1163} 1225}
1164EXPORT_SYMBOL_GPL(add_memory); 1226EXPORT_SYMBOL_GPL(add_memory);
@@ -1565,7 +1627,7 @@ static int __ref __offline_pages(unsigned long start_pfn,
1565 if (!test_pages_in_a_zone(start_pfn, end_pfn)) 1627 if (!test_pages_in_a_zone(start_pfn, end_pfn))
1566 return -EINVAL; 1628 return -EINVAL;
1567 1629
1568 lock_memory_hotplug(); 1630 mem_hotplug_begin();
1569 1631
1570 zone = page_zone(pfn_to_page(start_pfn)); 1632 zone = page_zone(pfn_to_page(start_pfn));
1571 node = zone_to_nid(zone); 1633 node = zone_to_nid(zone);
@@ -1672,7 +1734,7 @@ repeat:
1672 writeback_set_ratelimit(); 1734 writeback_set_ratelimit();
1673 1735
1674 memory_notify(MEM_OFFLINE, &arg); 1736 memory_notify(MEM_OFFLINE, &arg);
1675 unlock_memory_hotplug(); 1737 mem_hotplug_done();
1676 return 0; 1738 return 0;
1677 1739
1678failed_removal: 1740failed_removal:
@@ -1684,7 +1746,7 @@ failed_removal:
1684 undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE); 1746 undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
1685 1747
1686out: 1748out:
1687 unlock_memory_hotplug(); 1749 mem_hotplug_done();
1688 return ret; 1750 return ret;
1689} 1751}
1690 1752
@@ -1888,7 +1950,7 @@ void __ref remove_memory(int nid, u64 start, u64 size)
1888 1950
1889 BUG_ON(check_hotplug_memory_range(start, size)); 1951 BUG_ON(check_hotplug_memory_range(start, size));
1890 1952
1891 lock_memory_hotplug(); 1953 mem_hotplug_begin();
1892 1954
1893 /* 1955 /*
1894 * All memory blocks must be offlined before removing memory. Check 1956 * All memory blocks must be offlined before removing memory. Check
@@ -1897,10 +1959,8 @@ void __ref remove_memory(int nid, u64 start, u64 size)
1897 */ 1959 */
1898 ret = walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1), NULL, 1960 ret = walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1), NULL,
1899 check_memblock_offlined_cb); 1961 check_memblock_offlined_cb);
1900 if (ret) { 1962 if (ret)
1901 unlock_memory_hotplug();
1902 BUG(); 1963 BUG();
1903 }
1904 1964
1905 /* remove memmap entry */ 1965 /* remove memmap entry */
1906 firmware_map_remove(start, start + size, "System RAM"); 1966 firmware_map_remove(start, start + size, "System RAM");
@@ -1909,7 +1969,7 @@ void __ref remove_memory(int nid, u64 start, u64 size)
1909 1969
1910 try_offline_node(nid); 1970 try_offline_node(nid);
1911 1971
1912 unlock_memory_hotplug(); 1972 mem_hotplug_done();
1913} 1973}
1914EXPORT_SYMBOL_GPL(remove_memory); 1974EXPORT_SYMBOL_GPL(remove_memory);
1915#endif /* CONFIG_MEMORY_HOTREMOVE */ 1975#endif /* CONFIG_MEMORY_HOTREMOVE */
diff --git a/mm/slub.c b/mm/slub.c
index ddb60795f373..9cb2501a2960 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -4332,7 +4332,7 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
4332 } 4332 }
4333 } 4333 }
4334 4334
4335 lock_memory_hotplug(); 4335 get_online_mems();
4336#ifdef CONFIG_SLUB_DEBUG 4336#ifdef CONFIG_SLUB_DEBUG
4337 if (flags & SO_ALL) { 4337 if (flags & SO_ALL) {
4338 for_each_node_state(node, N_NORMAL_MEMORY) { 4338 for_each_node_state(node, N_NORMAL_MEMORY) {
@@ -4372,7 +4372,7 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
4372 x += sprintf(buf + x, " N%d=%lu", 4372 x += sprintf(buf + x, " N%d=%lu",
4373 node, nodes[node]); 4373 node, nodes[node]);
4374#endif 4374#endif
4375 unlock_memory_hotplug(); 4375 put_online_mems();
4376 kfree(nodes); 4376 kfree(nodes);
4377 return x + sprintf(buf + x, "\n"); 4377 return x + sprintf(buf + x, "\n");
4378} 4378}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 7901cb749e17..fbcf46076c4f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3434,7 +3434,7 @@ int kswapd_run(int nid)
3434 3434
3435/* 3435/*
3436 * Called by memory hotplug when all memory in a node is offlined. Caller must 3436 * Called by memory hotplug when all memory in a node is offlined. Caller must
3437 * hold lock_memory_hotplug(). 3437 * hold mem_hotplug_begin/end().
3438 */ 3438 */
3439void kswapd_stop(int nid) 3439void kswapd_stop(int nid)
3440{ 3440{