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