node.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * drivers/base/node.c - basic Node class support
  3. */
  4. #include <linux/sysdev.h>
  5. #include <linux/module.h>
  6. #include <linux/init.h>
  7. #include <linux/mm.h>
  8. #include <linux/node.h>
  9. #include <linux/hugetlb.h>
  10. #include <linux/cpumask.h>
  11. #include <linux/topology.h>
  12. #include <linux/nodemask.h>
  13. static struct sysdev_class node_class = {
  14. set_kset_name("node"),
  15. };
  16. static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
  17. {
  18. struct node *node_dev = to_node(dev);
  19. cpumask_t mask = node_to_cpumask(node_dev->sysdev.id);
  20. int len;
  21. /* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */
  22. BUILD_BUG_ON(MAX_NUMNODES/4 > PAGE_SIZE/2);
  23. len = cpumask_scnprintf(buf, PAGE_SIZE-1, mask);
  24. len += sprintf(buf + len, "\n");
  25. return len;
  26. }
  27. static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumap, NULL);
  28. #define K(x) ((x) << (PAGE_SHIFT - 10))
  29. static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
  30. {
  31. int n;
  32. int nid = dev->id;
  33. struct sysinfo i;
  34. struct page_state ps;
  35. unsigned long inactive;
  36. unsigned long active;
  37. unsigned long free;
  38. si_meminfo_node(&i, nid);
  39. get_page_state_node(&ps, nid);
  40. __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid));
  41. /* Check for negative values in these approximate counters */
  42. if ((long)ps.nr_dirty < 0)
  43. ps.nr_dirty = 0;
  44. if ((long)ps.nr_writeback < 0)
  45. ps.nr_writeback = 0;
  46. if ((long)ps.nr_mapped < 0)
  47. ps.nr_mapped = 0;
  48. if ((long)ps.nr_slab < 0)
  49. ps.nr_slab = 0;
  50. n = sprintf(buf, "\n"
  51. "Node %d MemTotal: %8lu kB\n"
  52. "Node %d MemFree: %8lu kB\n"
  53. "Node %d MemUsed: %8lu kB\n"
  54. "Node %d Active: %8lu kB\n"
  55. "Node %d Inactive: %8lu kB\n"
  56. "Node %d HighTotal: %8lu kB\n"
  57. "Node %d HighFree: %8lu kB\n"
  58. "Node %d LowTotal: %8lu kB\n"
  59. "Node %d LowFree: %8lu kB\n"
  60. "Node %d Dirty: %8lu kB\n"
  61. "Node %d Writeback: %8lu kB\n"
  62. "Node %d Mapped: %8lu kB\n"
  63. "Node %d Slab: %8lu kB\n",
  64. nid, K(i.totalram),
  65. nid, K(i.freeram),
  66. nid, K(i.totalram - i.freeram),
  67. nid, K(active),
  68. nid, K(inactive),
  69. nid, K(i.totalhigh),
  70. nid, K(i.freehigh),
  71. nid, K(i.totalram - i.totalhigh),
  72. nid, K(i.freeram - i.freehigh),
  73. nid, K(ps.nr_dirty),
  74. nid, K(ps.nr_writeback),
  75. nid, K(ps.nr_mapped),
  76. nid, K(ps.nr_slab));
  77. n += hugetlb_report_node_meminfo(nid, buf + n);
  78. return n;
  79. }
  80. #undef K
  81. static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
  82. static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
  83. {
  84. unsigned long numa_hit, numa_miss, interleave_hit, numa_foreign;
  85. unsigned long local_node, other_node;
  86. int i, cpu;
  87. pg_data_t *pg = NODE_DATA(dev->id);
  88. numa_hit = 0;
  89. numa_miss = 0;
  90. interleave_hit = 0;
  91. numa_foreign = 0;
  92. local_node = 0;
  93. other_node = 0;
  94. for (i = 0; i < MAX_NR_ZONES; i++) {
  95. struct zone *z = &pg->node_zones[i];
  96. for (cpu = 0; cpu < NR_CPUS; cpu++) {
  97. struct per_cpu_pageset *ps = zone_pcp(z,cpu);
  98. numa_hit += ps->numa_hit;
  99. numa_miss += ps->numa_miss;
  100. numa_foreign += ps->numa_foreign;
  101. interleave_hit += ps->interleave_hit;
  102. local_node += ps->local_node;
  103. other_node += ps->other_node;
  104. }
  105. }
  106. return sprintf(buf,
  107. "numa_hit %lu\n"
  108. "numa_miss %lu\n"
  109. "numa_foreign %lu\n"
  110. "interleave_hit %lu\n"
  111. "local_node %lu\n"
  112. "other_node %lu\n",
  113. numa_hit,
  114. numa_miss,
  115. numa_foreign,
  116. interleave_hit,
  117. local_node,
  118. other_node);
  119. }
  120. static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
  121. static ssize_t node_read_distance(struct sys_device * dev, char * buf)
  122. {
  123. int nid = dev->id;
  124. int len = 0;
  125. int i;
  126. /* buf currently PAGE_SIZE, need ~4 chars per node */
  127. BUILD_BUG_ON(MAX_NUMNODES*4 > PAGE_SIZE/2);
  128. for_each_online_node(i)
  129. len += sprintf(buf + len, "%s%d", i ? " " : "", node_distance(nid, i));
  130. len += sprintf(buf + len, "\n");
  131. return len;
  132. }
  133. static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL);
  134. /*
  135. * register_node - Setup a driverfs device for a node.
  136. * @num - Node number to use when creating the device.
  137. *
  138. * Initialize and register the node device.
  139. */
  140. int register_node(struct node *node, int num, struct node *parent)
  141. {
  142. int error;
  143. node->sysdev.id = num;
  144. node->sysdev.cls = &node_class;
  145. error = sysdev_register(&node->sysdev);
  146. if (!error){
  147. sysdev_create_file(&node->sysdev, &attr_cpumap);
  148. sysdev_create_file(&node->sysdev, &attr_meminfo);
  149. sysdev_create_file(&node->sysdev, &attr_numastat);
  150. sysdev_create_file(&node->sysdev, &attr_distance);
  151. }
  152. return error;
  153. }
  154. /**
  155. * unregister_node - unregister a node device
  156. * @node: node going away
  157. *
  158. * Unregisters a node device @node. All the devices on the node must be
  159. * unregistered before calling this function.
  160. */
  161. void unregister_node(struct node *node)
  162. {
  163. sysdev_remove_file(&node->sysdev, &attr_cpumap);
  164. sysdev_remove_file(&node->sysdev, &attr_meminfo);
  165. sysdev_remove_file(&node->sysdev, &attr_numastat);
  166. sysdev_remove_file(&node->sysdev, &attr_distance);
  167. sysdev_unregister(&node->sysdev);
  168. }
  169. static int __init register_node_type(void)
  170. {
  171. return sysdev_class_register(&node_class);
  172. }
  173. postcore_initcall(register_node_type);