aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 21:05:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 21:05:37 -0500
commit608ff1a210ab0e8b969399039bf8e18693605910 (patch)
treefaea7bb1764461c73d0953089bd5439d91733a03 /drivers/base
parent414a6750e59b0b687034764c464e9ddecac0f7a6 (diff)
parent74d42d8fe146e870c52bde3b1c692f86cc8ff844 (diff)
Merge branch 'akpm' (Andrew's patchbomb)
Merge misc updates from Andrew Morton: "About half of most of MM. Going very early this time due to uncertainty over the coreautounifiednumasched things. I'll send the other half of most of MM tomorrow. The rest of MM awaits a slab merge from Pekka." * emailed patches from Andrew Morton: (71 commits) memory_hotplug: ensure every online node has NORMAL memory memory_hotplug: handle empty zone when online_movable/online_kernel mm, memory-hotplug: dynamic configure movable memory and portion memory drivers/base/node.c: cleanup node_state_attr[] bootmem: fix wrong call parameter for free_bootmem() avr32, kconfig: remove HAVE_ARCH_BOOTMEM mm: cma: remove watermark hacks mm: cma: skip watermarks check for already isolated blocks in split_free_page() mm, oom: fix race when specifying a thread as the oom origin mm, oom: change type of oom_score_adj to short mm: cleanup register_node() mm, mempolicy: remove duplicate code mm/vmscan.c: try_to_freeze() returns boolean mm: introduce putback_movable_pages() virtio_balloon: introduce migration primitives to balloon pages mm: introduce compaction and migration for ballooned pages mm: introduce a common interface for balloon pages mobility mm: redefine address_space.assoc_mapping mm: adjust address_space_operations.migratepage() return code arch/sparc/kernel/sys_sparc_64.c: s/COLOUR/COLOR/ ...
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/memory.c42
-rw-r--r--drivers/base/node.c78
2 files changed, 81 insertions, 39 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 86c88216a503..987604d56c83 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -70,6 +70,13 @@ void unregister_memory_isolate_notifier(struct notifier_block *nb)
70} 70}
71EXPORT_SYMBOL(unregister_memory_isolate_notifier); 71EXPORT_SYMBOL(unregister_memory_isolate_notifier);
72 72
73static void memory_block_release(struct device *dev)
74{
75 struct memory_block *mem = container_of(dev, struct memory_block, dev);
76
77 kfree(mem);
78}
79
73/* 80/*
74 * register_memory - Setup a sysfs device for a memory block 81 * register_memory - Setup a sysfs device for a memory block
75 */ 82 */
@@ -80,6 +87,7 @@ int register_memory(struct memory_block *memory)
80 87
81 memory->dev.bus = &memory_subsys; 88 memory->dev.bus = &memory_subsys;
82 memory->dev.id = memory->start_section_nr / sections_per_block; 89 memory->dev.id = memory->start_section_nr / sections_per_block;
90 memory->dev.release = memory_block_release;
83 91
84 error = device_register(&memory->dev); 92 error = device_register(&memory->dev);
85 return error; 93 return error;
@@ -246,7 +254,7 @@ static bool pages_correctly_reserved(unsigned long start_pfn,
246 * OK to have direct references to sparsemem variables in here. 254 * OK to have direct references to sparsemem variables in here.
247 */ 255 */
248static int 256static int
249memory_block_action(unsigned long phys_index, unsigned long action) 257memory_block_action(unsigned long phys_index, unsigned long action, int online_type)
250{ 258{
251 unsigned long start_pfn; 259 unsigned long start_pfn;
252 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; 260 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
@@ -261,7 +269,7 @@ memory_block_action(unsigned long phys_index, unsigned long action)
261 if (!pages_correctly_reserved(start_pfn, nr_pages)) 269 if (!pages_correctly_reserved(start_pfn, nr_pages))
262 return -EBUSY; 270 return -EBUSY;
263 271
264 ret = online_pages(start_pfn, nr_pages); 272 ret = online_pages(start_pfn, nr_pages, online_type);
265 break; 273 break;
266 case MEM_OFFLINE: 274 case MEM_OFFLINE:
267 ret = offline_pages(start_pfn, nr_pages); 275 ret = offline_pages(start_pfn, nr_pages);
@@ -276,7 +284,8 @@ memory_block_action(unsigned long phys_index, unsigned long action)
276} 284}
277 285
278static int __memory_block_change_state(struct memory_block *mem, 286static int __memory_block_change_state(struct memory_block *mem,
279 unsigned long to_state, unsigned long from_state_req) 287 unsigned long to_state, unsigned long from_state_req,
288 int online_type)
280{ 289{
281 int ret = 0; 290 int ret = 0;
282 291
@@ -288,7 +297,7 @@ static int __memory_block_change_state(struct memory_block *mem,
288 if (to_state == MEM_OFFLINE) 297 if (to_state == MEM_OFFLINE)
289 mem->state = MEM_GOING_OFFLINE; 298 mem->state = MEM_GOING_OFFLINE;
290 299
291 ret = memory_block_action(mem->start_section_nr, to_state); 300 ret = memory_block_action(mem->start_section_nr, to_state, online_type);
292 301
293 if (ret) { 302 if (ret) {
294 mem->state = from_state_req; 303 mem->state = from_state_req;
@@ -311,12 +320,14 @@ out:
311} 320}
312 321
313static int memory_block_change_state(struct memory_block *mem, 322static int memory_block_change_state(struct memory_block *mem,
314 unsigned long to_state, unsigned long from_state_req) 323 unsigned long to_state, unsigned long from_state_req,
324 int online_type)
315{ 325{
316 int ret; 326 int ret;
317 327
318 mutex_lock(&mem->state_mutex); 328 mutex_lock(&mem->state_mutex);
319 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);
320 mutex_unlock(&mem->state_mutex); 331 mutex_unlock(&mem->state_mutex);
321 332
322 return ret; 333 return ret;
@@ -330,10 +341,18 @@ store_mem_state(struct device *dev,
330 341
331 mem = container_of(dev, struct memory_block, dev); 342 mem = container_of(dev, struct memory_block, dev);
332 343
333 if (!strncmp(buf, "online", min((int)count, 6))) 344 if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
334 ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE); 345 ret = memory_block_change_state(mem, MEM_ONLINE,
335 else if(!strncmp(buf, "offline", min((int)count, 7))) 346 MEM_OFFLINE, ONLINE_KERNEL);
336 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);
337 356
338 if (ret) 357 if (ret)
339 return ret; 358 return ret;
@@ -635,7 +654,6 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
635 mem_remove_simple_file(mem, phys_device); 654 mem_remove_simple_file(mem, phys_device);
636 mem_remove_simple_file(mem, removable); 655 mem_remove_simple_file(mem, removable);
637 unregister_memory(mem); 656 unregister_memory(mem);
638 kfree(mem);
639 } else 657 } else
640 kobject_put(&mem->dev.kobj); 658 kobject_put(&mem->dev.kobj);
641 659
@@ -669,7 +687,7 @@ int offline_memory_block(struct memory_block *mem)
669 687
670 mutex_lock(&mem->state_mutex); 688 mutex_lock(&mem->state_mutex);
671 if (mem->state != MEM_OFFLINE) 689 if (mem->state != MEM_OFFLINE)
672 ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); 690 ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, -1);
673 mutex_unlock(&mem->state_mutex); 691 mutex_unlock(&mem->state_mutex);
674 692
675 return ret; 693 return ret;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index af1a177216f1..294e31626210 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -252,6 +252,24 @@ static inline void hugetlb_register_node(struct node *node) {}
252static inline void hugetlb_unregister_node(struct node *node) {} 252static inline void hugetlb_unregister_node(struct node *node) {}
253#endif 253#endif
254 254
255static void node_device_release(struct device *dev)
256{
257 struct node *node = to_node(dev);
258
259#if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS)
260 /*
261 * We schedule the work only when a memory section is
262 * onlined/offlined on this node. When we come here,
263 * all the memory on this node has been offlined,
264 * so we won't enqueue new work to this work.
265 *
266 * The work is using node->node_work, so we should
267 * flush work before freeing the memory.
268 */
269 flush_work(&node->node_work);
270#endif
271 kfree(node);
272}
255 273
256/* 274/*
257 * register_node - Setup a sysfs device for a node. 275 * register_node - Setup a sysfs device for a node.
@@ -259,12 +277,13 @@ static inline void hugetlb_unregister_node(struct node *node) {}
259 * 277 *
260 * Initialize and register the node device. 278 * Initialize and register the node device.
261 */ 279 */
262int register_node(struct node *node, int num, struct node *parent) 280static int register_node(struct node *node, int num, struct node *parent)
263{ 281{
264 int error; 282 int error;
265 283
266 node->dev.id = num; 284 node->dev.id = num;
267 node->dev.bus = &node_subsys; 285 node->dev.bus = &node_subsys;
286 node->dev.release = node_device_release;
268 error = device_register(&node->dev); 287 error = device_register(&node->dev);
269 288
270 if (!error){ 289 if (!error){
@@ -306,7 +325,7 @@ void unregister_node(struct node *node)
306 device_unregister(&node->dev); 325 device_unregister(&node->dev);
307} 326}
308 327
309struct node node_devices[MAX_NUMNODES]; 328struct node *node_devices[MAX_NUMNODES];
310 329
311/* 330/*
312 * register cpu under node 331 * register cpu under node
@@ -323,15 +342,15 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
323 if (!obj) 342 if (!obj)
324 return 0; 343 return 0;
325 344
326 ret = sysfs_create_link(&node_devices[nid].dev.kobj, 345 ret = sysfs_create_link(&node_devices[nid]->dev.kobj,
327 &obj->kobj, 346 &obj->kobj,
328 kobject_name(&obj->kobj)); 347 kobject_name(&obj->kobj));
329 if (ret) 348 if (ret)
330 return ret; 349 return ret;
331 350
332 return sysfs_create_link(&obj->kobj, 351 return sysfs_create_link(&obj->kobj,
333 &node_devices[nid].dev.kobj, 352 &node_devices[nid]->dev.kobj,
334 kobject_name(&node_devices[nid].dev.kobj)); 353 kobject_name(&node_devices[nid]->dev.kobj));
335} 354}
336 355
337int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) 356int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
@@ -345,10 +364,10 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
345 if (!obj) 364 if (!obj)
346 return 0; 365 return 0;
347 366
348 sysfs_remove_link(&node_devices[nid].dev.kobj, 367 sysfs_remove_link(&node_devices[nid]->dev.kobj,
349 kobject_name(&obj->kobj)); 368 kobject_name(&obj->kobj));
350 sysfs_remove_link(&obj->kobj, 369 sysfs_remove_link(&obj->kobj,
351 kobject_name(&node_devices[nid].dev.kobj)); 370 kobject_name(&node_devices[nid]->dev.kobj));
352 371
353 return 0; 372 return 0;
354} 373}
@@ -390,15 +409,15 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
390 continue; 409 continue;
391 if (page_nid != nid) 410 if (page_nid != nid)
392 continue; 411 continue;
393 ret = sysfs_create_link_nowarn(&node_devices[nid].dev.kobj, 412 ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
394 &mem_blk->dev.kobj, 413 &mem_blk->dev.kobj,
395 kobject_name(&mem_blk->dev.kobj)); 414 kobject_name(&mem_blk->dev.kobj));
396 if (ret) 415 if (ret)
397 return ret; 416 return ret;
398 417
399 return sysfs_create_link_nowarn(&mem_blk->dev.kobj, 418 return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
400 &node_devices[nid].dev.kobj, 419 &node_devices[nid]->dev.kobj,
401 kobject_name(&node_devices[nid].dev.kobj)); 420 kobject_name(&node_devices[nid]->dev.kobj));
402 } 421 }
403 /* mem section does not span the specified node */ 422 /* mem section does not span the specified node */
404 return 0; 423 return 0;
@@ -431,10 +450,10 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
431 continue; 450 continue;
432 if (node_test_and_set(nid, *unlinked_nodes)) 451 if (node_test_and_set(nid, *unlinked_nodes))
433 continue; 452 continue;
434 sysfs_remove_link(&node_devices[nid].dev.kobj, 453 sysfs_remove_link(&node_devices[nid]->dev.kobj,
435 kobject_name(&mem_blk->dev.kobj)); 454 kobject_name(&mem_blk->dev.kobj));
436 sysfs_remove_link(&mem_blk->dev.kobj, 455 sysfs_remove_link(&mem_blk->dev.kobj,
437 kobject_name(&node_devices[nid].dev.kobj)); 456 kobject_name(&node_devices[nid]->dev.kobj));
438 } 457 }
439 NODEMASK_FREE(unlinked_nodes); 458 NODEMASK_FREE(unlinked_nodes);
440 return 0; 459 return 0;
@@ -500,7 +519,7 @@ static void node_hugetlb_work(struct work_struct *work)
500 519
501static void init_node_hugetlb_work(int nid) 520static void init_node_hugetlb_work(int nid)
502{ 521{
503 INIT_WORK(&node_devices[nid].node_work, node_hugetlb_work); 522 INIT_WORK(&node_devices[nid]->node_work, node_hugetlb_work);
504} 523}
505 524
506static int node_memory_callback(struct notifier_block *self, 525static int node_memory_callback(struct notifier_block *self,
@@ -517,7 +536,7 @@ static int node_memory_callback(struct notifier_block *self,
517 * when transitioning to/from memoryless state. 536 * when transitioning to/from memoryless state.
518 */ 537 */
519 if (nid != NUMA_NO_NODE) 538 if (nid != NUMA_NO_NODE)
520 schedule_work(&node_devices[nid].node_work); 539 schedule_work(&node_devices[nid]->node_work);
521 break; 540 break;
522 541
523 case MEM_GOING_ONLINE: 542 case MEM_GOING_ONLINE:
@@ -558,9 +577,13 @@ int register_one_node(int nid)
558 struct node *parent = NULL; 577 struct node *parent = NULL;
559 578
560 if (p_node != nid) 579 if (p_node != nid)
561 parent = &node_devices[p_node]; 580 parent = node_devices[p_node];
581
582 node_devices[nid] = kzalloc(sizeof(struct node), GFP_KERNEL);
583 if (!node_devices[nid])
584 return -ENOMEM;
562 585
563 error = register_node(&node_devices[nid], nid, parent); 586 error = register_node(node_devices[nid], nid, parent);
564 587
565 /* link cpu under this node */ 588 /* link cpu under this node */
566 for_each_present_cpu(cpu) { 589 for_each_present_cpu(cpu) {
@@ -581,7 +604,8 @@ int register_one_node(int nid)
581 604
582void unregister_one_node(int nid) 605void unregister_one_node(int nid)
583{ 606{
584 unregister_node(&node_devices[nid]); 607 unregister_node(node_devices[nid]);
608 node_devices[nid] = NULL;
585} 609}
586 610
587/* 611/*
@@ -614,23 +638,23 @@ static ssize_t show_node_state(struct device *dev,
614 { __ATTR(name, 0444, show_node_state, NULL), state } 638 { __ATTR(name, 0444, show_node_state, NULL), state }
615 639
616static struct node_attr node_state_attr[] = { 640static struct node_attr node_state_attr[] = {
617 _NODE_ATTR(possible, N_POSSIBLE), 641 [N_POSSIBLE] = _NODE_ATTR(possible, N_POSSIBLE),
618 _NODE_ATTR(online, N_ONLINE), 642 [N_ONLINE] = _NODE_ATTR(online, N_ONLINE),
619 _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY), 643 [N_NORMAL_MEMORY] = _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
620 _NODE_ATTR(has_cpu, N_CPU),
621#ifdef CONFIG_HIGHMEM 644#ifdef CONFIG_HIGHMEM
622 _NODE_ATTR(has_high_memory, N_HIGH_MEMORY), 645 [N_HIGH_MEMORY] = _NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
623#endif 646#endif
647 [N_CPU] = _NODE_ATTR(has_cpu, N_CPU),
624}; 648};
625 649
626static struct attribute *node_state_attrs[] = { 650static struct attribute *node_state_attrs[] = {
627 &node_state_attr[0].attr.attr, 651 &node_state_attr[N_POSSIBLE].attr.attr,
628 &node_state_attr[1].attr.attr, 652 &node_state_attr[N_ONLINE].attr.attr,
629 &node_state_attr[2].attr.attr, 653 &node_state_attr[N_NORMAL_MEMORY].attr.attr,
630 &node_state_attr[3].attr.attr,
631#ifdef CONFIG_HIGHMEM 654#ifdef CONFIG_HIGHMEM
632 &node_state_attr[4].attr.attr, 655 &node_state_attr[N_HIGH_MEMORY].attr.attr,
633#endif 656#endif
657 &node_state_attr[N_CPU].attr.attr,
634 NULL 658 NULL
635}; 659};
636 660