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 unsigned long inactive; 43 unsigned long active; 44 unsigned long free; 45 46 si_meminfo_node(&i, nid); 47 __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); 48 49 n = sprintf(buf, "\n" 50 "Node %d MemTotal: %8lu kB\n" 51 "Node %d MemFree: %8lu kB\n" 52 "Node %d MemUsed: %8lu kB\n" 53 "Node %d Active: %8lu kB\n" 54 "Node %d Inactive: %8lu kB\n" 55 "Node %d HighTotal: %8lu kB\n" 56 "Node %d HighFree: %8lu kB\n" 57 "Node %d LowTotal: %8lu kB\n" 58 "Node %d LowFree: %8lu kB\n", 59 nid, K(i.totalram), 60 nid, K(i.freeram), 61 nid, K(i.totalram - i.freeram), 62 nid, K(active), 63 nid, K(inactive), 64 nid, K(i.totalhigh), 65 nid, K(i.freehigh), 66 nid, K(i.totalram - i.totalhigh), 67 nid, K(i.freeram - i.freehigh)); 68 n += hugetlb_report_node_meminfo(nid, buf + n); 69 return n; 70 } 71 72 #undef K 73 static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); 74 75 static ssize_t node_read_numastat(struct sys_device * dev, char * buf) 76 { 77 unsigned long numa_hit, numa_miss, interleave_hit, numa_foreign; 78 unsigned long local_node, other_node; 79 int i, cpu; 80 pg_data_t *pg = NODE_DATA(dev->id); 81 numa_hit = 0; 82 numa_miss = 0; 83 interleave_hit = 0; 84 numa_foreign = 0; 85 local_node = 0; 86 other_node = 0; 87 for (i = 0; i < MAX_NR_ZONES; i++) { 88 struct zone *z = &pg->node_zones[i]; 89 for (cpu = 0; cpu < NR_CPUS; cpu++) { 90 struct per_cpu_pageset *ps = &z->pageset[cpu]; 91 numa_hit += ps->numa_hit; 92 numa_miss += ps->numa_miss; 93 numa_foreign += ps->numa_foreign; 94 interleave_hit += ps->interleave_hit; 95 local_node += ps->local_node; 96 other_node += ps->other_node; 97 } 98 } 99 return sprintf(buf, 100 "numa_hit %lu\n" 101 "numa_miss %lu\n" 102 "numa_foreign %lu\n" 103 "interleave_hit %lu\n" 104 "local_node %lu\n" 105 "other_node %lu\n", 106 numa_hit, 107 numa_miss, 108 numa_foreign, 109 interleave_hit, 110 local_node, 111 other_node); 112 } 113 static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); 114 115 static ssize_t node_read_distance(struct sys_device * dev, char * buf) 116 { 117 int nid = dev->id; 118 int len = 0; 119 int i; 120 121 /* buf currently PAGE_SIZE, need ~4 chars per node */ 122 BUILD_BUG_ON(MAX_NUMNODES*4 > PAGE_SIZE/2); 123 124 for_each_online_node(i) 125 len += sprintf(buf + len, "%s%d", i ? " " : "", node_distance(nid, i)); 126 127 len += sprintf(buf + len, "\n"); 128 return len; 129 } 130 static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL); 131 132 133 /* 134 * register_node - Setup a driverfs device for a node. 135 * @num - Node number to use when creating the device. 136 * 137 * Initialize and register the node device. 138 */ 139 int __init register_node(struct node *node, int num, struct node *parent) 140 { 141 int error; 142 143 node->sysdev.id = num; 144 node->sysdev.cls = &node_class; 145 error = sysdev_register(&node->sysdev); 146 147 if (!error){ 148 sysdev_create_file(&node->sysdev, &attr_cpumap); 149 sysdev_create_file(&node->sysdev, &attr_meminfo); 150 sysdev_create_file(&node->sysdev, &attr_numastat); 151 sysdev_create_file(&node->sysdev, &attr_distance); 152 } 153 return error; 154 } 155 156 157 int __init register_node_type(void) 158 { 159 return sysdev_class_register(&node_class); 160 } 161 postcore_initcall(register_node_type); 162