Blame view
drivers/base/node.c
19 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
10fbcf4c6 convert 'memory' ... |
2 |
* Basic Node interface support |
1da177e4c Linux-2.6.12-rc2 |
3 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
4 5 6 |
#include <linux/module.h> #include <linux/init.h> #include <linux/mm.h> |
c04fc586c mm: show node to ... |
7 |
#include <linux/memory.h> |
fa25c503d mm: per-node vmst... |
8 |
#include <linux/vmstat.h> |
6e259e7dc drivers/base/node... |
9 |
#include <linux/notifier.h> |
1da177e4c Linux-2.6.12-rc2 |
10 11 |
#include <linux/node.h> #include <linux/hugetlb.h> |
ed4a6d7f0 mm: compaction: a... |
12 |
#include <linux/compaction.h> |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 |
#include <linux/cpumask.h> #include <linux/topology.h> #include <linux/nodemask.h> |
76b67ed9d [PATCH] node hotp... |
16 |
#include <linux/cpu.h> |
bde631a51 mm: add node stat... |
17 |
#include <linux/device.h> |
af936a160 vmscan: unevictab... |
18 |
#include <linux/swap.h> |
18e5b539b nodemask: include... |
19 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
20 |
|
10fbcf4c6 convert 'memory' ... |
21 |
static struct bus_type node_subsys = { |
af5ca3f4e Driver core: chan... |
22 |
.name = "node", |
10fbcf4c6 convert 'memory' ... |
23 |
.dev_name = "node", |
1da177e4c Linux-2.6.12-rc2 |
24 |
}; |
5aaba3631 cpumask: factor o... |
25 |
static ssize_t node_read_cpumap(struct device *dev, bool list, char *buf) |
1da177e4c Linux-2.6.12-rc2 |
26 27 |
{ struct node *node_dev = to_node(dev); |
10fbcf4c6 convert 'memory' ... |
28 |
const struct cpumask *mask = cpumask_of_node(node_dev->dev.id); |
1da177e4c Linux-2.6.12-rc2 |
29 |
|
39106dcf8 cpumask: use new ... |
30 31 |
/* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */ BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1)); |
1da177e4c Linux-2.6.12-rc2 |
32 |
|
5aaba3631 cpumask: factor o... |
33 |
return cpumap_print_to_pagebuf(list, buf, mask); |
1da177e4c Linux-2.6.12-rc2 |
34 |
} |
10fbcf4c6 convert 'memory' ... |
35 36 |
static inline ssize_t node_read_cpumask(struct device *dev, struct device_attribute *attr, char *buf) |
39106dcf8 cpumask: use new ... |
37 |
{ |
5aaba3631 cpumask: factor o... |
38 |
return node_read_cpumap(dev, false, buf); |
39106dcf8 cpumask: use new ... |
39 |
} |
10fbcf4c6 convert 'memory' ... |
40 41 |
static inline ssize_t node_read_cpulist(struct device *dev, struct device_attribute *attr, char *buf) |
39106dcf8 cpumask: use new ... |
42 |
{ |
5aaba3631 cpumask: factor o... |
43 |
return node_read_cpumap(dev, true, buf); |
39106dcf8 cpumask: use new ... |
44 |
} |
10fbcf4c6 convert 'memory' ... |
45 46 |
static DEVICE_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL); static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL); |
1da177e4c Linux-2.6.12-rc2 |
47 48 |
#define K(x) ((x) << (PAGE_SHIFT - 10)) |
10fbcf4c6 convert 'memory' ... |
49 50 |
static ssize_t node_read_meminfo(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4c Linux-2.6.12-rc2 |
51 52 53 |
{ int n; int nid = dev->id; |
599d0c954 mm, vmscan: move ... |
54 |
struct pglist_data *pgdat = NODE_DATA(nid); |
1da177e4c Linux-2.6.12-rc2 |
55 |
struct sysinfo i; |
1da177e4c Linux-2.6.12-rc2 |
56 57 |
si_meminfo_node(&i, nid); |
7ee922554 drivers/base/node... |
58 |
n = sprintf(buf, |
4f98a2fee vmscan: split LRU... |
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
"Node %d MemTotal: %8lu kB " "Node %d MemFree: %8lu kB " "Node %d MemUsed: %8lu kB " "Node %d Active: %8lu kB " "Node %d Inactive: %8lu kB " "Node %d Active(anon): %8lu kB " "Node %d Inactive(anon): %8lu kB " "Node %d Active(file): %8lu kB " "Node %d Inactive(file): %8lu kB " |
5344b7e64 vmstat: mlocked p... |
77 78 |
"Node %d Unevictable: %8lu kB " |
7ee922554 drivers/base/node... |
79 80 81 82 83 |
"Node %d Mlocked: %8lu kB ", nid, K(i.totalram), nid, K(i.freeram), nid, K(i.totalram - i.freeram), |
599d0c954 mm, vmscan: move ... |
84 85 86 87 88 89 90 91 92 |
nid, K(node_page_state(pgdat, NR_ACTIVE_ANON) + node_page_state(pgdat, NR_ACTIVE_FILE)), nid, K(node_page_state(pgdat, NR_INACTIVE_ANON) + node_page_state(pgdat, NR_INACTIVE_FILE)), nid, K(node_page_state(pgdat, NR_ACTIVE_ANON)), nid, K(node_page_state(pgdat, NR_INACTIVE_ANON)), nid, K(node_page_state(pgdat, NR_ACTIVE_FILE)), nid, K(node_page_state(pgdat, NR_INACTIVE_FILE)), nid, K(node_page_state(pgdat, NR_UNEVICTABLE)), |
75ef71840 mm, vmstat: add i... |
93 |
nid, K(sum_zone_node_page_state(nid, NR_MLOCK))); |
7ee922554 drivers/base/node... |
94 |
|
182e8e237 [PATCH] reduce MA... |
95 |
#ifdef CONFIG_HIGHMEM |
7ee922554 drivers/base/node... |
96 |
n += sprintf(buf + n, |
4f98a2fee vmscan: split LRU... |
97 98 99 100 101 102 |
"Node %d HighTotal: %8lu kB " "Node %d HighFree: %8lu kB " "Node %d LowTotal: %8lu kB " |
7ee922554 drivers/base/node... |
103 104 105 106 107 108 |
"Node %d LowFree: %8lu kB ", nid, K(i.totalhigh), nid, K(i.freehigh), nid, K(i.totalram - i.totalhigh), nid, K(i.freeram - i.freehigh)); |
182e8e237 [PATCH] reduce MA... |
109 |
#endif |
7ee922554 drivers/base/node... |
110 |
n += sprintf(buf + n, |
4f98a2fee vmscan: split LRU... |
111 112 113 114 115 116 117 118 119 120 |
"Node %d Dirty: %8lu kB " "Node %d Writeback: %8lu kB " "Node %d FilePages: %8lu kB " "Node %d Mapped: %8lu kB " "Node %d AnonPages: %8lu kB " |
4b02108ac mm: oom analysis:... |
121 122 |
"Node %d Shmem: %8lu kB " |
c6a7f5728 mm: oom analysis:... |
123 124 |
"Node %d KernelStack: %8lu kB " |
4f98a2fee vmscan: split LRU... |
125 126 127 128 129 130 131 132 133 134 135 136 |
"Node %d PageTables: %8lu kB " "Node %d NFS_Unstable: %8lu kB " "Node %d Bounce: %8lu kB " "Node %d WritebackTmp: %8lu kB " "Node %d Slab: %8lu kB " "Node %d SReclaimable: %8lu kB " |
05b258e99 thp: transparent ... |
137 138 139 140 141 |
"Node %d SUnreclaim: %8lu kB " #ifdef CONFIG_TRANSPARENT_HUGEPAGE "Node %d AnonHugePages: %8lu kB " |
65c453778 mm, rmap: account... |
142 143 144 145 |
"Node %d ShmemHugePages: %8lu kB " "Node %d ShmemPmdMapped: %8lu kB " |
05b258e99 thp: transparent ... |
146 147 |
#endif , |
11fb99898 mm: move most fil... |
148 149 150 |
nid, K(node_page_state(pgdat, NR_FILE_DIRTY)), nid, K(node_page_state(pgdat, NR_WRITEBACK)), nid, K(node_page_state(pgdat, NR_FILE_PAGES)), |
50658e2e0 mm: move page map... |
151 |
nid, K(node_page_state(pgdat, NR_FILE_MAPPED)), |
4b9d0fab7 mm: rename NR_ANO... |
152 |
nid, K(node_page_state(pgdat, NR_ANON_MAPPED)), |
cc7452b6d mm: export NR_SHM... |
153 |
nid, K(i.sharedram), |
d30dd8be0 mm: track NR_KERN... |
154 |
nid, sum_zone_node_page_state(nid, NR_KERNEL_STACK_KB), |
75ef71840 mm, vmstat: add i... |
155 |
nid, K(sum_zone_node_page_state(nid, NR_PAGETABLE)), |
11fb99898 mm: move most fil... |
156 |
nid, K(node_page_state(pgdat, NR_UNSTABLE_NFS)), |
75ef71840 mm, vmstat: add i... |
157 |
nid, K(sum_zone_node_page_state(nid, NR_BOUNCE)), |
11fb99898 mm: move most fil... |
158 |
nid, K(node_page_state(pgdat, NR_WRITEBACK_TEMP)), |
75ef71840 mm, vmstat: add i... |
159 160 161 |
nid, K(sum_zone_node_page_state(nid, NR_SLAB_RECLAIMABLE) + sum_zone_node_page_state(nid, NR_SLAB_UNRECLAIMABLE)), nid, K(sum_zone_node_page_state(nid, NR_SLAB_RECLAIMABLE)), |
05b258e99 thp: transparent ... |
162 |
#ifdef CONFIG_TRANSPARENT_HUGEPAGE |
75ef71840 mm, vmstat: add i... |
163 |
nid, K(sum_zone_node_page_state(nid, NR_SLAB_UNRECLAIMABLE)), |
11fb99898 mm: move most fil... |
164 |
nid, K(node_page_state(pgdat, NR_ANON_THPS) * |
65c453778 mm, rmap: account... |
165 |
HPAGE_PMD_NR), |
11fb99898 mm: move most fil... |
166 |
nid, K(node_page_state(pgdat, NR_SHMEM_THPS) * |
65c453778 mm, rmap: account... |
167 |
HPAGE_PMD_NR), |
11fb99898 mm: move most fil... |
168 |
nid, K(node_page_state(pgdat, NR_SHMEM_PMDMAPPED) * |
65c453778 mm, rmap: account... |
169 |
HPAGE_PMD_NR)); |
91a13c281 drivers/base/node... |
170 |
#else |
75ef71840 mm, vmstat: add i... |
171 |
nid, K(sum_zone_node_page_state(nid, NR_SLAB_UNRECLAIMABLE))); |
05b258e99 thp: transparent ... |
172 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
173 174 175 176 177 |
n += hugetlb_report_node_meminfo(nid, buf + n); return n; } #undef K |
10fbcf4c6 convert 'memory' ... |
178 |
static DEVICE_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); |
1da177e4c Linux-2.6.12-rc2 |
179 |
|
10fbcf4c6 convert 'memory' ... |
180 181 |
static ssize_t node_read_numastat(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4c Linux-2.6.12-rc2 |
182 |
{ |
1da177e4c Linux-2.6.12-rc2 |
183 184 185 186 187 188 189 190 191 192 193 194 195 |
return sprintf(buf, "numa_hit %lu " "numa_miss %lu " "numa_foreign %lu " "interleave_hit %lu " "local_node %lu " "other_node %lu ", |
75ef71840 mm, vmstat: add i... |
196 197 198 199 200 201 |
sum_zone_node_page_state(dev->id, NUMA_HIT), sum_zone_node_page_state(dev->id, NUMA_MISS), sum_zone_node_page_state(dev->id, NUMA_FOREIGN), sum_zone_node_page_state(dev->id, NUMA_INTERLEAVE_HIT), sum_zone_node_page_state(dev->id, NUMA_LOCAL), sum_zone_node_page_state(dev->id, NUMA_OTHER)); |
1da177e4c Linux-2.6.12-rc2 |
202 |
} |
10fbcf4c6 convert 'memory' ... |
203 |
static DEVICE_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); |
1da177e4c Linux-2.6.12-rc2 |
204 |
|
10fbcf4c6 convert 'memory' ... |
205 206 |
static ssize_t node_read_vmstat(struct device *dev, struct device_attribute *attr, char *buf) |
2ac390370 writeback: add /s... |
207 208 |
{ int nid = dev->id; |
75ef71840 mm, vmstat: add i... |
209 |
struct pglist_data *pgdat = NODE_DATA(nid); |
fa25c503d mm: per-node vmst... |
210 211 212 213 214 215 |
int i; int n = 0; for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) n += sprintf(buf+n, "%s %lu ", vmstat_text[i], |
75ef71840 mm, vmstat: add i... |
216 217 218 219 220 221 222 |
sum_zone_node_page_state(nid, i)); for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) n += sprintf(buf+n, "%s %lu ", vmstat_text[i + NR_VM_ZONE_STAT_ITEMS], node_page_state(pgdat, i)); |
fa25c503d mm: per-node vmst... |
223 224 |
return n; |
2ac390370 writeback: add /s... |
225 |
} |
10fbcf4c6 convert 'memory' ... |
226 |
static DEVICE_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL); |
2ac390370 writeback: add /s... |
227 |
|
10fbcf4c6 convert 'memory' ... |
228 |
static ssize_t node_read_distance(struct device *dev, |
518d3f38a drivers: base: no... |
229 |
struct device_attribute *attr, char *buf) |
1da177e4c Linux-2.6.12-rc2 |
230 231 232 233 |
{ int nid = dev->id; int len = 0; int i; |
12ee3c0a0 driver core: numa... |
234 235 236 237 238 |
/* * buf is currently PAGE_SIZE in length and each node needs 4 chars * at the most (distance + space or newline). */ BUILD_BUG_ON(MAX_NUMNODES * 4 > PAGE_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
239 240 241 242 243 244 245 246 |
for_each_online_node(i) len += sprintf(buf + len, "%s%d", i ? " " : "", node_distance(nid, i)); len += sprintf(buf + len, " "); return len; } |
10fbcf4c6 convert 'memory' ... |
247 |
static DEVICE_ATTR(distance, S_IRUGO, node_read_distance, NULL); |
1da177e4c Linux-2.6.12-rc2 |
248 |
|
3c9b8aaf9 drivers/base/node... |
249 250 251 252 253 254 255 256 257 |
static struct attribute *node_dev_attrs[] = { &dev_attr_cpumap.attr, &dev_attr_cpulist.attr, &dev_attr_meminfo.attr, &dev_attr_numastat.attr, &dev_attr_distance.attr, &dev_attr_vmstat.attr, NULL }; |
7ca7ec40f drivers/base/node... |
258 |
ATTRIBUTE_GROUPS(node_dev); |
3c9b8aaf9 drivers/base/node... |
259 |
|
9a3052306 hugetlb: add per ... |
260 261 262 263 |
#ifdef CONFIG_HUGETLBFS /* * hugetlbfs per node attributes registration interface: * When/if hugetlb[fs] subsystem initializes [sometime after this module], |
4faf8d950 hugetlb: handle m... |
264 265 |
* it will register its per node attributes for all online nodes with * memory. It will also call register_hugetlbfs_with_node(), below, to |
9a3052306 hugetlb: add per ... |
266 267 268 269 270 271 |
* register its attribute registration functions with this node driver. * Once these hooks have been initialized, the node driver will call into * the hugetlb module to [un]register attributes for hot-plugged nodes. */ static node_registration_func_t __hugetlb_register_node; static node_registration_func_t __hugetlb_unregister_node; |
39da08cb0 hugetlb: offload ... |
272 |
static inline bool hugetlb_register_node(struct node *node) |
9a3052306 hugetlb: add per ... |
273 |
{ |
4faf8d950 hugetlb: handle m... |
274 |
if (__hugetlb_register_node && |
8cebfcd07 hugetlb: use N_ME... |
275 |
node_state(node->dev.id, N_MEMORY)) { |
9a3052306 hugetlb: add per ... |
276 |
__hugetlb_register_node(node); |
39da08cb0 hugetlb: offload ... |
277 278 279 |
return true; } return false; |
9a3052306 hugetlb: add per ... |
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
} static inline void hugetlb_unregister_node(struct node *node) { if (__hugetlb_unregister_node) __hugetlb_unregister_node(node); } void register_hugetlbfs_with_node(node_registration_func_t doregister, node_registration_func_t unregister) { __hugetlb_register_node = doregister; __hugetlb_unregister_node = unregister; } #else static inline void hugetlb_register_node(struct node *node) {} static inline void hugetlb_unregister_node(struct node *node) {} #endif |
8c7b5b4ed memory-hotplug: s... |
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
static void node_device_release(struct device *dev) { struct node *node = to_node(dev); #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS) /* * We schedule the work only when a memory section is * onlined/offlined on this node. When we come here, * all the memory on this node has been offlined, * so we won't enqueue new work to this work. * * The work is using node->node_work, so we should * flush work before freeing the memory. */ flush_work(&node->node_work); #endif kfree(node); } |
1da177e4c Linux-2.6.12-rc2 |
317 318 |
/* |
405ae7d38 Replace remaining... |
319 |
* register_node - Setup a sysfs device for a node. |
1da177e4c Linux-2.6.12-rc2 |
320 321 322 323 |
* @num - Node number to use when creating the device. * * Initialize and register the node device. */ |
fa2643751 mm: cleanup regis... |
324 |
static int register_node(struct node *node, int num, struct node *parent) |
1da177e4c Linux-2.6.12-rc2 |
325 326 |
{ int error; |
10fbcf4c6 convert 'memory' ... |
327 328 |
node->dev.id = num; node->dev.bus = &node_subsys; |
8c7b5b4ed memory-hotplug: s... |
329 |
node->dev.release = node_device_release; |
7ca7ec40f drivers/base/node... |
330 |
node->dev.groups = node_dev_groups; |
10fbcf4c6 convert 'memory' ... |
331 |
error = device_register(&node->dev); |
1da177e4c Linux-2.6.12-rc2 |
332 333 |
if (!error){ |
9a3052306 hugetlb: add per ... |
334 |
hugetlb_register_node(node); |
ed4a6d7f0 mm: compaction: a... |
335 336 |
compaction_register_node(node); |
1da177e4c Linux-2.6.12-rc2 |
337 338 339 |
} return error; } |
4b45099b7 [PATCH] Driver co... |
340 341 342 343 344 345 346 347 348 |
/** * unregister_node - unregister a node device * @node: node going away * * Unregisters a node device @node. All the devices on the node must be * unregistered before calling this function. */ void unregister_node(struct node *node) { |
4faf8d950 hugetlb: handle m... |
349 |
hugetlb_unregister_node(node); /* no-op, if memoryless node */ |
af936a160 vmscan: unevictab... |
350 |
|
10fbcf4c6 convert 'memory' ... |
351 |
device_unregister(&node->dev); |
4b45099b7 [PATCH] Driver co... |
352 |
} |
1da177e4c Linux-2.6.12-rc2 |
353 |
|
8732794b1 numa: convert sta... |
354 |
struct node *node_devices[MAX_NUMNODES]; |
0fc44159b [PATCH] Register ... |
355 |
|
76b67ed9d [PATCH] node hotp... |
356 357 358 359 360 |
/* * register cpu under node */ int register_cpu_under_node(unsigned int cpu, unsigned int nid) { |
1830794ae mm: add numa node... |
361 |
int ret; |
8a25a2fd1 cpu: convert 'cpu... |
362 |
struct device *obj; |
76b67ed9d [PATCH] node hotp... |
363 |
|
f8246f315 mm: refactor regi... |
364 365 |
if (!node_online(nid)) return 0; |
8a25a2fd1 cpu: convert 'cpu... |
366 |
obj = get_cpu_device(cpu); |
f8246f315 mm: refactor regi... |
367 368 |
if (!obj) return 0; |
8732794b1 numa: convert sta... |
369 |
ret = sysfs_create_link(&node_devices[nid]->dev.kobj, |
f8246f315 mm: refactor regi... |
370 371 |
&obj->kobj, kobject_name(&obj->kobj)); |
1830794ae mm: add numa node... |
372 373 374 375 |
if (ret) return ret; return sysfs_create_link(&obj->kobj, |
8732794b1 numa: convert sta... |
376 377 |
&node_devices[nid]->dev.kobj, kobject_name(&node_devices[nid]->dev.kobj)); |
76b67ed9d [PATCH] node hotp... |
378 379 380 381 |
} int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) { |
8a25a2fd1 cpu: convert 'cpu... |
382 |
struct device *obj; |
b9d52dad9 mm: refactor unre... |
383 384 385 |
if (!node_online(nid)) return 0; |
8a25a2fd1 cpu: convert 'cpu... |
386 |
obj = get_cpu_device(cpu); |
b9d52dad9 mm: refactor unre... |
387 388 |
if (!obj) return 0; |
8732794b1 numa: convert sta... |
389 |
sysfs_remove_link(&node_devices[nid]->dev.kobj, |
b9d52dad9 mm: refactor unre... |
390 |
kobject_name(&obj->kobj)); |
1830794ae mm: add numa node... |
391 |
sysfs_remove_link(&obj->kobj, |
8732794b1 numa: convert sta... |
392 |
kobject_name(&node_devices[nid]->dev.kobj)); |
b9d52dad9 mm: refactor unre... |
393 |
|
76b67ed9d [PATCH] node hotp... |
394 395 |
return 0; } |
c04fc586c mm: show node to ... |
396 397 |
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE #define page_initialized(page) (page->lru.next) |
bd721ea73 treewide: replace... |
398 |
static int __ref get_nid_for_pfn(unsigned long pfn) |
c04fc586c mm: show node to ... |
399 400 401 402 403 |
{ struct page *page; if (!pfn_valid_within(pfn)) return -1; |
3a80a7fa7 mm: meminit: init... |
404 405 406 407 |
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT if (system_state == SYSTEM_BOOTING) return early_pfn_to_nid(pfn); #endif |
c04fc586c mm: show node to ... |
408 409 410 411 412 413 414 415 416 |
page = pfn_to_page(pfn); if (!page_initialized(page)) return -1; return pfn_to_nid(pfn); } /* register memory section under specified node if it spans that node */ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) { |
dee5d0d51 mm: add numa node... |
417 |
int ret; |
c04fc586c mm: show node to ... |
418 419 420 421 422 423 |
unsigned long pfn, sect_start_pfn, sect_end_pfn; if (!mem_blk) return -EFAULT; if (!node_online(nid)) return 0; |
d33601644 memory hotplug: U... |
424 425 426 427 |
sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr); sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr); sect_end_pfn += PAGES_PER_SECTION - 1; |
c04fc586c mm: show node to ... |
428 429 |
for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { int page_nid; |
04697858d mm: check if sect... |
430 431 432 433 434 435 436 437 438 |
/* * memory block could have several absent sections from start. * skip pfn range from absent section */ if (!pfn_present(pfn)) { pfn = round_down(pfn + PAGES_PER_SECTION, PAGES_PER_SECTION) - 1; continue; } |
c04fc586c mm: show node to ... |
439 440 441 442 443 |
page_nid = get_nid_for_pfn(pfn); if (page_nid < 0) continue; if (page_nid != nid) continue; |
8732794b1 numa: convert sta... |
444 |
ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj, |
10fbcf4c6 convert 'memory' ... |
445 446 |
&mem_blk->dev.kobj, kobject_name(&mem_blk->dev.kobj)); |
dee5d0d51 mm: add numa node... |
447 448 |
if (ret) return ret; |
10fbcf4c6 convert 'memory' ... |
449 |
return sysfs_create_link_nowarn(&mem_blk->dev.kobj, |
8732794b1 numa: convert sta... |
450 451 |
&node_devices[nid]->dev.kobj, kobject_name(&node_devices[nid]->dev.kobj)); |
c04fc586c mm: show node to ... |
452 453 454 455 456 457 |
} /* mem section does not span the specified node */ return 0; } /* unregister memory section under all nodes that it spans */ |
d33601644 memory hotplug: U... |
458 459 |
int unregister_mem_sect_under_nodes(struct memory_block *mem_blk, unsigned long phys_index) |
c04fc586c mm: show node to ... |
460 |
{ |
9ae49fab2 mm: slab-allocate... |
461 |
NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL); |
c04fc586c mm: show node to ... |
462 |
unsigned long pfn, sect_start_pfn, sect_end_pfn; |
9ae49fab2 mm: slab-allocate... |
463 464 |
if (!mem_blk) { NODEMASK_FREE(unlinked_nodes); |
c04fc586c mm: show node to ... |
465 |
return -EFAULT; |
9ae49fab2 mm: slab-allocate... |
466 467 468 469 |
} if (!unlinked_nodes) return -ENOMEM; nodes_clear(*unlinked_nodes); |
d33601644 memory hotplug: U... |
470 471 |
sect_start_pfn = section_nr_to_pfn(phys_index); |
c04fc586c mm: show node to ... |
472 473 |
sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { |
475049809 mm: get_nid_for_p... |
474 |
int nid; |
c04fc586c mm: show node to ... |
475 476 477 478 479 480 |
nid = get_nid_for_pfn(pfn); if (nid < 0) continue; if (!node_online(nid)) continue; |
9ae49fab2 mm: slab-allocate... |
481 |
if (node_test_and_set(nid, *unlinked_nodes)) |
c04fc586c mm: show node to ... |
482 |
continue; |
8732794b1 numa: convert sta... |
483 |
sysfs_remove_link(&node_devices[nid]->dev.kobj, |
10fbcf4c6 convert 'memory' ... |
484 485 |
kobject_name(&mem_blk->dev.kobj)); sysfs_remove_link(&mem_blk->dev.kobj, |
8732794b1 numa: convert sta... |
486 |
kobject_name(&node_devices[nid]->dev.kobj)); |
c04fc586c mm: show node to ... |
487 |
} |
9ae49fab2 mm: slab-allocate... |
488 |
NODEMASK_FREE(unlinked_nodes); |
c04fc586c mm: show node to ... |
489 490 491 492 493 494 495 496 |
return 0; } static int link_mem_sections(int nid) { unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn; unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages; unsigned long pfn; |
63d027a63 driver core: Conv... |
497 |
struct memory_block *mem_blk = NULL; |
c04fc586c mm: show node to ... |
498 499 500 501 502 |
int err = 0; for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) { unsigned long section_nr = pfn_to_section_nr(pfn); struct mem_section *mem_sect; |
c04fc586c mm: show node to ... |
503 504 505 506 507 |
int ret; if (!present_section_nr(section_nr)) continue; mem_sect = __nr_to_section(section_nr); |
321bf4ed5 drivers/base/memo... |
508 509 510 511 512 513 |
/* same memblock ? */ if (mem_blk) if ((section_nr >= mem_blk->start_section_nr) && (section_nr <= mem_blk->end_section_nr)) continue; |
63d027a63 driver core: Conv... |
514 |
mem_blk = find_memory_block_hinted(mem_sect, mem_blk); |
321bf4ed5 drivers/base/memo... |
515 |
|
c04fc586c mm: show node to ... |
516 517 518 519 520 |
ret = register_mem_sect_under_node(mem_blk, nid); if (!err) err = ret; /* discard ref obtained in find_memory_block() */ |
c04fc586c mm: show node to ... |
521 |
} |
63d027a63 driver core: Conv... |
522 523 |
if (mem_blk) |
10fbcf4c6 convert 'memory' ... |
524 |
kobject_put(&mem_blk->dev.kobj); |
c04fc586c mm: show node to ... |
525 526 |
return err; } |
4faf8d950 hugetlb: handle m... |
527 |
|
39da08cb0 hugetlb: offload ... |
528 |
#ifdef CONFIG_HUGETLBFS |
4faf8d950 hugetlb: handle m... |
529 530 531 532 |
/* * Handle per node hstate attribute [un]registration on transistions * to/from memoryless state. */ |
39da08cb0 hugetlb: offload ... |
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 |
static void node_hugetlb_work(struct work_struct *work) { struct node *node = container_of(work, struct node, node_work); /* * We only get here when a node transitions to/from memoryless state. * We can detect which transition occurred by examining whether the * node has memory now. hugetlb_register_node() already check this * so we try to register the attributes. If that fails, then the * node has transitioned to memoryless, try to unregister the * attributes. */ if (!hugetlb_register_node(node)) hugetlb_unregister_node(node); } static void init_node_hugetlb_work(int nid) { |
8732794b1 numa: convert sta... |
551 |
INIT_WORK(&node_devices[nid]->node_work, node_hugetlb_work); |
39da08cb0 hugetlb: offload ... |
552 |
} |
4faf8d950 hugetlb: handle m... |
553 554 555 556 557 558 559 560 |
static int node_memory_callback(struct notifier_block *self, unsigned long action, void *arg) { struct memory_notify *mnb = arg; int nid = mnb->status_change_nid; switch (action) { |
39da08cb0 hugetlb: offload ... |
561 562 563 564 565 566 |
case MEM_ONLINE: case MEM_OFFLINE: /* * offload per node hstate [un]registration to a work thread * when transitioning to/from memoryless state. */ |
4faf8d950 hugetlb: handle m... |
567 |
if (nid != NUMA_NO_NODE) |
8732794b1 numa: convert sta... |
568 |
schedule_work(&node_devices[nid]->node_work); |
4faf8d950 hugetlb: handle m... |
569 |
break; |
39da08cb0 hugetlb: offload ... |
570 |
|
4faf8d950 hugetlb: handle m... |
571 572 573 574 575 576 577 578 579 580 |
case MEM_GOING_ONLINE: case MEM_GOING_OFFLINE: case MEM_CANCEL_ONLINE: case MEM_CANCEL_OFFLINE: default: break; } return NOTIFY_OK; } |
39da08cb0 hugetlb: offload ... |
581 582 |
#endif /* CONFIG_HUGETLBFS */ #else /* !CONFIG_MEMORY_HOTPLUG_SPARSE */ |
c04fc586c mm: show node to ... |
583 |
static int link_mem_sections(int nid) { return 0; } |
39da08cb0 hugetlb: offload ... |
584 |
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ |
4faf8d950 hugetlb: handle m... |
585 |
|
39da08cb0 hugetlb: offload ... |
586 587 |
#if !defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || \ !defined(CONFIG_HUGETLBFS) |
4faf8d950 hugetlb: handle m... |
588 589 590 591 592 |
static inline int node_memory_callback(struct notifier_block *self, unsigned long action, void *arg) { return NOTIFY_OK; } |
39da08cb0 hugetlb: offload ... |
593 594 595 596 |
static void init_node_hugetlb_work(int nid) { } #endif |
c04fc586c mm: show node to ... |
597 |
|
0fc44159b [PATCH] Register ... |
598 599 600 |
int register_one_node(int nid) { int error = 0; |
76b67ed9d [PATCH] node hotp... |
601 |
int cpu; |
0fc44159b [PATCH] Register ... |
602 603 604 605 606 607 |
if (node_online(nid)) { int p_node = parent_node(nid); struct node *parent = NULL; if (p_node != nid) |
8732794b1 numa: convert sta... |
608 |
parent = node_devices[p_node]; |
0fc44159b [PATCH] Register ... |
609 |
|
8732794b1 numa: convert sta... |
610 611 612 613 614 |
node_devices[nid] = kzalloc(sizeof(struct node), GFP_KERNEL); if (!node_devices[nid]) return -ENOMEM; error = register_node(node_devices[nid], nid, parent); |
76b67ed9d [PATCH] node hotp... |
615 616 617 618 619 620 |
/* link cpu under this node */ for_each_present_cpu(cpu) { if (cpu_to_node(cpu) == nid) register_cpu_under_node(cpu, nid); } |
c04fc586c mm: show node to ... |
621 622 623 |
/* link memory sections under this node */ error = link_mem_sections(nid); |
39da08cb0 hugetlb: offload ... |
624 625 626 |
/* initialize work queue for memory hot plug */ init_node_hugetlb_work(nid); |
0fc44159b [PATCH] Register ... |
627 628 629 630 631 632 633 634 |
} return error; } void unregister_one_node(int nid) { |
92d585ef0 numa: fix NULL po... |
635 636 |
if (!node_devices[nid]) return; |
8732794b1 numa: convert sta... |
637 |
unregister_node(node_devices[nid]); |
8732794b1 numa: convert sta... |
638 |
node_devices[nid] = NULL; |
0fc44159b [PATCH] Register ... |
639 |
} |
bde631a51 mm: add node stat... |
640 641 642 643 644 645 646 |
/* * node states attributes */ static ssize_t print_nodes_state(enum node_states state, char *buf) { int n; |
f799b1a7f drivers/base: use... |
647 648 |
n = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", nodemask_pr_args(&node_states[state])); |
f62388187 mm: fix off-by-on... |
649 650 651 |
buf[n++] = ' '; buf[n] = '\0'; |
bde631a51 mm: add node stat... |
652 653 |
return n; } |
b15f562fc sysdev: Convert n... |
654 |
struct node_attr { |
10fbcf4c6 convert 'memory' ... |
655 |
struct device_attribute attr; |
b15f562fc sysdev: Convert n... |
656 657 |
enum node_states state; }; |
bde631a51 mm: add node stat... |
658 |
|
10fbcf4c6 convert 'memory' ... |
659 660 |
static ssize_t show_node_state(struct device *dev, struct device_attribute *attr, char *buf) |
bde631a51 mm: add node stat... |
661 |
{ |
b15f562fc sysdev: Convert n... |
662 663 |
struct node_attr *na = container_of(attr, struct node_attr, attr); return print_nodes_state(na->state, buf); |
bde631a51 mm: add node stat... |
664 |
} |
b15f562fc sysdev: Convert n... |
665 |
#define _NODE_ATTR(name, state) \ |
10fbcf4c6 convert 'memory' ... |
666 |
{ __ATTR(name, 0444, show_node_state, NULL), state } |
bde631a51 mm: add node stat... |
667 |
|
b15f562fc sysdev: Convert n... |
668 |
static struct node_attr node_state_attr[] = { |
fcf07d22f drivers/base/node... |
669 670 671 |
[N_POSSIBLE] = _NODE_ATTR(possible, N_POSSIBLE), [N_ONLINE] = _NODE_ATTR(online, N_ONLINE), [N_NORMAL_MEMORY] = _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY), |
bde631a51 mm: add node stat... |
672 |
#ifdef CONFIG_HIGHMEM |
fcf07d22f drivers/base/node... |
673 |
[N_HIGH_MEMORY] = _NODE_ATTR(has_high_memory, N_HIGH_MEMORY), |
bde631a51 mm: add node stat... |
674 |
#endif |
20b2f52b7 numa: add CONFIG_... |
675 676 677 |
#ifdef CONFIG_MOVABLE_NODE [N_MEMORY] = _NODE_ATTR(has_memory, N_MEMORY), #endif |
fcf07d22f drivers/base/node... |
678 |
[N_CPU] = _NODE_ATTR(has_cpu, N_CPU), |
bde631a51 mm: add node stat... |
679 |
}; |
10fbcf4c6 convert 'memory' ... |
680 |
static struct attribute *node_state_attrs[] = { |
fcf07d22f drivers/base/node... |
681 682 683 |
&node_state_attr[N_POSSIBLE].attr.attr, &node_state_attr[N_ONLINE].attr.attr, &node_state_attr[N_NORMAL_MEMORY].attr.attr, |
3701cde6e sysdev: Use sysde... |
684 |
#ifdef CONFIG_HIGHMEM |
fcf07d22f drivers/base/node... |
685 |
&node_state_attr[N_HIGH_MEMORY].attr.attr, |
3701cde6e sysdev: Use sysde... |
686 |
#endif |
20b2f52b7 numa: add CONFIG_... |
687 688 689 |
#ifdef CONFIG_MOVABLE_NODE &node_state_attr[N_MEMORY].attr.attr, #endif |
fcf07d22f drivers/base/node... |
690 |
&node_state_attr[N_CPU].attr.attr, |
3701cde6e sysdev: Use sysde... |
691 692 |
NULL }; |
bde631a51 mm: add node stat... |
693 |
|
10fbcf4c6 convert 'memory' ... |
694 695 696 697 698 699 700 701 |
static struct attribute_group memory_root_attr_group = { .attrs = node_state_attrs, }; static const struct attribute_group *cpu_root_attr_groups[] = { &memory_root_attr_group, NULL, }; |
4faf8d950 hugetlb: handle m... |
702 |
#define NODE_CALLBACK_PRI 2 /* lower than SLAB */ |
4b45099b7 [PATCH] Driver co... |
703 |
static int __init register_node_type(void) |
1da177e4c Linux-2.6.12-rc2 |
704 |
{ |
bde631a51 mm: add node stat... |
705 |
int ret; |
3701cde6e sysdev: Use sysde... |
706 707 |
BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES); BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES); |
10fbcf4c6 convert 'memory' ... |
708 |
ret = subsys_system_register(&node_subsys, cpu_root_attr_groups); |
4faf8d950 hugetlb: handle m... |
709 |
if (!ret) { |
6e259e7dc drivers/base/node... |
710 711 712 713 714 |
static struct notifier_block node_memory_callback_nb = { .notifier_call = node_memory_callback, .priority = NODE_CALLBACK_PRI, }; register_hotmemory_notifier(&node_memory_callback_nb); |
4faf8d950 hugetlb: handle m... |
715 |
} |
bde631a51 mm: add node stat... |
716 717 718 719 720 721 |
/* * Note: we're not going to unregister the node class if we fail * to register the node state class attribute files. */ return ret; |
1da177e4c Linux-2.6.12-rc2 |
722 723 |
} postcore_initcall(register_node_type); |