Currently, all newly added memory blocks remain in 'offline' state unless someone onlines them, some linux distributions carry special udev rules like: SUBSYSTEM=="memory", ACTION=="add", ATTR{state}=="offline", ATTR{state}="online" to make this happen automatically. This is not a great solution for virtual machines where memory hotplug is being used to address high memory pressure situations as such onlining is slow and a userspace process doing this (udev) has a chance of being killed by the OOM killer as it will probably require to allocate some memory. Introduce default policy for the newly added memory blocks in /sys/devices/system/memory/hotplug_autoonline file with two possible values: "offline" (the default) which preserves the current behavior and "online" which causes all newly added memory blocks to go online as soon as they're added. Cc: Jonathan Corbet <corbet@xxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> Cc: Daniel Kiper <daniel.kiper@xxxxxxxxxx> Cc: Dan Williams <dan.j.williams@xxxxxxxxx> Cc: Tang Chen <tangchen@xxxxxxxxxxxxxx> Cc: David Vrabel <david.vrabel@xxxxxxxxxx> Cc: David Rientjes <rientjes@xxxxxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Naoya Horiguchi <n-horiguchi@xxxxxxxxxxxxx> Cc: Gu Zheng <guz.fnst@xxxxxxxxxxxxxx> Cc: Xishi Qiu <qiuxishi@xxxxxxxxxx> Cc: Mel Gorman <mgorman@xxxxxxxxxxxxxxxxxxx> Cc: "K. Y. Srinivasan" <kys@xxxxxxxxxxxxx> Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> --- - I was able to find previous attempts to fix the issue, e.g.: http://marc.info/?l=linux-kernel&m=137425951924598&w=2 http://marc.info/?l=linux-acpi&m=127186488905382 but I'm not completely sure why it didn't work out and the solution I suggest is not 'smart enough', thus 'RFC'. --- Documentation/memory-hotplug.txt | 21 +++++++++++++++++---- drivers/base/memory.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/memory_hotplug.h | 2 ++ mm/memory_hotplug.c | 8 ++++++++ 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt index ce2cfcf..fe576d9 100644 --- a/Documentation/memory-hotplug.txt +++ b/Documentation/memory-hotplug.txt @@ -254,12 +254,25 @@ If the memory block is online, you'll read "online". If the memory block is offline, you'll read "offline". -5.2. How to online memory +5.2. Memory onlining ------------ -Even if the memory is hot-added, it is not at ready-to-use state. -For using newly added memory, you have to "online" the memory block. +When the memory is hot-added, the kernel decides whether or not to "online" +it according to the policy which can be read from "hotplug_autoonline" file: -For onlining, you have to write "online" to the memory block's state file as: +% cat /sys/devices/system/memory/hotplug_autoonline + +The default is "offline" which means the newly added memory will not be at +ready-to-use state and you have to "online" the newly added memory blocks +manually. + +Automatic onlining can be requested by writing "online" to "hotplug_autoonline" +file: + +% echo online > /sys/devices/system/memory/hotplug_autoonline + +If the automatic onlining wasn't requested or some memory block was offlined +it is possible to change the individual block's state by writing to the "state" +file: % echo online > /sys/devices/system/memory/memoryXXX/state diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 25425d3..001fefe 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -438,6 +438,40 @@ print_block_size(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(block_size_bytes, 0444, print_block_size, NULL); + +/* + * Memory auto online policy. + */ + +static ssize_t +show_memhp_autoonline(struct device *dev, struct device_attribute *attr, + char *buf) +{ + if (memhp_autoonline == MMOP_ONLINE_KEEP) + return sprintf(buf, "online\n"); + else if (memhp_autoonline == MMOP_OFFLINE) + return sprintf(buf, "offline\n"); + else + return sprintf(buf, "unknown\n"); +} + +static ssize_t +store_memhp_autoonline(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + if (sysfs_streq(buf, "online")) + memhp_autoonline = MMOP_ONLINE_KEEP; + else if (sysfs_streq(buf, "offline")) + memhp_autoonline = MMOP_OFFLINE; + else + return -EINVAL; + + return count; +} + +static DEVICE_ATTR(hotplug_autoonline, 0644, show_memhp_autoonline, + store_memhp_autoonline); + /* * Some architectures will have custom drivers to do this, and * will not need to do it from userspace. The fake hot-add code @@ -737,6 +771,7 @@ static struct attribute *memory_root_attrs[] = { #endif &dev_attr_block_size_bytes.attr, + &dev_attr_hotplug_autoonline.attr, NULL }; diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 2ea574f..fb64eea 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -99,6 +99,8 @@ extern void __online_page_free(struct page *page); extern int try_online_node(int nid); +extern int memhp_autoonline; + #ifdef CONFIG_MEMORY_HOTREMOVE extern bool is_pageblock_removable_nolock(struct page *page); extern int arch_remove_memory(u64 start, u64 size); diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 67d488a..37a190e 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -76,6 +76,9 @@ static struct { #define memhp_lock_acquire() lock_map_acquire(&mem_hotplug.dep_map) #define memhp_lock_release() lock_map_release(&mem_hotplug.dep_map) +int memhp_autoonline = MMOP_OFFLINE; +EXPORT_SYMBOL_GPL(memhp_autoonline); + void get_online_mems(void) { might_sleep(); @@ -1292,6 +1295,11 @@ int __ref add_memory_resource(int nid, struct resource *res) /* create new memmap entry */ firmware_map_add_hotplug(start, start + size, "System RAM"); + /* online the region if it is requested by current policy */ + if (memhp_autoonline != MMOP_OFFLINE) + online_pages(start >> PAGE_SHIFT, size >> PAGE_SHIFT, + memhp_autoonline); + goto out; error: -- 2.4.3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>