linux/drivers/base/node.c
<<
>>
Prefs
   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#include <linux/cpu.h>
  15#include <linux/device.h>
  16#include <linux/swap.h>
  17
  18static struct sysdev_class node_class = {
  19        .name = "node",
  20};
  21
  22
  23static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
  24{
  25        struct node *node_dev = to_node(dev);
  26        node_to_cpumask_ptr(mask, node_dev->sysdev.id);
  27        int len;
  28
  29        /* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
  30        BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
  31
  32        len = type?
  33                cpulist_scnprintf(buf, PAGE_SIZE-2, *mask):
  34                cpumask_scnprintf(buf, PAGE_SIZE-2, *mask);
  35        buf[len++] = '\n';
  36        buf[len] = '\0';
  37        return len;
  38}
  39
  40static inline ssize_t node_read_cpumask(struct sys_device *dev,
  41                                struct sysdev_attribute *attr, char *buf)
  42{
  43        return node_read_cpumap(dev, 0, buf);
  44}
  45static inline ssize_t node_read_cpulist(struct sys_device *dev,
  46                                struct sysdev_attribute *attr, char *buf)
  47{
  48        return node_read_cpumap(dev, 1, buf);
  49}
  50
  51static SYSDEV_ATTR(cpumap,  S_IRUGO, node_read_cpumask, NULL);
  52static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
  53
  54#define K(x) ((x) << (PAGE_SHIFT - 10))
  55static ssize_t node_read_meminfo(struct sys_device * dev,
  56                        struct sysdev_attribute *attr, char * buf)
  57{
  58        int n;
  59        int nid = dev->id;
  60        struct sysinfo i;
  61
  62        si_meminfo_node(&i, nid);
  63
  64        n = sprintf(buf, "\n"
  65                       "Node %d MemTotal:       %8lu kB\n"
  66                       "Node %d MemFree:        %8lu kB\n"
  67                       "Node %d MemUsed:        %8lu kB\n"
  68                       "Node %d Active:         %8lu kB\n"
  69                       "Node %d Inactive:       %8lu kB\n"
  70                       "Node %d Active(anon):   %8lu kB\n"
  71                       "Node %d Inactive(anon): %8lu kB\n"
  72                       "Node %d Active(file):   %8lu kB\n"
  73                       "Node %d Inactive(file): %8lu kB\n"
  74#ifdef CONFIG_UNEVICTABLE_LRU
  75                       "Node %d Unevictable:    %8lu kB\n"
  76                       "Node %d Mlocked:        %8lu kB\n"
  77#endif
  78#ifdef CONFIG_HIGHMEM
  79                       "Node %d HighTotal:      %8lu kB\n"
  80                       "Node %d HighFree:       %8lu kB\n"
  81                       "Node %d LowTotal:       %8lu kB\n"
  82                       "Node %d LowFree:        %8lu kB\n"
  83#endif
  84                       "Node %d Dirty:          %8lu kB\n"
  85                       "Node %d Writeback:      %8lu kB\n"
  86                       "Node %d FilePages:      %8lu kB\n"
  87                       "Node %d Mapped:         %8lu kB\n"
  88                       "Node %d AnonPages:      %8lu kB\n"
  89                       "Node %d PageTables:     %8lu kB\n"
  90                       "Node %d NFS_Unstable:   %8lu kB\n"
  91                       "Node %d Bounce:         %8lu kB\n"
  92                       "Node %d WritebackTmp:   %8lu kB\n"
  93                       "Node %d Slab:           %8lu kB\n"
  94                       "Node %d SReclaimable:   %8lu kB\n"
  95                       "Node %d SUnreclaim:     %8lu kB\n",
  96                       nid, K(i.totalram),
  97                       nid, K(i.freeram),
  98                       nid, K(i.totalram - i.freeram),
  99                       nid, K(node_page_state(nid, NR_ACTIVE_ANON) +
 100                                node_page_state(nid, NR_ACTIVE_FILE)),
 101                       nid, K(node_page_state(nid, NR_INACTIVE_ANON) +
 102                                node_page_state(nid, NR_INACTIVE_FILE)),
 103                       nid, K(node_page_state(nid, NR_ACTIVE_ANON)),
 104                       nid, K(node_page_state(nid, NR_INACTIVE_ANON)),
 105                       nid, K(node_page_state(nid, NR_ACTIVE_FILE)),
 106                       nid, K(node_page_state(nid, NR_INACTIVE_FILE)),
 107#ifdef CONFIG_UNEVICTABLE_LRU
 108                       nid, K(node_page_state(nid, NR_UNEVICTABLE)),
 109                       nid, K(node_page_state(nid, NR_MLOCK)),
 110#endif
 111#ifdef CONFIG_HIGHMEM
 112                       nid, K(i.totalhigh),
 113                       nid, K(i.freehigh),
 114                       nid, K(i.totalram - i.totalhigh),
 115                       nid, K(i.freeram - i.freehigh),
 116#endif
 117                       nid, K(node_page_state(nid, NR_FILE_DIRTY)),
 118                       nid, K(node_page_state(nid, NR_WRITEBACK)),
 119                       nid, K(node_page_state(nid, NR_FILE_PAGES)),
 120                       nid, K(node_page_state(nid, NR_FILE_MAPPED)),
 121                       nid, K(node_page_state(nid, NR_ANON_PAGES)),
 122                       nid, K(node_page_state(nid, NR_PAGETABLE)),
 123                       nid, K(node_page_state(nid, NR_UNSTABLE_NFS)),
 124                       nid, K(node_page_state(nid, NR_BOUNCE)),
 125                       nid, K(node_page_state(nid, NR_WRITEBACK_TEMP)),
 126                       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +
 127                                node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
 128                       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
 129                       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));
 130        n += hugetlb_report_node_meminfo(nid, buf + n);
 131        return n;
 132}
 133
 134#undef K
 135static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
 136
 137static ssize_t node_read_numastat(struct sys_device * dev,
 138                                struct sysdev_attribute *attr, char * buf)
 139{
 140        return sprintf(buf,
 141                       "numa_hit %lu\n"
 142                       "numa_miss %lu\n"
 143                       "numa_foreign %lu\n"
 144                       "interleave_hit %lu\n"
 145                       "local_node %lu\n"
 146                       "other_node %lu\n",
 147                       node_page_state(dev->id, NUMA_HIT),
 148                       node_page_state(dev->id, NUMA_MISS),
 149                       node_page_state(dev->id, NUMA_FOREIGN),
 150                       node_page_state(dev->id, NUMA_INTERLEAVE_HIT),
 151                       node_page_state(dev->id, NUMA_LOCAL),
 152                       node_page_state(dev->id, NUMA_OTHER));
 153}
 154static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
 155
 156static ssize_t node_read_distance(struct sys_device * dev,
 157                        struct sysdev_attribute *attr, char * buf)
 158{
 159        int nid = dev->id;
 160        int len = 0;
 161        int i;
 162
 163        /* buf currently PAGE_SIZE, need ~4 chars per node */
 164        BUILD_BUG_ON(MAX_NUMNODES*4 > PAGE_SIZE/2);
 165
 166        for_each_online_node(i)
 167                len += sprintf(buf + len, "%s%d", i ? " " : "", node_distance(nid, i));
 168
 169        len += sprintf(buf + len, "\n");
 170        return len;
 171}
 172static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL);
 173
 174
 175/*
 176 * register_node - Setup a sysfs device for a node.
 177 * @num - Node number to use when creating the device.
 178 *
 179 * Initialize and register the node device.
 180 */
 181int register_node(struct node *node, int num, struct node *parent)
 182{
 183        int error;
 184
 185        node->sysdev.id = num;
 186        node->sysdev.cls = &node_class;
 187        error = sysdev_register(&node->sysdev);
 188
 189        if (!error){
 190                sysdev_create_file(&node->sysdev, &attr_cpumap);
 191                sysdev_create_file(&node->sysdev, &attr_cpulist);
 192                sysdev_create_file(&node->sysdev, &attr_meminfo);
 193                sysdev_create_file(&node->sysdev, &attr_numastat);
 194                sysdev_create_file(&node->sysdev, &attr_distance);
 195
 196                scan_unevictable_register_node(node);
 197        }
 198        return error;
 199}
 200
 201/**
 202 * unregister_node - unregister a node device
 203 * @node: node going away
 204 *
 205 * Unregisters a node device @node.  All the devices on the node must be
 206 * unregistered before calling this function.
 207 */
 208void unregister_node(struct node *node)
 209{
 210        sysdev_remove_file(&node->sysdev, &attr_cpumap);
 211        sysdev_remove_file(&node->sysdev, &attr_cpulist);
 212        sysdev_remove_file(&node->sysdev, &attr_meminfo);
 213        sysdev_remove_file(&node->sysdev, &attr_numastat);
 214        sysdev_remove_file(&node->sysdev, &attr_distance);
 215
 216        scan_unevictable_unregister_node(node);
 217
 218        sysdev_unregister(&node->sysdev);
 219}
 220
 221struct node node_devices[MAX_NUMNODES];
 222
 223/*
 224 * register cpu under node
 225 */
 226int register_cpu_under_node(unsigned int cpu, unsigned int nid)
 227{
 228        if (node_online(nid)) {
 229                struct sys_device *obj = get_cpu_sysdev(cpu);
 230                if (!obj)
 231                        return 0;
 232                return sysfs_create_link(&node_devices[nid].sysdev.kobj,
 233                                         &obj->kobj,
 234                                         kobject_name(&obj->kobj));
 235         }
 236
 237        return 0;
 238}
 239
 240int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
 241{
 242        if (node_online(nid)) {
 243                struct sys_device *obj = get_cpu_sysdev(cpu);
 244                if (obj)
 245                        sysfs_remove_link(&node_devices[nid].sysdev.kobj,
 246                                         kobject_name(&obj->kobj));
 247        }
 248        return 0;
 249}
 250
 251int register_one_node(int nid)
 252{
 253        int error = 0;
 254        int cpu;
 255
 256        if (node_online(nid)) {
 257                int p_node = parent_node(nid);
 258                struct node *parent = NULL;
 259
 260                if (p_node != nid)
 261                        parent = &node_devices[p_node];
 262
 263                error = register_node(&node_devices[nid], nid, parent);
 264
 265                /* link cpu under this node */
 266                for_each_present_cpu(cpu) {
 267                        if (cpu_to_node(cpu) == nid)
 268                                register_cpu_under_node(cpu, nid);
 269                }
 270        }
 271
 272        return error;
 273
 274}
 275
 276void unregister_one_node(int nid)
 277{
 278        unregister_node(&node_devices[nid]);
 279}
 280
 281/*
 282 * node states attributes
 283 */
 284
 285static ssize_t print_nodes_state(enum node_states state, char *buf)
 286{
 287        int n;
 288
 289        n = nodelist_scnprintf(buf, PAGE_SIZE, node_states[state]);
 290        if (n > 0 && PAGE_SIZE > n + 1) {
 291                *(buf + n++) = '\n';
 292                *(buf + n++) = '\0';
 293        }
 294        return n;
 295}
 296
 297static ssize_t print_nodes_possible(struct sysdev_class *class, char *buf)
 298{
 299        return print_nodes_state(N_POSSIBLE, buf);
 300}
 301
 302static ssize_t print_nodes_online(struct sysdev_class *class, char *buf)
 303{
 304        return print_nodes_state(N_ONLINE, buf);
 305}
 306
 307static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class,
 308                                                char *buf)
 309{
 310        return print_nodes_state(N_NORMAL_MEMORY, buf);
 311}
 312
 313static ssize_t print_nodes_has_cpu(struct sysdev_class *class, char *buf)
 314{
 315        return print_nodes_state(N_CPU, buf);
 316}
 317
 318static SYSDEV_CLASS_ATTR(possible, 0444, print_nodes_possible, NULL);
 319static SYSDEV_CLASS_ATTR(online, 0444, print_nodes_online, NULL);
 320static SYSDEV_CLASS_ATTR(has_normal_memory, 0444, print_nodes_has_normal_memory,
 321                                                                        NULL);
 322static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL);
 323
 324#ifdef CONFIG_HIGHMEM
 325static ssize_t print_nodes_has_high_memory(struct sysdev_class *class,
 326                                                 char *buf)
 327{
 328        return print_nodes_state(N_HIGH_MEMORY, buf);
 329}
 330
 331static SYSDEV_CLASS_ATTR(has_high_memory, 0444, print_nodes_has_high_memory,
 332                                                                         NULL);
 333#endif
 334
 335struct sysdev_class_attribute *node_state_attr[] = {
 336        &attr_possible,
 337        &attr_online,
 338        &attr_has_normal_memory,
 339#ifdef CONFIG_HIGHMEM
 340        &attr_has_high_memory,
 341#endif
 342        &attr_has_cpu,
 343};
 344
 345static int node_states_init(void)
 346{
 347        int i;
 348        int err = 0;
 349
 350        for (i = 0;  i < NR_NODE_STATES; i++) {
 351                int ret;
 352                ret = sysdev_class_create_file(&node_class, node_state_attr[i]);
 353                if (!err)
 354                        err = ret;
 355        }
 356        return err;
 357}
 358
 359static int __init register_node_type(void)
 360{
 361        int ret;
 362
 363        ret = sysdev_class_register(&node_class);
 364        if (!ret)
 365                ret = node_states_init();
 366
 367        /*
 368         * Note:  we're not going to unregister the node class if we fail
 369         * to register the node state class attribute files.
 370         */
 371        return ret;
 372}
 373postcore_initcall(register_node_type);
 374
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.