diff options
author | Ingo Molnar <mingo@kernel.org> | 2013-01-24 06:47:48 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-01-24 06:47:48 -0500 |
commit | befddb21c845f8fb49e637997891ef97c6a869dc (patch) | |
tree | 0e7629123184f2dd50291ad6d477b894175f0f26 /drivers/base/node.c | |
parent | e716efde75267eab919cdb2bef5b2cb77f305326 (diff) | |
parent | 7d1f9aeff1ee4a20b1aeb377dd0f579fe9647619 (diff) |
Merge tag 'v3.8-rc4' into irq/core
Merge Linux 3.8-rc4 before pulling in new commits - we were on an old v3.7 base.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/base/node.c')
-rw-r--r-- | drivers/base/node.c | 86 |
1 files changed, 58 insertions, 28 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c index af1a177216f1..fac124a7e1c5 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -227,7 +227,7 @@ static node_registration_func_t __hugetlb_unregister_node; | |||
227 | static inline bool hugetlb_register_node(struct node *node) | 227 | static inline bool hugetlb_register_node(struct node *node) |
228 | { | 228 | { |
229 | if (__hugetlb_register_node && | 229 | if (__hugetlb_register_node && |
230 | node_state(node->dev.id, N_HIGH_MEMORY)) { | 230 | node_state(node->dev.id, N_MEMORY)) { |
231 | __hugetlb_register_node(node); | 231 | __hugetlb_register_node(node); |
232 | return true; | 232 | return true; |
233 | } | 233 | } |
@@ -252,6 +252,24 @@ static inline void hugetlb_register_node(struct node *node) {} | |||
252 | static inline void hugetlb_unregister_node(struct node *node) {} | 252 | static inline void hugetlb_unregister_node(struct node *node) {} |
253 | #endif | 253 | #endif |
254 | 254 | ||
255 | static 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 | */ |
262 | int register_node(struct node *node, int num, struct node *parent) | 280 | static 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 | ||
309 | struct node node_devices[MAX_NUMNODES]; | 328 | struct 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 | ||
337 | int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) | 356 | int 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 | ||
501 | static void init_node_hugetlb_work(int nid) | 520 | static 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 | ||
506 | static int node_memory_callback(struct notifier_block *self, | 525 | static 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 | ||
582 | void unregister_one_node(int nid) | 605 | void 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,29 @@ 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 | ||
616 | static struct node_attr node_state_attr[] = { | 640 | static 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 | #ifdef CONFIG_MOVABLE_NODE | ||
648 | [N_MEMORY] = _NODE_ATTR(has_memory, N_MEMORY), | ||
649 | #endif | ||
650 | [N_CPU] = _NODE_ATTR(has_cpu, N_CPU), | ||
624 | }; | 651 | }; |
625 | 652 | ||
626 | static struct attribute *node_state_attrs[] = { | 653 | static struct attribute *node_state_attrs[] = { |
627 | &node_state_attr[0].attr.attr, | 654 | &node_state_attr[N_POSSIBLE].attr.attr, |
628 | &node_state_attr[1].attr.attr, | 655 | &node_state_attr[N_ONLINE].attr.attr, |
629 | &node_state_attr[2].attr.attr, | 656 | &node_state_attr[N_NORMAL_MEMORY].attr.attr, |
630 | &node_state_attr[3].attr.attr, | ||
631 | #ifdef CONFIG_HIGHMEM | 657 | #ifdef CONFIG_HIGHMEM |
632 | &node_state_attr[4].attr.attr, | 658 | &node_state_attr[N_HIGH_MEMORY].attr.attr, |
659 | #endif | ||
660 | #ifdef CONFIG_MOVABLE_NODE | ||
661 | &node_state_attr[N_MEMORY].attr.attr, | ||
633 | #endif | 662 | #endif |
663 | &node_state_attr[N_CPU].attr.attr, | ||
634 | NULL | 664 | NULL |
635 | }; | 665 | }; |
636 | 666 | ||