Page blocks might contain references to the next page block. So a page block cannot be offlined independently. E.g. on x86: page block size is 2MB, MAX_ORDER -1 (10) allows 4MB allocations. -> Right now, __offline_isolated_pages() will mark pages in the following page block as reserved. Let document offline_pages() while at it. Signed-off-by: David Hildenbrand <david@xxxxxxxxxx> --- mm/memory_hotplug.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 3a8d56476233..1d6054edc241 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1598,11 +1598,14 @@ static int __ref __offline_pages(unsigned long start_pfn, struct zone *zone; struct memory_notify arg; - /* at least, alignment against pageblock is necessary */ if (!IS_ALIGNED(start_pfn, pageblock_nr_pages)) return -EINVAL; + if (!IS_ALIGNED(start_pfn, (1 << (MAX_ORDER - 1)))) + return -EINVAL; if (!IS_ALIGNED(end_pfn, pageblock_nr_pages)) return -EINVAL; + if (!IS_ALIGNED(end_pfn, (1 << (MAX_ORDER - 1)))) + return -EINVAL; /* This makes hotplug much easier...and readable. we assume this for now. .*/ if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end)) @@ -1699,7 +1702,22 @@ static int __ref __offline_pages(unsigned long start_pfn, return ret; } -/* Must be protected by mem_hotplug_begin() or a device_lock */ +/** + * offline_pages - offline pages in a given range (that are currently online) + * @start_pfn: start pfn of the memory range + * @nr_pages: the number of pages + * + * This function tries to offline the given pages. The alignment/size that + * can be used is max(pageblock_nr_pages, 1 << (MAX_ORDER - 1)). + * + * Returns 0 if sucessful, -EBUSY if the pages cannot be offlined and + * -EINVAL if start_pfn/nr_pages is not properly aligned or not in a zone. + * -EINTR is returned if interrupted by a signal. + * + * Bad things will happen if pages are already offline. + * + * Must be protected by mem_hotplug_begin() or a device_lock + */ int offline_pages(unsigned long start_pfn, unsigned long nr_pages) { return __offline_pages(start_pfn, start_pfn + nr_pages); -- 2.14.3