diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-05-27 06:58:46 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-06-01 15:37:10 -0400 |
commit | 242831eb15a06fa4414eaa705fdc6dd432ab98d1 (patch) | |
tree | 65b57b16800e27b0354ef72a4fe1aecbf8b6d89a | |
parent | 303bfdb1a14d0460feb859cd008ff81da36b517c (diff) |
Memory hotplug / ACPI: Simplify memory removal
Now that the memory offlining should be taken care of by the
companion device offlining code in acpi_scan_hot_remove(), the
ACPI memory hotplug driver doesn't need to offline it in
remove_memory() any more. Moreover, since the return value of
remove_memory() is not used, it's better to make it be a void
function and trigger a BUG() if the memory scheduled for removal is
not offline.
Change the code in accordance with the above observations.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Toshi Kani <toshi.kani@hp.com>
-rw-r--r-- | drivers/acpi/acpi_memhotplug.c | 13 | ||||
-rw-r--r-- | include/linux/memory_hotplug.h | 2 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 71 |
3 files changed, 12 insertions, 74 deletions
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 5590db12028e..c711d1144044 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
@@ -271,13 +271,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) | |||
271 | return 0; | 271 | return 0; |
272 | } | 272 | } |
273 | 273 | ||
274 | static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) | 274 | static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device) |
275 | { | 275 | { |
276 | acpi_handle handle = mem_device->device->handle; | 276 | acpi_handle handle = mem_device->device->handle; |
277 | int result = 0, nid; | ||
278 | struct acpi_memory_info *info, *n; | 277 | struct acpi_memory_info *info, *n; |
279 | 278 | int nid = acpi_get_node(handle); | |
280 | nid = acpi_get_node(handle); | ||
281 | 279 | ||
282 | list_for_each_entry_safe(info, n, &mem_device->res_list, list) { | 280 | list_for_each_entry_safe(info, n, &mem_device->res_list, list) { |
283 | if (!info->enabled) | 281 | if (!info->enabled) |
@@ -287,15 +285,10 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) | |||
287 | nid = memory_add_physaddr_to_nid(info->start_addr); | 285 | nid = memory_add_physaddr_to_nid(info->start_addr); |
288 | 286 | ||
289 | acpi_unbind_memory_blocks(info, handle); | 287 | acpi_unbind_memory_blocks(info, handle); |
290 | result = remove_memory(nid, info->start_addr, info->length); | 288 | remove_memory(nid, info->start_addr, info->length); |
291 | if (result) | ||
292 | return result; | ||
293 | |||
294 | list_del(&info->list); | 289 | list_del(&info->list); |
295 | kfree(info); | 290 | kfree(info); |
296 | } | 291 | } |
297 | |||
298 | return result; | ||
299 | } | 292 | } |
300 | 293 | ||
301 | static void acpi_memory_device_free(struct acpi_memory_device *mem_device) | 294 | static void acpi_memory_device_free(struct acpi_memory_device *mem_device) |
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index ae5480a00963..00569fb4ed6a 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h | |||
@@ -252,7 +252,7 @@ extern int add_memory(int nid, u64 start, u64 size); | |||
252 | extern int arch_add_memory(int nid, u64 start, u64 size); | 252 | extern int arch_add_memory(int nid, u64 start, u64 size); |
253 | extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages); | 253 | extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages); |
254 | extern bool is_memblock_offlined(struct memory_block *mem); | 254 | extern bool is_memblock_offlined(struct memory_block *mem); |
255 | extern int remove_memory(int nid, u64 start, u64 size); | 255 | extern void remove_memory(int nid, u64 start, u64 size); |
256 | extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, | 256 | extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, |
257 | int nr_pages); | 257 | int nr_pages); |
258 | extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms); | 258 | extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms); |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a39841d240e8..7026fbc42aaa 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -1670,24 +1670,6 @@ int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, | |||
1670 | } | 1670 | } |
1671 | 1671 | ||
1672 | #ifdef CONFIG_MEMORY_HOTREMOVE | 1672 | #ifdef CONFIG_MEMORY_HOTREMOVE |
1673 | /** | ||
1674 | * offline_memory_block_cb - callback function for offlining memory block | ||
1675 | * @mem: the memory block to be offlined | ||
1676 | * @arg: buffer to hold error msg | ||
1677 | * | ||
1678 | * Always return 0, and put the error msg in arg if any. | ||
1679 | */ | ||
1680 | static int offline_memory_block_cb(struct memory_block *mem, void *arg) | ||
1681 | { | ||
1682 | int *ret = arg; | ||
1683 | int error = device_offline(&mem->dev); | ||
1684 | |||
1685 | if (error != 0 && *ret == 0) | ||
1686 | *ret = error; | ||
1687 | |||
1688 | return 0; | ||
1689 | } | ||
1690 | |||
1691 | static int is_memblock_offlined_cb(struct memory_block *mem, void *arg) | 1673 | static int is_memblock_offlined_cb(struct memory_block *mem, void *arg) |
1692 | { | 1674 | { |
1693 | int ret = !is_memblock_offlined(mem); | 1675 | int ret = !is_memblock_offlined(mem); |
@@ -1813,54 +1795,22 @@ void try_offline_node(int nid) | |||
1813 | } | 1795 | } |
1814 | EXPORT_SYMBOL(try_offline_node); | 1796 | EXPORT_SYMBOL(try_offline_node); |
1815 | 1797 | ||
1816 | int __ref remove_memory(int nid, u64 start, u64 size) | 1798 | void __ref remove_memory(int nid, u64 start, u64 size) |
1817 | { | 1799 | { |
1818 | unsigned long start_pfn, end_pfn; | 1800 | int ret; |
1819 | int ret = 0; | ||
1820 | int retry = 1; | ||
1821 | |||
1822 | start_pfn = PFN_DOWN(start); | ||
1823 | end_pfn = PFN_UP(start + size - 1); | ||
1824 | |||
1825 | /* | ||
1826 | * When CONFIG_MEMCG is on, one memory block may be used by other | ||
1827 | * blocks to store page cgroup when onlining pages. But we don't know | ||
1828 | * in what order pages are onlined. So we iterate twice to offline | ||
1829 | * memory: | ||
1830 | * 1st iterate: offline every non primary memory block. | ||
1831 | * 2nd iterate: offline primary (i.e. first added) memory block. | ||
1832 | */ | ||
1833 | repeat: | ||
1834 | walk_memory_range(start_pfn, end_pfn, &ret, | ||
1835 | offline_memory_block_cb); | ||
1836 | if (ret) { | ||
1837 | if (!retry) | ||
1838 | return ret; | ||
1839 | |||
1840 | retry = 0; | ||
1841 | ret = 0; | ||
1842 | goto repeat; | ||
1843 | } | ||
1844 | 1801 | ||
1845 | lock_memory_hotplug(); | 1802 | lock_memory_hotplug(); |
1846 | 1803 | ||
1847 | /* | 1804 | /* |
1848 | * we have offlined all memory blocks like this: | 1805 | * All memory blocks must be offlined before removing memory. Check |
1849 | * 1. lock memory hotplug | 1806 | * whether all memory blocks in question are offline and trigger a BUG() |
1850 | * 2. offline a memory block | 1807 | * if this is not the case. |
1851 | * 3. unlock memory hotplug | ||
1852 | * | ||
1853 | * repeat step1-3 to offline the memory block. All memory blocks | ||
1854 | * must be offlined before removing memory. But we don't hold the | ||
1855 | * lock in the whole operation. So we should check whether all | ||
1856 | * memory blocks are offlined. | ||
1857 | */ | 1808 | */ |
1858 | 1809 | ret = walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1), NULL, | |
1859 | ret = walk_memory_range(start_pfn, end_pfn, NULL, | ||
1860 | is_memblock_offlined_cb); | 1810 | is_memblock_offlined_cb); |
1861 | if (ret) { | 1811 | if (ret) { |
1862 | unlock_memory_hotplug(); | 1812 | unlock_memory_hotplug(); |
1863 | return ret; | 1813 | BUG(); |
1864 | } | 1814 | } |
1865 | 1815 | ||
1866 | /* remove memmap entry */ | 1816 | /* remove memmap entry */ |
@@ -1871,17 +1821,12 @@ repeat: | |||
1871 | try_offline_node(nid); | 1821 | try_offline_node(nid); |
1872 | 1822 | ||
1873 | unlock_memory_hotplug(); | 1823 | unlock_memory_hotplug(); |
1874 | |||
1875 | return 0; | ||
1876 | } | 1824 | } |
1877 | #else | 1825 | #else |
1878 | int offline_pages(unsigned long start_pfn, unsigned long nr_pages) | 1826 | int offline_pages(unsigned long start_pfn, unsigned long nr_pages) |
1879 | { | 1827 | { |
1880 | return -EINVAL; | 1828 | return -EINVAL; |
1881 | } | 1829 | } |
1882 | int remove_memory(int nid, u64 start, u64 size) | 1830 | void remove_memory(int nid, u64 start, u64 size) {} |
1883 | { | ||
1884 | return -EINVAL; | ||
1885 | } | ||
1886 | #endif /* CONFIG_MEMORY_HOTREMOVE */ | 1831 | #endif /* CONFIG_MEMORY_HOTREMOVE */ |
1887 | EXPORT_SYMBOL_GPL(remove_memory); | 1832 | EXPORT_SYMBOL_GPL(remove_memory); |