aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/memory.c
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2012-12-11 19:03:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 20:22:28 -0500
commit511c2aba8f07fc45bdcba548cb63f7b8a450c6dc (patch)
tree6a1a853e60e0004f5895d78231ed1bea33fecaac /drivers/base/memory.c
parentfcf07d22f089856631b52a75c35ba3c33b70a1b4 (diff)
mm, memory-hotplug: dynamic configure movable memory and portion memory
Add online_movable and online_kernel for logic memory hotplug. This is the dynamic version of "movablecore" & "kernelcore". We have the same reason to introduce it as to introduce "movablecore" & "kernelcore". It has the same motive as "movablecore" & "kernelcore", but it is dynamic/running-time: o We can configure memory as kernelcore or movablecore after boot. Userspace workload is increased, we need more hugepage, we can't use "online_movable" to add memory and allow the system use more THP(transparent-huge-page), vice-verse when kernel workload is increase. Also help for virtualization to dynamic configure host/guest's memory, to save/(reduce waste) memory. Memory capacity on Demand o When a new node is physically online after boot, we need to use "online_movable" or "online_kernel" to configure/portion it as we expected when we logic-online it. This configuration also helps for physically-memory-migrate. o all benefit as the same as existed "movablecore" & "kernelcore". o Preparing for movable-node, which is very important for power-saving, hardware partitioning and high-available-system(hardware fault management). (Note, we don't introduce movable-node here.) Action behavior: When a memoryblock/memorysection is onlined by "online_movable", the kernel will not have directly reference to the page of the memoryblock, thus we can remove that memory any time when needed. When it is online by "online_kernel", the kernel can use it. When it is online by "online", the zone type doesn't changed. Current constraints: Only the memoryblock which is adjacent to the ZONE_MOVABLE can be online from ZONE_NORMAL to ZONE_MOVABLE. [akpm@linux-foundation.org: use min_t, cleanups] Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Jiang Liu <jiang.liu@huawei.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Minchan Kim <minchan.kim@gmail.com> Cc: Mel Gorman <mgorman@suse.de> Cc: David Rientjes <rientjes@google.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/base/memory.c')
-rw-r--r--drivers/base/memory.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 7eb1211ab688..987604d56c83 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -254,7 +254,7 @@ static bool pages_correctly_reserved(unsigned long start_pfn,
254 * OK to have direct references to sparsemem variables in here. 254 * OK to have direct references to sparsemem variables in here.
255 */ 255 */
256static int 256static int
257memory_block_action(unsigned long phys_index, unsigned long action) 257memory_block_action(unsigned long phys_index, unsigned long action, int online_type)
258{ 258{
259 unsigned long start_pfn; 259 unsigned long start_pfn;
260 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; 260 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
@@ -269,7 +269,7 @@ memory_block_action(unsigned long phys_index, unsigned long action)
269 if (!pages_correctly_reserved(start_pfn, nr_pages)) 269 if (!pages_correctly_reserved(start_pfn, nr_pages))
270 return -EBUSY; 270 return -EBUSY;
271 271
272 ret = online_pages(start_pfn, nr_pages); 272 ret = online_pages(start_pfn, nr_pages, online_type);
273 break; 273 break;
274 case MEM_OFFLINE: 274 case MEM_OFFLINE:
275 ret = offline_pages(start_pfn, nr_pages); 275 ret = offline_pages(start_pfn, nr_pages);
@@ -284,7 +284,8 @@ memory_block_action(unsigned long phys_index, unsigned long action)
284} 284}
285 285
286static int __memory_block_change_state(struct memory_block *mem, 286static int __memory_block_change_state(struct memory_block *mem,
287 unsigned long to_state, unsigned long from_state_req) 287 unsigned long to_state, unsigned long from_state_req,
288 int online_type)
288{ 289{
289 int ret = 0; 290 int ret = 0;
290 291
@@ -296,7 +297,7 @@ static int __memory_block_change_state(struct memory_block *mem,
296 if (to_state == MEM_OFFLINE) 297 if (to_state == MEM_OFFLINE)
297 mem->state = MEM_GOING_OFFLINE; 298 mem->state = MEM_GOING_OFFLINE;
298 299
299 ret = memory_block_action(mem->start_section_nr, to_state); 300 ret = memory_block_action(mem->start_section_nr, to_state, online_type);
300 301
301 if (ret) { 302 if (ret) {
302 mem->state = from_state_req; 303 mem->state = from_state_req;
@@ -319,12 +320,14 @@ out:
319} 320}
320 321
321static int memory_block_change_state(struct memory_block *mem, 322static int memory_block_change_state(struct memory_block *mem,
322 unsigned long to_state, unsigned long from_state_req) 323 unsigned long to_state, unsigned long from_state_req,
324 int online_type)
323{ 325{
324 int ret; 326 int ret;
325 327
326 mutex_lock(&mem->state_mutex); 328 mutex_lock(&mem->state_mutex);
327 ret = __memory_block_change_state(mem, to_state, from_state_req); 329 ret = __memory_block_change_state(mem, to_state, from_state_req,
330 online_type);
328 mutex_unlock(&mem->state_mutex); 331 mutex_unlock(&mem->state_mutex);
329 332
330 return ret; 333 return ret;
@@ -338,10 +341,18 @@ store_mem_state(struct device *dev,
338 341
339 mem = container_of(dev, struct memory_block, dev); 342 mem = container_of(dev, struct memory_block, dev);
340 343
341 if (!strncmp(buf, "online", min((int)count, 6))) 344 if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
342 ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE); 345 ret = memory_block_change_state(mem, MEM_ONLINE,
343 else if(!strncmp(buf, "offline", min((int)count, 7))) 346 MEM_OFFLINE, ONLINE_KERNEL);
344 ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); 347 else if (!strncmp(buf, "online_movable", min_t(int, count, 14)))
348 ret = memory_block_change_state(mem, MEM_ONLINE,
349 MEM_OFFLINE, ONLINE_MOVABLE);
350 else if (!strncmp(buf, "online", min_t(int, count, 6)))
351 ret = memory_block_change_state(mem, MEM_ONLINE,
352 MEM_OFFLINE, ONLINE_KEEP);
353 else if(!strncmp(buf, "offline", min_t(int, count, 7)))
354 ret = memory_block_change_state(mem, MEM_OFFLINE,
355 MEM_ONLINE, -1);
345 356
346 if (ret) 357 if (ret)
347 return ret; 358 return ret;
@@ -676,7 +687,7 @@ int offline_memory_block(struct memory_block *mem)
676 687
677 mutex_lock(&mem->state_mutex); 688 mutex_lock(&mem->state_mutex);
678 if (mem->state != MEM_OFFLINE) 689 if (mem->state != MEM_OFFLINE)
679 ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); 690 ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, -1);
680 mutex_unlock(&mem->state_mutex); 691 mutex_unlock(&mem->state_mutex);
681 692
682 return ret; 693 return ret;