Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Basic Node interface support
4 : : */
5 : :
6 : : #include <linux/module.h>
7 : : #include <linux/init.h>
8 : : #include <linux/mm.h>
9 : : #include <linux/memory.h>
10 : : #include <linux/vmstat.h>
11 : : #include <linux/notifier.h>
12 : : #include <linux/node.h>
13 : : #include <linux/hugetlb.h>
14 : : #include <linux/compaction.h>
15 : : #include <linux/cpumask.h>
16 : : #include <linux/topology.h>
17 : : #include <linux/nodemask.h>
18 : : #include <linux/cpu.h>
19 : : #include <linux/device.h>
20 : : #include <linux/pm_runtime.h>
21 : : #include <linux/swap.h>
22 : : #include <linux/slab.h>
23 : :
24 : : static struct bus_type node_subsys = {
25 : : .name = "node",
26 : : .dev_name = "node",
27 : : };
28 : :
29 : :
30 : 0 : static ssize_t node_read_cpumap(struct device *dev, bool list, char *buf)
31 : : {
32 : 0 : ssize_t n;
33 : 0 : cpumask_var_t mask;
34 : 0 : struct node *node_dev = to_node(dev);
35 : :
36 : : /* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
37 : 0 : BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
38 : :
39 : 0 : if (!alloc_cpumask_var(&mask, GFP_KERNEL))
40 : : return 0;
41 : :
42 : 0 : cpumask_and(mask, cpumask_of_node(node_dev->dev.id), cpu_online_mask);
43 : 0 : n = cpumap_print_to_pagebuf(list, buf, mask);
44 : 0 : free_cpumask_var(mask);
45 : :
46 : 0 : return n;
47 : : }
48 : :
49 : 0 : static inline ssize_t node_read_cpumask(struct device *dev,
50 : : struct device_attribute *attr, char *buf)
51 : : {
52 : 0 : return node_read_cpumap(dev, false, buf);
53 : : }
54 : 0 : static inline ssize_t node_read_cpulist(struct device *dev,
55 : : struct device_attribute *attr, char *buf)
56 : : {
57 : 0 : return node_read_cpumap(dev, true, buf);
58 : : }
59 : :
60 : : static DEVICE_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL);
61 : : static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
62 : :
63 : : /**
64 : : * struct node_access_nodes - Access class device to hold user visible
65 : : * relationships to other nodes.
66 : : * @dev: Device for this memory access class
67 : : * @list_node: List element in the node's access list
68 : : * @access: The access class rank
69 : : * @hmem_attrs: Heterogeneous memory performance attributes
70 : : */
71 : : struct node_access_nodes {
72 : : struct device dev;
73 : : struct list_head list_node;
74 : : unsigned access;
75 : : #ifdef CONFIG_HMEM_REPORTING
76 : : struct node_hmem_attrs hmem_attrs;
77 : : #endif
78 : : };
79 : : #define to_access_nodes(dev) container_of(dev, struct node_access_nodes, dev)
80 : :
81 : : static struct attribute *node_init_access_node_attrs[] = {
82 : : NULL,
83 : : };
84 : :
85 : : static struct attribute *node_targ_access_node_attrs[] = {
86 : : NULL,
87 : : };
88 : :
89 : : static const struct attribute_group initiators = {
90 : : .name = "initiators",
91 : : .attrs = node_init_access_node_attrs,
92 : : };
93 : :
94 : : static const struct attribute_group targets = {
95 : : .name = "targets",
96 : : .attrs = node_targ_access_node_attrs,
97 : : };
98 : :
99 : : static const struct attribute_group *node_access_node_groups[] = {
100 : : &initiators,
101 : : &targets,
102 : : NULL,
103 : : };
104 : :
105 : 0 : static void node_remove_accesses(struct node *node)
106 : : {
107 : 0 : struct node_access_nodes *c, *cnext;
108 : :
109 [ # # ]: 0 : list_for_each_entry_safe(c, cnext, &node->access_list, list_node) {
110 : 0 : list_del(&c->list_node);
111 : 0 : device_unregister(&c->dev);
112 : : }
113 : 0 : }
114 : :
115 : 0 : static void node_access_release(struct device *dev)
116 : : {
117 : 0 : kfree(to_access_nodes(dev));
118 : 0 : }
119 : :
120 : 0 : static struct node_access_nodes *node_init_node_access(struct node *node,
121 : : unsigned access)
122 : : {
123 : 0 : struct node_access_nodes *access_node;
124 : 0 : struct device *dev;
125 : :
126 [ # # ]: 0 : list_for_each_entry(access_node, &node->access_list, list_node)
127 [ # # ]: 0 : if (access_node->access == access)
128 : 0 : return access_node;
129 : :
130 : 0 : access_node = kzalloc(sizeof(*access_node), GFP_KERNEL);
131 [ # # ]: 0 : if (!access_node)
132 : : return NULL;
133 : :
134 : 0 : access_node->access = access;
135 : 0 : dev = &access_node->dev;
136 : 0 : dev->parent = &node->dev;
137 : 0 : dev->release = node_access_release;
138 : 0 : dev->groups = node_access_node_groups;
139 [ # # ]: 0 : if (dev_set_name(dev, "access%u", access))
140 : 0 : goto free;
141 : :
142 [ # # ]: 0 : if (device_register(dev))
143 : 0 : goto free_name;
144 : :
145 : 0 : pm_runtime_no_callbacks(dev);
146 : 0 : list_add_tail(&access_node->list_node, &node->access_list);
147 : 0 : return access_node;
148 : : free_name:
149 : 0 : kfree_const(dev->kobj.name);
150 : 0 : free:
151 : 0 : kfree(access_node);
152 : 0 : return NULL;
153 : : }
154 : :
155 : : #ifdef CONFIG_HMEM_REPORTING
156 : : #define ACCESS_ATTR(name) \
157 : : static ssize_t name##_show(struct device *dev, \
158 : : struct device_attribute *attr, \
159 : : char *buf) \
160 : : { \
161 : : return sprintf(buf, "%u\n", to_access_nodes(dev)->hmem_attrs.name); \
162 : : } \
163 : : static DEVICE_ATTR_RO(name);
164 : :
165 : : ACCESS_ATTR(read_bandwidth)
166 : : ACCESS_ATTR(read_latency)
167 : : ACCESS_ATTR(write_bandwidth)
168 : : ACCESS_ATTR(write_latency)
169 : :
170 : : static struct attribute *access_attrs[] = {
171 : : &dev_attr_read_bandwidth.attr,
172 : : &dev_attr_read_latency.attr,
173 : : &dev_attr_write_bandwidth.attr,
174 : : &dev_attr_write_latency.attr,
175 : : NULL,
176 : : };
177 : :
178 : : /**
179 : : * node_set_perf_attrs - Set the performance values for given access class
180 : : * @nid: Node identifier to be set
181 : : * @hmem_attrs: Heterogeneous memory performance attributes
182 : : * @access: The access class the for the given attributes
183 : : */
184 : : void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs,
185 : : unsigned access)
186 : : {
187 : : struct node_access_nodes *c;
188 : : struct node *node;
189 : : int i;
190 : :
191 : : if (WARN_ON_ONCE(!node_online(nid)))
192 : : return;
193 : :
194 : : node = node_devices[nid];
195 : : c = node_init_node_access(node, access);
196 : : if (!c)
197 : : return;
198 : :
199 : : c->hmem_attrs = *hmem_attrs;
200 : : for (i = 0; access_attrs[i] != NULL; i++) {
201 : : if (sysfs_add_file_to_group(&c->dev.kobj, access_attrs[i],
202 : : "initiators")) {
203 : : pr_info("failed to add performance attribute to node %d\n",
204 : : nid);
205 : : break;
206 : : }
207 : : }
208 : : }
209 : :
210 : : /**
211 : : * struct node_cache_info - Internal tracking for memory node caches
212 : : * @dev: Device represeting the cache level
213 : : * @node: List element for tracking in the node
214 : : * @cache_attrs:Attributes for this cache level
215 : : */
216 : : struct node_cache_info {
217 : : struct device dev;
218 : : struct list_head node;
219 : : struct node_cache_attrs cache_attrs;
220 : : };
221 : : #define to_cache_info(device) container_of(device, struct node_cache_info, dev)
222 : :
223 : : #define CACHE_ATTR(name, fmt) \
224 : : static ssize_t name##_show(struct device *dev, \
225 : : struct device_attribute *attr, \
226 : : char *buf) \
227 : : { \
228 : : return sprintf(buf, fmt "\n", to_cache_info(dev)->cache_attrs.name);\
229 : : } \
230 : : DEVICE_ATTR_RO(name);
231 : :
232 : : CACHE_ATTR(size, "%llu")
233 : : CACHE_ATTR(line_size, "%u")
234 : : CACHE_ATTR(indexing, "%u")
235 : : CACHE_ATTR(write_policy, "%u")
236 : :
237 : : static struct attribute *cache_attrs[] = {
238 : : &dev_attr_indexing.attr,
239 : : &dev_attr_size.attr,
240 : : &dev_attr_line_size.attr,
241 : : &dev_attr_write_policy.attr,
242 : : NULL,
243 : : };
244 : : ATTRIBUTE_GROUPS(cache);
245 : :
246 : : static void node_cache_release(struct device *dev)
247 : : {
248 : : kfree(dev);
249 : : }
250 : :
251 : : static void node_cacheinfo_release(struct device *dev)
252 : : {
253 : : struct node_cache_info *info = to_cache_info(dev);
254 : : kfree(info);
255 : : }
256 : :
257 : : static void node_init_cache_dev(struct node *node)
258 : : {
259 : : struct device *dev;
260 : :
261 : : dev = kzalloc(sizeof(*dev), GFP_KERNEL);
262 : : if (!dev)
263 : : return;
264 : :
265 : : dev->parent = &node->dev;
266 : : dev->release = node_cache_release;
267 : : if (dev_set_name(dev, "memory_side_cache"))
268 : : goto free_dev;
269 : :
270 : : if (device_register(dev))
271 : : goto free_name;
272 : :
273 : : pm_runtime_no_callbacks(dev);
274 : : node->cache_dev = dev;
275 : : return;
276 : : free_name:
277 : : kfree_const(dev->kobj.name);
278 : : free_dev:
279 : : kfree(dev);
280 : : }
281 : :
282 : : /**
283 : : * node_add_cache() - add cache attribute to a memory node
284 : : * @nid: Node identifier that has new cache attributes
285 : : * @cache_attrs: Attributes for the cache being added
286 : : */
287 : : void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs)
288 : : {
289 : : struct node_cache_info *info;
290 : : struct device *dev;
291 : : struct node *node;
292 : :
293 : : if (!node_online(nid) || !node_devices[nid])
294 : : return;
295 : :
296 : : node = node_devices[nid];
297 : : list_for_each_entry(info, &node->cache_attrs, node) {
298 : : if (info->cache_attrs.level == cache_attrs->level) {
299 : : dev_warn(&node->dev,
300 : : "attempt to add duplicate cache level:%d\n",
301 : : cache_attrs->level);
302 : : return;
303 : : }
304 : : }
305 : :
306 : : if (!node->cache_dev)
307 : : node_init_cache_dev(node);
308 : : if (!node->cache_dev)
309 : : return;
310 : :
311 : : info = kzalloc(sizeof(*info), GFP_KERNEL);
312 : : if (!info)
313 : : return;
314 : :
315 : : dev = &info->dev;
316 : : dev->parent = node->cache_dev;
317 : : dev->release = node_cacheinfo_release;
318 : : dev->groups = cache_groups;
319 : : if (dev_set_name(dev, "index%d", cache_attrs->level))
320 : : goto free_cache;
321 : :
322 : : info->cache_attrs = *cache_attrs;
323 : : if (device_register(dev)) {
324 : : dev_warn(&node->dev, "failed to add cache level:%d\n",
325 : : cache_attrs->level);
326 : : goto free_name;
327 : : }
328 : : pm_runtime_no_callbacks(dev);
329 : : list_add_tail(&info->node, &node->cache_attrs);
330 : : return;
331 : : free_name:
332 : : kfree_const(dev->kobj.name);
333 : : free_cache:
334 : : kfree(info);
335 : : }
336 : :
337 : : static void node_remove_caches(struct node *node)
338 : : {
339 : : struct node_cache_info *info, *next;
340 : :
341 : : if (!node->cache_dev)
342 : : return;
343 : :
344 : : list_for_each_entry_safe(info, next, &node->cache_attrs, node) {
345 : : list_del(&info->node);
346 : : device_unregister(&info->dev);
347 : : }
348 : : device_unregister(node->cache_dev);
349 : : }
350 : :
351 : : static void node_init_caches(unsigned int nid)
352 : : {
353 : : INIT_LIST_HEAD(&node_devices[nid]->cache_attrs);
354 : : }
355 : : #else
356 : 78 : static void node_init_caches(unsigned int nid) { }
357 : 0 : static void node_remove_caches(struct node *node) { }
358 : : #endif
359 : :
360 : : #define K(x) ((x) << (PAGE_SHIFT - 10))
361 : 0 : static ssize_t node_read_meminfo(struct device *dev,
362 : : struct device_attribute *attr, char *buf)
363 : : {
364 : 0 : int n;
365 : 0 : int nid = dev->id;
366 : 0 : struct pglist_data *pgdat = NODE_DATA(nid);
367 : 0 : struct sysinfo i;
368 : 0 : unsigned long sreclaimable, sunreclaimable;
369 : :
370 : 0 : si_meminfo_node(&i, nid);
371 : 0 : sreclaimable = node_page_state(pgdat, NR_SLAB_RECLAIMABLE);
372 : 0 : sunreclaimable = node_page_state(pgdat, NR_SLAB_UNRECLAIMABLE);
373 : 0 : n = sprintf(buf,
374 : : "Node %d MemTotal: %8lu kB\n"
375 : : "Node %d MemFree: %8lu kB\n"
376 : : "Node %d MemUsed: %8lu kB\n"
377 : : "Node %d Active: %8lu kB\n"
378 : : "Node %d Inactive: %8lu kB\n"
379 : : "Node %d Active(anon): %8lu kB\n"
380 : : "Node %d Inactive(anon): %8lu kB\n"
381 : : "Node %d Active(file): %8lu kB\n"
382 : : "Node %d Inactive(file): %8lu kB\n"
383 : : "Node %d Unevictable: %8lu kB\n"
384 : : "Node %d Mlocked: %8lu kB\n",
385 : : nid, K(i.totalram),
386 : : nid, K(i.freeram),
387 : 0 : nid, K(i.totalram - i.freeram),
388 : 0 : nid, K(node_page_state(pgdat, NR_ACTIVE_ANON) +
389 : : node_page_state(pgdat, NR_ACTIVE_FILE)),
390 : 0 : nid, K(node_page_state(pgdat, NR_INACTIVE_ANON) +
391 : : node_page_state(pgdat, NR_INACTIVE_FILE)),
392 : 0 : nid, K(node_page_state(pgdat, NR_ACTIVE_ANON)),
393 : 0 : nid, K(node_page_state(pgdat, NR_INACTIVE_ANON)),
394 : 0 : nid, K(node_page_state(pgdat, NR_ACTIVE_FILE)),
395 : 0 : nid, K(node_page_state(pgdat, NR_INACTIVE_FILE)),
396 : 0 : nid, K(node_page_state(pgdat, NR_UNEVICTABLE)),
397 : 0 : nid, K(sum_zone_node_page_state(nid, NR_MLOCK)));
398 : :
399 : : #ifdef CONFIG_HIGHMEM
400 : : n += sprintf(buf + n,
401 : : "Node %d HighTotal: %8lu kB\n"
402 : : "Node %d HighFree: %8lu kB\n"
403 : : "Node %d LowTotal: %8lu kB\n"
404 : : "Node %d LowFree: %8lu kB\n",
405 : : nid, K(i.totalhigh),
406 : : nid, K(i.freehigh),
407 : : nid, K(i.totalram - i.totalhigh),
408 : : nid, K(i.freeram - i.freehigh));
409 : : #endif
410 : 0 : n += sprintf(buf + n,
411 : : "Node %d Dirty: %8lu kB\n"
412 : : "Node %d Writeback: %8lu kB\n"
413 : : "Node %d FilePages: %8lu kB\n"
414 : : "Node %d Mapped: %8lu kB\n"
415 : : "Node %d AnonPages: %8lu kB\n"
416 : : "Node %d Shmem: %8lu kB\n"
417 : : "Node %d KernelStack: %8lu kB\n"
418 : : "Node %d PageTables: %8lu kB\n"
419 : : "Node %d NFS_Unstable: %8lu kB\n"
420 : : "Node %d Bounce: %8lu kB\n"
421 : : "Node %d WritebackTmp: %8lu kB\n"
422 : : "Node %d KReclaimable: %8lu kB\n"
423 : : "Node %d Slab: %8lu kB\n"
424 : : "Node %d SReclaimable: %8lu kB\n"
425 : : "Node %d SUnreclaim: %8lu kB\n"
426 : : #ifdef CONFIG_TRANSPARENT_HUGEPAGE
427 : : "Node %d AnonHugePages: %8lu kB\n"
428 : : "Node %d ShmemHugePages: %8lu kB\n"
429 : : "Node %d ShmemPmdMapped: %8lu kB\n"
430 : : "Node %d FileHugePages: %8lu kB\n"
431 : : "Node %d FilePmdMapped: %8lu kB\n"
432 : : #endif
433 : : ,
434 : 0 : nid, K(node_page_state(pgdat, NR_FILE_DIRTY)),
435 : 0 : nid, K(node_page_state(pgdat, NR_WRITEBACK)),
436 : 0 : nid, K(node_page_state(pgdat, NR_FILE_PAGES)),
437 : 0 : nid, K(node_page_state(pgdat, NR_FILE_MAPPED)),
438 : 0 : nid, K(node_page_state(pgdat, NR_ANON_MAPPED)),
439 : 0 : nid, K(i.sharedram),
440 : : nid, sum_zone_node_page_state(nid, NR_KERNEL_STACK_KB),
441 : 0 : nid, K(sum_zone_node_page_state(nid, NR_PAGETABLE)),
442 : 0 : nid, K(node_page_state(pgdat, NR_UNSTABLE_NFS)),
443 : 0 : nid, K(sum_zone_node_page_state(nid, NR_BOUNCE)),
444 : 0 : nid, K(node_page_state(pgdat, NR_WRITEBACK_TEMP)),
445 : 0 : nid, K(sreclaimable +
446 : : node_page_state(pgdat, NR_KERNEL_MISC_RECLAIMABLE)),
447 : 0 : nid, K(sreclaimable + sunreclaimable),
448 : : nid, K(sreclaimable),
449 : : nid, K(sunreclaimable)
450 : : #ifdef CONFIG_TRANSPARENT_HUGEPAGE
451 : : ,
452 : : nid, K(node_page_state(pgdat, NR_ANON_THPS) *
453 : : HPAGE_PMD_NR),
454 : : nid, K(node_page_state(pgdat, NR_SHMEM_THPS) *
455 : : HPAGE_PMD_NR),
456 : : nid, K(node_page_state(pgdat, NR_SHMEM_PMDMAPPED) *
457 : : HPAGE_PMD_NR),
458 : : nid, K(node_page_state(pgdat, NR_FILE_THPS) *
459 : : HPAGE_PMD_NR),
460 : : nid, K(node_page_state(pgdat, NR_FILE_PMDMAPPED) *
461 : : HPAGE_PMD_NR)
462 : : #endif
463 : : );
464 : 0 : n += hugetlb_report_node_meminfo(nid, buf + n);
465 : 0 : return n;
466 : : }
467 : :
468 : : #undef K
469 : : static DEVICE_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
470 : :
471 : 0 : static ssize_t node_read_numastat(struct device *dev,
472 : : struct device_attribute *attr, char *buf)
473 : : {
474 : 0 : return sprintf(buf,
475 : : "numa_hit %lu\n"
476 : : "numa_miss %lu\n"
477 : : "numa_foreign %lu\n"
478 : : "interleave_hit %lu\n"
479 : : "local_node %lu\n"
480 : : "other_node %lu\n",
481 : 0 : sum_zone_numa_state(dev->id, NUMA_HIT),
482 : 0 : sum_zone_numa_state(dev->id, NUMA_MISS),
483 : 0 : sum_zone_numa_state(dev->id, NUMA_FOREIGN),
484 : 0 : sum_zone_numa_state(dev->id, NUMA_INTERLEAVE_HIT),
485 : 0 : sum_zone_numa_state(dev->id, NUMA_LOCAL),
486 : 0 : sum_zone_numa_state(dev->id, NUMA_OTHER));
487 : : }
488 : : static DEVICE_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
489 : :
490 : 0 : static ssize_t node_read_vmstat(struct device *dev,
491 : : struct device_attribute *attr, char *buf)
492 : : {
493 : 0 : int nid = dev->id;
494 : 0 : struct pglist_data *pgdat = NODE_DATA(nid);
495 : 0 : int i;
496 : 0 : int n = 0;
497 : :
498 [ # # ]: 0 : for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
499 : 0 : n += sprintf(buf+n, "%s %lu\n", zone_stat_name(i),
500 : : sum_zone_node_page_state(nid, i));
501 : :
502 : : #ifdef CONFIG_NUMA
503 [ # # ]: 0 : for (i = 0; i < NR_VM_NUMA_STAT_ITEMS; i++)
504 : 0 : n += sprintf(buf+n, "%s %lu\n", numa_stat_name(i),
505 : : sum_zone_numa_state(nid, i));
506 : : #endif
507 : :
508 [ # # ]: 0 : for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
509 : 0 : n += sprintf(buf+n, "%s %lu\n", node_stat_name(i),
510 : : node_page_state(pgdat, i));
511 : :
512 : 0 : return n;
513 : : }
514 : : static DEVICE_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL);
515 : :
516 : 0 : static ssize_t node_read_distance(struct device *dev,
517 : : struct device_attribute *attr, char *buf)
518 : : {
519 : 0 : int nid = dev->id;
520 : 0 : int len = 0;
521 : 0 : int i;
522 : :
523 : : /*
524 : : * buf is currently PAGE_SIZE in length and each node needs 4 chars
525 : : * at the most (distance + space or newline).
526 : : */
527 : 0 : BUILD_BUG_ON(MAX_NUMNODES * 4 > PAGE_SIZE);
528 : :
529 [ # # ]: 0 : for_each_online_node(i)
530 [ # # ]: 0 : len += sprintf(buf + len, "%s%d", i ? " " : "", node_distance(nid, i));
531 : :
532 : 0 : len += sprintf(buf + len, "\n");
533 : 0 : return len;
534 : : }
535 : : static DEVICE_ATTR(distance, S_IRUGO, node_read_distance, NULL);
536 : :
537 : : static struct attribute *node_dev_attrs[] = {
538 : : &dev_attr_cpumap.attr,
539 : : &dev_attr_cpulist.attr,
540 : : &dev_attr_meminfo.attr,
541 : : &dev_attr_numastat.attr,
542 : : &dev_attr_distance.attr,
543 : : &dev_attr_vmstat.attr,
544 : : NULL
545 : : };
546 : : ATTRIBUTE_GROUPS(node_dev);
547 : :
548 : : #ifdef CONFIG_HUGETLBFS
549 : : /*
550 : : * hugetlbfs per node attributes registration interface:
551 : : * When/if hugetlb[fs] subsystem initializes [sometime after this module],
552 : : * it will register its per node attributes for all online nodes with
553 : : * memory. It will also call register_hugetlbfs_with_node(), below, to
554 : : * register its attribute registration functions with this node driver.
555 : : * Once these hooks have been initialized, the node driver will call into
556 : : * the hugetlb module to [un]register attributes for hot-plugged nodes.
557 : : */
558 : : static node_registration_func_t __hugetlb_register_node;
559 : : static node_registration_func_t __hugetlb_unregister_node;
560 : :
561 : 78 : static inline bool hugetlb_register_node(struct node *node)
562 : : {
563 [ - + - - ]: 78 : if (__hugetlb_register_node &&
564 : 0 : node_state(node->dev.id, N_MEMORY)) {
565 : 0 : __hugetlb_register_node(node);
566 : 0 : return true;
567 : : }
568 : : return false;
569 : : }
570 : :
571 : 0 : static inline void hugetlb_unregister_node(struct node *node)
572 : : {
573 : 0 : if (__hugetlb_unregister_node)
574 : 0 : __hugetlb_unregister_node(node);
575 : : }
576 : :
577 : 78 : void register_hugetlbfs_with_node(node_registration_func_t doregister,
578 : : node_registration_func_t unregister)
579 : : {
580 : 78 : __hugetlb_register_node = doregister;
581 : 78 : __hugetlb_unregister_node = unregister;
582 : 78 : }
583 : : #else
584 : : static inline void hugetlb_register_node(struct node *node) {}
585 : :
586 : : static inline void hugetlb_unregister_node(struct node *node) {}
587 : : #endif
588 : :
589 : 0 : static void node_device_release(struct device *dev)
590 : : {
591 : 0 : struct node *node = to_node(dev);
592 : :
593 : : #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS)
594 : : /*
595 : : * We schedule the work only when a memory section is
596 : : * onlined/offlined on this node. When we come here,
597 : : * all the memory on this node has been offlined,
598 : : * so we won't enqueue new work to this work.
599 : : *
600 : : * The work is using node->node_work, so we should
601 : : * flush work before freeing the memory.
602 : : */
603 : : flush_work(&node->node_work);
604 : : #endif
605 : 0 : kfree(node);
606 : 0 : }
607 : :
608 : : /*
609 : : * register_node - Setup a sysfs device for a node.
610 : : * @num - Node number to use when creating the device.
611 : : *
612 : : * Initialize and register the node device.
613 : : */
614 : 78 : static int register_node(struct node *node, int num)
615 : : {
616 : 78 : int error;
617 : :
618 : 78 : node->dev.id = num;
619 : 78 : node->dev.bus = &node_subsys;
620 : 78 : node->dev.release = node_device_release;
621 : 78 : node->dev.groups = node_dev_groups;
622 : 78 : error = device_register(&node->dev);
623 : :
624 [ - + ]: 78 : if (error)
625 : 0 : put_device(&node->dev);
626 : : else {
627 : 78 : hugetlb_register_node(node);
628 : :
629 : 78 : compaction_register_node(node);
630 : : }
631 : 78 : return error;
632 : : }
633 : :
634 : : /**
635 : : * unregister_node - unregister a node device
636 : : * @node: node going away
637 : : *
638 : : * Unregisters a node device @node. All the devices on the node must be
639 : : * unregistered before calling this function.
640 : : */
641 : 0 : void unregister_node(struct node *node)
642 : : {
643 [ # # ]: 0 : hugetlb_unregister_node(node); /* no-op, if memoryless node */
644 : 0 : node_remove_accesses(node);
645 : 0 : node_remove_caches(node);
646 : 0 : device_unregister(&node->dev);
647 : 0 : }
648 : :
649 : : struct node *node_devices[MAX_NUMNODES];
650 : :
651 : : /*
652 : : * register cpu under node
653 : : */
654 : 156 : int register_cpu_under_node(unsigned int cpu, unsigned int nid)
655 : : {
656 : 156 : int ret;
657 : 156 : struct device *obj;
658 : :
659 [ + - ]: 156 : if (!node_online(nid))
660 : : return 0;
661 : :
662 : 156 : obj = get_cpu_device(cpu);
663 [ + + ]: 156 : if (!obj)
664 : : return 0;
665 : :
666 : 78 : ret = sysfs_create_link(&node_devices[nid]->dev.kobj,
667 : : &obj->kobj,
668 : : kobject_name(&obj->kobj));
669 [ + - ]: 78 : if (ret)
670 : : return ret;
671 : :
672 : 78 : return sysfs_create_link(&obj->kobj,
673 : : &node_devices[nid]->dev.kobj,
674 : 78 : kobject_name(&node_devices[nid]->dev.kobj));
675 : : }
676 : :
677 : : /**
678 : : * register_memory_node_under_compute_node - link memory node to its compute
679 : : * node for a given access class.
680 : : * @mem_nid: Memory node number
681 : : * @cpu_nid: Cpu node number
682 : : * @access: Access class to register
683 : : *
684 : : * Description:
685 : : * For use with platforms that may have separate memory and compute nodes.
686 : : * This function will export node relationships linking which memory
687 : : * initiator nodes can access memory targets at a given ranked access
688 : : * class.
689 : : */
690 : 0 : int register_memory_node_under_compute_node(unsigned int mem_nid,
691 : : unsigned int cpu_nid,
692 : : unsigned access)
693 : : {
694 : 0 : struct node *init_node, *targ_node;
695 : 0 : struct node_access_nodes *initiator, *target;
696 : 0 : int ret;
697 : :
698 [ # # # # ]: 0 : if (!node_online(cpu_nid) || !node_online(mem_nid))
699 : 0 : return -ENODEV;
700 : :
701 : 0 : init_node = node_devices[cpu_nid];
702 : 0 : targ_node = node_devices[mem_nid];
703 : 0 : initiator = node_init_node_access(init_node, access);
704 : 0 : target = node_init_node_access(targ_node, access);
705 [ # # ]: 0 : if (!initiator || !target)
706 : : return -ENOMEM;
707 : :
708 [ # # ]: 0 : ret = sysfs_add_link_to_group(&initiator->dev.kobj, "targets",
709 : : &targ_node->dev.kobj,
710 : : dev_name(&targ_node->dev));
711 [ # # ]: 0 : if (ret)
712 : : return ret;
713 : :
714 [ # # ]: 0 : ret = sysfs_add_link_to_group(&target->dev.kobj, "initiators",
715 : : &init_node->dev.kobj,
716 : : dev_name(&init_node->dev));
717 [ # # ]: 0 : if (ret)
718 : 0 : goto err;
719 : :
720 : : return 0;
721 : : err:
722 [ # # ]: 0 : sysfs_remove_link_from_group(&initiator->dev.kobj, "targets",
723 : : dev_name(&targ_node->dev));
724 : 0 : return ret;
725 : : }
726 : :
727 : 0 : int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
728 : : {
729 : 0 : struct device *obj;
730 : :
731 [ # # ]: 0 : if (!node_online(nid))
732 : : return 0;
733 : :
734 : 0 : obj = get_cpu_device(cpu);
735 [ # # ]: 0 : if (!obj)
736 : : return 0;
737 : :
738 : 0 : sysfs_remove_link(&node_devices[nid]->dev.kobj,
739 : : kobject_name(&obj->kobj));
740 : 0 : sysfs_remove_link(&obj->kobj,
741 : 0 : kobject_name(&node_devices[nid]->dev.kobj));
742 : :
743 : 0 : return 0;
744 : : }
745 : :
746 : : #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
747 : : static int __ref get_nid_for_pfn(unsigned long pfn)
748 : : {
749 : : if (!pfn_valid_within(pfn))
750 : : return -1;
751 : : #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
752 : : if (system_state < SYSTEM_RUNNING)
753 : : return early_pfn_to_nid(pfn);
754 : : #endif
755 : : return pfn_to_nid(pfn);
756 : : }
757 : :
758 : : /* register memory section under specified node if it spans that node */
759 : : static int register_mem_sect_under_node(struct memory_block *mem_blk,
760 : : void *arg)
761 : : {
762 : : unsigned long memory_block_pfns = memory_block_size_bytes() / PAGE_SIZE;
763 : : unsigned long start_pfn = section_nr_to_pfn(mem_blk->start_section_nr);
764 : : unsigned long end_pfn = start_pfn + memory_block_pfns - 1;
765 : : int ret, nid = *(int *)arg;
766 : : unsigned long pfn;
767 : :
768 : : for (pfn = start_pfn; pfn <= end_pfn; pfn++) {
769 : : int page_nid;
770 : :
771 : : /*
772 : : * memory block could have several absent sections from start.
773 : : * skip pfn range from absent section
774 : : */
775 : : if (!pfn_present(pfn)) {
776 : : pfn = round_down(pfn + PAGES_PER_SECTION,
777 : : PAGES_PER_SECTION) - 1;
778 : : continue;
779 : : }
780 : :
781 : : /*
782 : : * We need to check if page belongs to nid only for the boot
783 : : * case, during hotplug we know that all pages in the memory
784 : : * block belong to the same node.
785 : : */
786 : : if (system_state == SYSTEM_BOOTING) {
787 : : page_nid = get_nid_for_pfn(pfn);
788 : : if (page_nid < 0)
789 : : continue;
790 : : if (page_nid != nid)
791 : : continue;
792 : : }
793 : :
794 : : /*
795 : : * If this memory block spans multiple nodes, we only indicate
796 : : * the last processed node.
797 : : */
798 : : mem_blk->nid = nid;
799 : :
800 : : ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
801 : : &mem_blk->dev.kobj,
802 : : kobject_name(&mem_blk->dev.kobj));
803 : : if (ret)
804 : : return ret;
805 : :
806 : : return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
807 : : &node_devices[nid]->dev.kobj,
808 : : kobject_name(&node_devices[nid]->dev.kobj));
809 : : }
810 : : /* mem section does not span the specified node */
811 : : return 0;
812 : : }
813 : :
814 : : /*
815 : : * Unregister a memory block device under the node it spans. Memory blocks
816 : : * with multiple nodes cannot be offlined and therefore also never be removed.
817 : : */
818 : : void unregister_memory_block_under_nodes(struct memory_block *mem_blk)
819 : : {
820 : : if (mem_blk->nid == NUMA_NO_NODE)
821 : : return;
822 : :
823 : : sysfs_remove_link(&node_devices[mem_blk->nid]->dev.kobj,
824 : : kobject_name(&mem_blk->dev.kobj));
825 : : sysfs_remove_link(&mem_blk->dev.kobj,
826 : : kobject_name(&node_devices[mem_blk->nid]->dev.kobj));
827 : : }
828 : :
829 : : int link_mem_sections(int nid, unsigned long start_pfn, unsigned long end_pfn)
830 : : {
831 : : return walk_memory_blocks(PFN_PHYS(start_pfn),
832 : : PFN_PHYS(end_pfn - start_pfn), (void *)&nid,
833 : : register_mem_sect_under_node);
834 : : }
835 : :
836 : : #ifdef CONFIG_HUGETLBFS
837 : : /*
838 : : * Handle per node hstate attribute [un]registration on transistions
839 : : * to/from memoryless state.
840 : : */
841 : : static void node_hugetlb_work(struct work_struct *work)
842 : : {
843 : : struct node *node = container_of(work, struct node, node_work);
844 : :
845 : : /*
846 : : * We only get here when a node transitions to/from memoryless state.
847 : : * We can detect which transition occurred by examining whether the
848 : : * node has memory now. hugetlb_register_node() already check this
849 : : * so we try to register the attributes. If that fails, then the
850 : : * node has transitioned to memoryless, try to unregister the
851 : : * attributes.
852 : : */
853 : : if (!hugetlb_register_node(node))
854 : : hugetlb_unregister_node(node);
855 : : }
856 : :
857 : : static void init_node_hugetlb_work(int nid)
858 : : {
859 : : INIT_WORK(&node_devices[nid]->node_work, node_hugetlb_work);
860 : : }
861 : :
862 : : static int node_memory_callback(struct notifier_block *self,
863 : : unsigned long action, void *arg)
864 : : {
865 : : struct memory_notify *mnb = arg;
866 : : int nid = mnb->status_change_nid;
867 : :
868 : : switch (action) {
869 : : case MEM_ONLINE:
870 : : case MEM_OFFLINE:
871 : : /*
872 : : * offload per node hstate [un]registration to a work thread
873 : : * when transitioning to/from memoryless state.
874 : : */
875 : : if (nid != NUMA_NO_NODE)
876 : : schedule_work(&node_devices[nid]->node_work);
877 : : break;
878 : :
879 : : case MEM_GOING_ONLINE:
880 : : case MEM_GOING_OFFLINE:
881 : : case MEM_CANCEL_ONLINE:
882 : : case MEM_CANCEL_OFFLINE:
883 : : default:
884 : : break;
885 : : }
886 : :
887 : : return NOTIFY_OK;
888 : : }
889 : : #endif /* CONFIG_HUGETLBFS */
890 : : #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
891 : :
892 : : #if !defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || \
893 : : !defined(CONFIG_HUGETLBFS)
894 : : static inline int node_memory_callback(struct notifier_block *self,
895 : : unsigned long action, void *arg)
896 : : {
897 : : return NOTIFY_OK;
898 : : }
899 : :
900 : 78 : static void init_node_hugetlb_work(int nid) { }
901 : :
902 : : #endif
903 : :
904 : 78 : int __register_one_node(int nid)
905 : : {
906 : 78 : int error;
907 : 78 : int cpu;
908 : :
909 : 78 : node_devices[nid] = kzalloc(sizeof(struct node), GFP_KERNEL);
910 [ + - ]: 78 : if (!node_devices[nid])
911 : : return -ENOMEM;
912 : :
913 : 78 : error = register_node(node_devices[nid], nid);
914 : :
915 : : /* link cpu under this node */
916 [ + + ]: 234 : for_each_present_cpu(cpu) {
917 [ + - ]: 78 : if (cpu_to_node(cpu) == nid)
918 : 78 : register_cpu_under_node(cpu, nid);
919 : : }
920 : :
921 : 78 : INIT_LIST_HEAD(&node_devices[nid]->access_list);
922 : : /* initialize work queue for memory hot plug */
923 : 78 : init_node_hugetlb_work(nid);
924 : 78 : node_init_caches(nid);
925 : :
926 : 78 : return error;
927 : : }
928 : :
929 : 0 : void unregister_one_node(int nid)
930 : : {
931 [ # # ]: 0 : if (!node_devices[nid])
932 : : return;
933 : :
934 : 0 : unregister_node(node_devices[nid]);
935 : 0 : node_devices[nid] = NULL;
936 : : }
937 : :
938 : : /*
939 : : * node states attributes
940 : : */
941 : :
942 : 0 : static ssize_t print_nodes_state(enum node_states state, char *buf)
943 : : {
944 : 0 : int n;
945 : :
946 : 0 : n = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
947 [ # # ]: 0 : nodemask_pr_args(&node_states[state]));
948 : 0 : buf[n++] = '\n';
949 : 0 : buf[n] = '\0';
950 : 0 : return n;
951 : : }
952 : :
953 : : struct node_attr {
954 : : struct device_attribute attr;
955 : : enum node_states state;
956 : : };
957 : :
958 : 0 : static ssize_t show_node_state(struct device *dev,
959 : : struct device_attribute *attr, char *buf)
960 : : {
961 : 0 : struct node_attr *na = container_of(attr, struct node_attr, attr);
962 : 0 : return print_nodes_state(na->state, buf);
963 : : }
964 : :
965 : : #define _NODE_ATTR(name, state) \
966 : : { __ATTR(name, 0444, show_node_state, NULL), state }
967 : :
968 : : static struct node_attr node_state_attr[] = {
969 : : [N_POSSIBLE] = _NODE_ATTR(possible, N_POSSIBLE),
970 : : [N_ONLINE] = _NODE_ATTR(online, N_ONLINE),
971 : : [N_NORMAL_MEMORY] = _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
972 : : #ifdef CONFIG_HIGHMEM
973 : : [N_HIGH_MEMORY] = _NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
974 : : #endif
975 : : [N_MEMORY] = _NODE_ATTR(has_memory, N_MEMORY),
976 : : [N_CPU] = _NODE_ATTR(has_cpu, N_CPU),
977 : : };
978 : :
979 : : static struct attribute *node_state_attrs[] = {
980 : : &node_state_attr[N_POSSIBLE].attr.attr,
981 : : &node_state_attr[N_ONLINE].attr.attr,
982 : : &node_state_attr[N_NORMAL_MEMORY].attr.attr,
983 : : #ifdef CONFIG_HIGHMEM
984 : : &node_state_attr[N_HIGH_MEMORY].attr.attr,
985 : : #endif
986 : : &node_state_attr[N_MEMORY].attr.attr,
987 : : &node_state_attr[N_CPU].attr.attr,
988 : : NULL
989 : : };
990 : :
991 : : static struct attribute_group memory_root_attr_group = {
992 : : .attrs = node_state_attrs,
993 : : };
994 : :
995 : : static const struct attribute_group *cpu_root_attr_groups[] = {
996 : : &memory_root_attr_group,
997 : : NULL,
998 : : };
999 : :
1000 : : #define NODE_CALLBACK_PRI 2 /* lower than SLAB */
1001 : 78 : static int __init register_node_type(void)
1002 : : {
1003 : 78 : int ret;
1004 : :
1005 : 78 : BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES);
1006 : 78 : BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES);
1007 : :
1008 : 78 : ret = subsys_system_register(&node_subsys, cpu_root_attr_groups);
1009 : 78 : if (!ret) {
1010 : : static struct notifier_block node_memory_callback_nb = {
1011 : : .notifier_call = node_memory_callback,
1012 : : .priority = NODE_CALLBACK_PRI,
1013 : : };
1014 : : register_hotmemory_notifier(&node_memory_callback_nb);
1015 : : }
1016 : :
1017 : : /*
1018 : : * Note: we're not going to unregister the node class if we fail
1019 : : * to register the node state class attribute files.
1020 : : */
1021 : 78 : return ret;
1022 : : }
1023 : : postcore_initcall(register_node_type);
|