numa: convert static memory to dynamically allocated memory for per node device
authorWen Congyang <wency@cn.fujitsu.com>
Wed, 12 Dec 2012 00:00:56 +0000 (16:00 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 12 Dec 2012 01:22:23 +0000 (17:22 -0800)
We use a static array to store struct node.  In many cases, we don't have
too many nodes, and some memory will be unused.  Convert it to per-device
dynamically allocated memory.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Jiang Liu <liuj97@gmail.com>
Cc: Minchan Kim <minchan.kim@gmail.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/powerpc/kernel/sysfs.c
drivers/base/node.c
include/linux/node.h
mm/hugetlb.c

index cf357a059ddb73856275ad7c1fda70170356751d..3ce1f864c2d3f749c2f3b6f2f7008a8f051230c1 100644 (file)
@@ -607,7 +607,7 @@ static void register_nodes(void)
 
 int sysfs_add_device_to_node(struct device *dev, int nid)
 {
-       struct node *node = &node_devices[nid];
+       struct node *node = node_devices[nid];
        return sysfs_create_link(&node->dev.kobj, &dev->kobj,
                        kobject_name(&dev->kobj));
 }
@@ -615,7 +615,7 @@ EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
 
 void sysfs_remove_device_from_node(struct device *dev, int nid)
 {
-       struct node *node = &node_devices[nid];
+       struct node *node = node_devices[nid];
        sysfs_remove_link(&node->dev.kobj, kobject_name(&dev->kobj));
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
index af1a177216f12573c7e481fea0a568c09b97ef12..28216ce74b3dadc4fa495d3f3e8ba335ddd30a0b 100644 (file)
@@ -306,7 +306,7 @@ void unregister_node(struct node *node)
        device_unregister(&node->dev);
 }
 
-struct node node_devices[MAX_NUMNODES];
+struct node *node_devices[MAX_NUMNODES];
 
 /*
  * register cpu under node
@@ -323,15 +323,15 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
        if (!obj)
                return 0;
 
-       ret = sysfs_create_link(&node_devices[nid].dev.kobj,
+       ret = sysfs_create_link(&node_devices[nid]->dev.kobj,
                                &obj->kobj,
                                kobject_name(&obj->kobj));
        if (ret)
                return ret;
 
        return sysfs_create_link(&obj->kobj,
-                                &node_devices[nid].dev.kobj,
-                                kobject_name(&node_devices[nid].dev.kobj));
+                                &node_devices[nid]->dev.kobj,
+                                kobject_name(&node_devices[nid]->dev.kobj));
 }
 
 int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
@@ -345,10 +345,10 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
        if (!obj)
                return 0;
 
-       sysfs_remove_link(&node_devices[nid].dev.kobj,
+       sysfs_remove_link(&node_devices[nid]->dev.kobj,
                          kobject_name(&obj->kobj));
        sysfs_remove_link(&obj->kobj,
-                         kobject_name(&node_devices[nid].dev.kobj));
+                         kobject_name(&node_devices[nid]->dev.kobj));
 
        return 0;
 }
@@ -390,15 +390,15 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
                        continue;
                if (page_nid != nid)
                        continue;
-               ret = sysfs_create_link_nowarn(&node_devices[nid].dev.kobj,
+               ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
                                        &mem_blk->dev.kobj,
                                        kobject_name(&mem_blk->dev.kobj));
                if (ret)
                        return ret;
 
                return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
-                               &node_devices[nid].dev.kobj,
-                               kobject_name(&node_devices[nid].dev.kobj));
+                               &node_devices[nid]->dev.kobj,
+                               kobject_name(&node_devices[nid]->dev.kobj));
        }
        /* mem section does not span the specified node */
        return 0;
@@ -431,10 +431,10 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
                        continue;
                if (node_test_and_set(nid, *unlinked_nodes))
                        continue;
-               sysfs_remove_link(&node_devices[nid].dev.kobj,
+               sysfs_remove_link(&node_devices[nid]->dev.kobj,
                         kobject_name(&mem_blk->dev.kobj));
                sysfs_remove_link(&mem_blk->dev.kobj,
-                        kobject_name(&node_devices[nid].dev.kobj));
+                        kobject_name(&node_devices[nid]->dev.kobj));
        }
        NODEMASK_FREE(unlinked_nodes);
        return 0;
@@ -500,7 +500,7 @@ static void node_hugetlb_work(struct work_struct *work)
 
 static void init_node_hugetlb_work(int nid)
 {
-       INIT_WORK(&node_devices[nid].node_work, node_hugetlb_work);
+       INIT_WORK(&node_devices[nid]->node_work, node_hugetlb_work);
 }
 
 static int node_memory_callback(struct notifier_block *self,
@@ -517,7 +517,7 @@ static int node_memory_callback(struct notifier_block *self,
                 * when transitioning to/from memoryless state.
                 */
                if (nid != NUMA_NO_NODE)
-                       schedule_work(&node_devices[nid].node_work);
+                       schedule_work(&node_devices[nid]->node_work);
                break;
 
        case MEM_GOING_ONLINE:
@@ -558,9 +558,13 @@ int register_one_node(int nid)
                struct node *parent = NULL;
 
                if (p_node != nid)
-                       parent = &node_devices[p_node];
+                       parent = node_devices[p_node];
 
-               error = register_node(&node_devices[nid], nid, parent);
+               node_devices[nid] = kzalloc(sizeof(struct node), GFP_KERNEL);
+               if (!node_devices[nid])
+                       return -ENOMEM;
+
+               error = register_node(node_devices[nid], nid, parent);
 
                /* link cpu under this node */
                for_each_present_cpu(cpu) {
@@ -581,7 +585,9 @@ int register_one_node(int nid)
 
 void unregister_one_node(int nid)
 {
-       unregister_node(&node_devices[nid]);
+       unregister_node(node_devices[nid]);
+       kfree(node_devices[nid]);
+       node_devices[nid] = NULL;
 }
 
 /*
index 624e53cecc0298a70b6393ff4a262ae0935af727..10316f1c68a9124bdd77ce655f3c6c9f620ee3e1 100644 (file)
@@ -27,7 +27,7 @@ struct node {
 };
 
 struct memory_block;
-extern struct node node_devices[];
+extern struct node *node_devices[];
 typedef  void (*node_registration_func_t)(struct node *);
 
 extern int register_node(struct node *, int, struct node *);
index 59a0059b39e27e8eb6d8dbaea784318dbde97333..1ef2cd4ae3c98229ffe9a244985c4c49da3fbb00 100644 (file)
@@ -1800,7 +1800,7 @@ static void hugetlb_unregister_all_nodes(void)
         * remove hstate attributes from any nodes that have them.
         */
        for (nid = 0; nid < nr_node_ids; nid++)
-               hugetlb_unregister_node(&node_devices[nid]);
+               hugetlb_unregister_node(node_devices[nid]);
 }
 
 /*
@@ -1845,7 +1845,7 @@ static void hugetlb_register_all_nodes(void)
        int nid;
 
        for_each_node_state(nid, N_HIGH_MEMORY) {
-               struct node *node = &node_devices[nid];
+               struct node *node = node_devices[nid];
                if (node->dev.id == nid)
                        hugetlb_register_node(node);
        }