linux/fs/proc/proc_misc.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/proc/proc_misc.c
   3 *
   4 *  linux/fs/proc/array.c
   5 *  Copyright (C) 1992  by Linus Torvalds
   6 *  based on ideas by Darren Senn
   7 *
   8 *  This used to be the part of array.c. See the rest of history and credits
   9 *  there. I took this into a separate file and switched the thing to generic
  10 *  proc_file_inode_operations, leaving in array.c only per-process stuff.
  11 *  Inumbers allocation made dynamic (via create_proc_entry()).  AV, May 1999.
  12 *
  13 * Changes:
  14 * Fulton Green      :  Encapsulated position metric calculations.
  15 *                      <kernel@FultonGreen.com>
  16 */
  17
  18#include <linux/types.h>
  19#include <linux/errno.h>
  20#include <linux/time.h>
  21#include <linux/kernel.h>
  22#include <linux/kernel_stat.h>
  23#include <linux/fs.h>
  24#include <linux/tty.h>
  25#include <linux/string.h>
  26#include <linux/mman.h>
  27#include <linux/quicklist.h>
  28#include <linux/proc_fs.h>
  29#include <linux/ioport.h>
  30#include <linux/mm.h>
  31#include <linux/mmzone.h>
  32#include <linux/pagemap.h>
  33#include <linux/interrupt.h>
  34#include <linux/swap.h>
  35#include <linux/slab.h>
  36#include <linux/genhd.h>
  37#include <linux/smp.h>
  38#include <linux/signal.h>
  39#include <linux/module.h>
  40#include <linux/init.h>
  41#include <linux/seq_file.h>
  42#include <linux/times.h>
  43#include <linux/profile.h>
  44#include <linux/utsname.h>
  45#include <linux/blkdev.h>
  46#include <linux/hugetlb.h>
  47#include <linux/jiffies.h>
  48#include <linux/sysrq.h>
  49#include <linux/vmalloc.h>
  50#include <linux/crash_dump.h>
  51#include <linux/pid_namespace.h>
  52#include <linux/bootmem.h>
  53#include <asm/uaccess.h>
  54#include <asm/pgtable.h>
  55#include <asm/io.h>
  56#include <asm/tlb.h>
  57#include <asm/div64.h>
  58#include "internal.h"
  59
  60#define LOAD_INT(x) ((x) >> FSHIFT)
  61#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
  62/*
  63 * Warning: stuff below (imported functions) assumes that its output will fit
  64 * into one page. For some of those functions it may be wrong. Moreover, we
  65 * have a way to deal with that gracefully. Right now I used straightforward
  66 * wrappers, but this needs further analysis wrt potential overflows.
  67 */
  68extern int get_hardware_list(char *);
  69extern int get_stram_list(char *);
  70extern int get_exec_domain_list(char *);
  71extern int get_dma_list(char *);
  72
  73static int proc_calc_metrics(char *page, char **start, off_t off,
  74                                 int count, int *eof, int len)
  75{
  76        if (len <= off+count) *eof = 1;
  77        *start = page + off;
  78        len -= off;
  79        if (len>count) len = count;
  80        if (len<0) len = 0;
  81        return len;
  82}
  83
  84static int loadavg_read_proc(char *page, char **start, off_t off,
  85                                 int count, int *eof, void *data)
  86{
  87        int a, b, c;
  88        int len;
  89        unsigned long seq;
  90
  91        do {
  92                seq = read_seqbegin(&xtime_lock);
  93                a = avenrun[0] + (FIXED_1/200);
  94                b = avenrun[1] + (FIXED_1/200);
  95                c = avenrun[2] + (FIXED_1/200);
  96        } while (read_seqretry(&xtime_lock, seq));
  97
  98        len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
  99                LOAD_INT(a), LOAD_FRAC(a),
 100                LOAD_INT(b), LOAD_FRAC(b),
 101                LOAD_INT(c), LOAD_FRAC(c),
 102                nr_running(), nr_threads,
 103                task_active_pid_ns(current)->last_pid);
 104        return proc_calc_metrics(page, start, off, count, eof, len);
 105}
 106
 107static int uptime_read_proc(char *page, char **start, off_t off,
 108                                 int count, int *eof, void *data)
 109{
 110        struct timespec uptime;
 111        struct timespec idle;
 112        int len;
 113        cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
 114
 115        do_posix_clock_monotonic_gettime(&uptime);
 116        monotonic_to_bootbased(&uptime);
 117        cputime_to_timespec(idletime, &idle);
 118        len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
 119                        (unsigned long) uptime.tv_sec,
 120                        (uptime.tv_nsec / (NSEC_PER_SEC / 100)),
 121                        (unsigned long) idle.tv_sec,
 122                        (idle.tv_nsec / (NSEC_PER_SEC / 100)));
 123
 124        return proc_calc_metrics(page, start, off, count, eof, len);
 125}
 126
 127int __attribute__((weak)) arch_report_meminfo(char *page)
 128{
 129        return 0;
 130}
 131
 132static int meminfo_read_proc(char *page, char **start, off_t off,
 133                                 int count, int *eof, void *data)
 134{
 135        struct sysinfo i;
 136        int len;
 137        unsigned long committed;
 138        unsigned long allowed;
 139        struct vmalloc_info vmi;
 140        long cached;
 141
 142/*
 143 * display in kilobytes.
 144 */
 145#define K(x) ((x) << (PAGE_SHIFT - 10))
 146        si_meminfo(&i);
 147        si_swapinfo(&i);
 148        committed = atomic_long_read(&vm_committed_space);
 149        allowed = ((totalram_pages - hugetlb_total_pages())
 150                * sysctl_overcommit_ratio / 100) + total_swap_pages;
 151
 152        cached = global_page_state(NR_FILE_PAGES) -
 153                        total_swapcache_pages - i.bufferram;
 154        if (cached < 0)
 155                cached = 0;
 156
 157        get_vmalloc_info(&vmi);
 158
 159        /*
 160         * Tagged format, for easy grepping and expansion.
 161         */
 162        len = sprintf(page,
 163                "MemTotal:     %8lu kB\n"
 164                "MemFree:      %8lu kB\n"
 165                "Buffers:      %8lu kB\n"
 166                "Cached:       %8lu kB\n"
 167                "SwapCached:   %8lu kB\n"
 168                "Active:       %8lu kB\n"
 169                "Inactive:     %8lu kB\n"
 170#ifdef CONFIG_HIGHMEM
 171                "HighTotal:    %8lu kB\n"
 172                "HighFree:     %8lu kB\n"
 173                "LowTotal:     %8lu kB\n"
 174                "LowFree:      %8lu kB\n"
 175#endif
 176                "SwapTotal:    %8lu kB\n"
 177                "SwapFree:     %8lu kB\n"
 178                "Dirty:        %8lu kB\n"
 179                "Writeback:    %8lu kB\n"
 180                "AnonPages:    %8lu kB\n"
 181                "Mapped:       %8lu kB\n"
 182                "Slab:         %8lu kB\n"
 183                "SReclaimable: %8lu kB\n"
 184                "SUnreclaim:   %8lu kB\n"
 185                "PageTables:   %8lu kB\n"
 186#ifdef CONFIG_QUICKLIST
 187                "Quicklists:   %8lu kB\n"
 188#endif
 189                "NFS_Unstable: %8lu kB\n"
 190                "Bounce:       %8lu kB\n"
 191                "WritebackTmp: %8lu kB\n"
 192                "CommitLimit:  %8lu kB\n"
 193                "Committed_AS: %8lu kB\n"
 194                "VmallocTotal: %8lu kB\n"
 195                "VmallocUsed:  %8lu kB\n"
 196                "VmallocChunk: %8lu kB\n",
 197                K(i.totalram),
 198                K(i.freeram),
 199                K(i.bufferram),
 200                K(cached),
 201                K(total_swapcache_pages),
 202                K(global_page_state(NR_ACTIVE)),
 203                K(global_page_state(NR_INACTIVE)),
 204#ifdef CONFIG_HIGHMEM
 205                K(i.totalhigh),
 206                K(i.freehigh),
 207                K(i.totalram-i.totalhigh),
 208                K(i.freeram-i.freehigh),
 209#endif
 210                K(i.totalswap),
 211                K(i.freeswap),
 212                K(global_page_state(NR_FILE_DIRTY)),
 213                K(global_page_state(NR_WRITEBACK)),
 214                K(global_page_state(NR_ANON_PAGES)),
 215                K(global_page_state(NR_FILE_MAPPED)),
 216                K(global_page_state(NR_SLAB_RECLAIMABLE) +
 217                                global_page_state(NR_SLAB_UNRECLAIMABLE)),
 218                K(global_page_state(NR_SLAB_RECLAIMABLE)),
 219                K(global_page_state(NR_SLAB_UNRECLAIMABLE)),
 220                K(global_page_state(NR_PAGETABLE)),
 221#ifdef CONFIG_QUICKLIST
 222                K(quicklist_total_size()),
 223#endif
 224                K(global_page_state(NR_UNSTABLE_NFS)),
 225                K(global_page_state(NR_BOUNCE)),
 226                K(global_page_state(NR_WRITEBACK_TEMP)),
 227                K(allowed),
 228                K(committed),
 229                (unsigned long)VMALLOC_TOTAL >> 10,
 230                vmi.used >> 10,
 231                vmi.largest_chunk >> 10
 232                );
 233
 234                len += hugetlb_report_meminfo(page + len);
 235
 236        len += arch_report_meminfo(page + len);
 237
 238        return proc_calc_metrics(page, start, off, count, eof, len);
 239#undef K
 240}
 241
 242static int fragmentation_open(struct inode *inode, struct file *file)
 243{
 244        (void)inode;
 245        return seq_open(file, &fragmentation_op);
 246}
 247
 248static const struct file_operations fragmentation_file_operations = {
 249        .open           = fragmentation_open,
 250        .read           = seq_read,
 251        .llseek         = seq_lseek,
 252        .release        = seq_release,
 253};
 254
 255static int pagetypeinfo_open(struct inode *inode, struct file *file)
 256{
 257        return seq_open(file, &pagetypeinfo_op);
 258}
 259
 260static const struct file_operations pagetypeinfo_file_ops = {
 261        .open           = pagetypeinfo_open,
 262        .read           = seq_read,
 263        .llseek         = seq_lseek,
 264        .release        = seq_release,
 265};
 266
 267static int zoneinfo_open(struct inode *inode, struct file *file)
 268{
 269        return seq_open(file, &zoneinfo_op);
 270}
 271
 272static const struct file_operations proc_zoneinfo_file_operations = {
 273        .open           = zoneinfo_open,
 274        .read           = seq_read,
 275        .llseek         = seq_lseek,
 276        .release        = seq_release,
 277};
 278
 279static int version_read_proc(char *page, char **start, off_t off,
 280                                 int count, int *eof, void *data)
 281{
 282        int len;
 283
 284        len = snprintf(page, PAGE_SIZE, linux_proc_banner,
 285                utsname()->sysname,
 286                utsname()->release,
 287                utsname()->version);
 288        return proc_calc_metrics(page, start, off, count, eof, len);
 289}
 290
 291extern const struct seq_operations cpuinfo_op;
 292static int cpuinfo_open(struct inode *inode, struct file *file)
 293{
 294        return seq_open(file, &cpuinfo_op);
 295}
 296
 297static const struct file_operations proc_cpuinfo_operations = {
 298        .open           = cpuinfo_open,
 299        .read           = seq_read,
 300        .llseek         = seq_lseek,
 301        .release        = seq_release,
 302};
 303
 304static int devinfo_show(struct seq_file *f, void *v)
 305{
 306        int i = *(loff_t *) v;
 307
 308        if (i < CHRDEV_MAJOR_HASH_SIZE) {
 309                if (i == 0)
 310                        seq_printf(f, "Character devices:\n");
 311                chrdev_show(f, i);
 312        }
 313#ifdef CONFIG_BLOCK
 314        else {
 315                i -= CHRDEV_MAJOR_HASH_SIZE;
 316                if (i == 0)
 317                        seq_printf(f, "\nBlock devices:\n");
 318                blkdev_show(f, i);
 319        }
 320#endif
 321        return 0;
 322}
 323
 324static void *devinfo_start(struct seq_file *f, loff_t *pos)
 325{
 326        if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
 327                return pos;
 328        return NULL;
 329}
 330
 331static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
 332{
 333        (*pos)++;
 334        if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
 335                return NULL;
 336        return pos;
 337}
 338
 339static void devinfo_stop(struct seq_file *f, void *v)
 340{
 341        /* Nothing to do */
 342}
 343
 344static const struct seq_operations devinfo_ops = {
 345        .start = devinfo_start,
 346        .next  = devinfo_next,
 347        .stop  = devinfo_stop,
 348        .show  = devinfo_show
 349};
 350
 351static int devinfo_open(struct inode *inode, struct file *filp)
 352{
 353        return seq_open(filp, &devinfo_ops);
 354}
 355
 356static const struct file_operations proc_devinfo_operations = {
 357        .open           = devinfo_open,
 358        .read           = seq_read,
 359        .llseek         = seq_lseek,
 360        .release        = seq_release,
 361};
 362
 363static int vmstat_open(struct inode *inode, struct file *file)
 364{
 365        return seq_open(file, &vmstat_op);
 366}
 367static const struct file_operations proc_vmstat_file_operations = {
 368        .open           = vmstat_open,
 369        .read           = seq_read,
 370        .llseek         = seq_lseek,
 371        .release        = seq_release,
 372};
 373
 374#ifdef CONFIG_PROC_HARDWARE
 375static int hardware_read_proc(char *page, char **start, off_t off,
 376                                 int count, int *eof, void *data)
 377{
 378        int len = get_hardware_list(page);
 379        return proc_calc_metrics(page, start, off, count, eof, len);
 380}
 381#endif
 382
 383#ifdef CONFIG_STRAM_PROC
 384static int stram_read_proc(char *page, char **start, off_t off,
 385                                 int count, int *eof, void *data)
 386{
 387        int len = get_stram_list(page);
 388        return proc_calc_metrics(page, start, off, count, eof, len);
 389}
 390#endif
 391
 392#ifdef CONFIG_BLOCK
 393static int partitions_open(struct inode *inode, struct file *file)
 394{
 395        return seq_open(file, &partitions_op);
 396}
 397static const struct file_operations proc_partitions_operations = {
 398        .open           = partitions_open,
 399        .read           = seq_read,
 400        .llseek         = seq_lseek,
 401        .release        = seq_release,
 402};
 403
 404static int diskstats_open(struct inode *inode, struct file *file)
 405{
 406        return seq_open(file, &diskstats_op);
 407}
 408static const struct file_operations proc_diskstats_operations = {
 409        .open           = diskstats_open,
 410        .read           = seq_read,
 411        .llseek         = seq_lseek,
 412        .release        = seq_release,
 413};
 414#endif
 415
 416#ifdef CONFIG_MODULES
 417extern const struct seq_operations modules_op;
 418static int modules_open(struct inode *inode, struct file *file)
 419{
 420        return seq_open(file, &modules_op);
 421}
 422static const struct file_operations proc_modules_operations = {
 423        .open           = modules_open,
 424        .read           = seq_read,
 425        .llseek         = seq_lseek,
 426        .release        = seq_release,
 427};
 428#endif
 429
 430#ifdef CONFIG_SLABINFO
 431static int slabinfo_open(struct inode *inode, struct file *file)
 432{
 433        return seq_open(file, &slabinfo_op);
 434}
 435static const struct file_operations proc_slabinfo_operations = {
 436        .open           = slabinfo_open,
 437        .read           = seq_read,
 438        .write          = slabinfo_write,
 439        .llseek         = seq_lseek,
 440        .release        = seq_release,
 441};
 442
 443#ifdef CONFIG_DEBUG_SLAB_LEAK
 444extern const struct seq_operations slabstats_op;
 445static int slabstats_open(struct inode *inode, struct file *file)
 446{
 447        unsigned long *n = kzalloc(PAGE_SIZE, GFP_KERNEL);
 448        int ret = -ENOMEM;
 449        if (n) {
 450                ret = seq_open(file, &slabstats_op);
 451                if (!ret) {
 452                        struct seq_file *m = file->private_data;
 453                        *n = PAGE_SIZE / (2 * sizeof(unsigned long));
 454                        m->private = n;
 455                        n = NULL;
 456                }
 457                kfree(n);
 458        }
 459        return ret;
 460}
 461
 462static const struct file_operations proc_slabstats_operations = {
 463        .open           = slabstats_open,
 464        .read           = seq_read,
 465        .llseek         = seq_lseek,
 466        .release        = seq_release_private,
 467};
 468#endif
 469#endif
 470
 471#ifdef CONFIG_MMU
 472static int vmalloc_open(struct inode *inode, struct file *file)
 473{
 474        unsigned int *ptr = NULL;
 475        int ret;
 476
 477        if (NUMA_BUILD)
 478                ptr = kmalloc(nr_node_ids * sizeof(unsigned int), GFP_KERNEL);
 479        ret = seq_open(file, &vmalloc_op);
 480        if (!ret) {
 481                struct seq_file *m = file->private_data;
 482                m->private = ptr;
 483        } else
 484                kfree(ptr);
 485        return ret;
 486}
 487
 488static const struct file_operations proc_vmalloc_operations = {
 489        .open           = vmalloc_open,
 490        .read           = seq_read,
 491        .llseek         = seq_lseek,
 492        .release        = seq_release_private,
 493};
 494#endif
 495
 496#ifndef arch_irq_stat_cpu
 497#define arch_irq_stat_cpu(cpu) 0
 498#endif
 499#ifndef arch_irq_stat
 500#define arch_irq_stat() 0
 501#endif
 502
 503static int show_stat(struct seq_file *p, void *v)
 504{
 505        int i;
 506        unsigned long jif;
 507        cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
 508        cputime64_t guest;
 509        u64 sum = 0;
 510        struct timespec boottime;
 511        unsigned int *per_irq_sum;
 512
 513        per_irq_sum = kzalloc(sizeof(unsigned int)*NR_IRQS, GFP_KERNEL);
 514        if (!per_irq_sum)
 515                return -ENOMEM;
 516
 517        user = nice = system = idle = iowait =
 518                irq = softirq = steal = cputime64_zero;
 519        guest = cputime64_zero;
 520        getboottime(&boottime);
 521        jif = boottime.tv_sec;
 522
 523        for_each_possible_cpu(i) {
 524                int j;
 525
 526                user = cputime64_add(user, kstat_cpu(i).cpustat.user);
 527                nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
 528                system = cputime64_add(system, kstat_cpu(i).cpustat.system);
 529                idle = cputime64_add(idle, kstat_cpu(i).cpustat.idle);
 530                iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait);
 531                irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq);
 532                softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
 533                steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
 534                guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
 535                for (j = 0; j < NR_IRQS; j++) {
 536                        unsigned int temp = kstat_cpu(i).irqs[j];
 537                        sum += temp;
 538                        per_irq_sum[j] += temp;
 539                }
 540                sum += arch_irq_stat_cpu(i);
 541        }
 542        sum += arch_irq_stat();
 543
 544        seq_printf(p, "cpu  %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
 545                (unsigned long long)cputime64_to_clock_t(user),
 546                (unsigned long long)cputime64_to_clock_t(nice),
 547                (unsigned long long)cputime64_to_clock_t(system),
 548                (unsigned long long)cputime64_to_clock_t(idle),
 549                (unsigned long long)cputime64_to_clock_t(iowait),
 550                (unsigned long long)cputime64_to_clock_t(irq),
 551                (unsigned long long)cputime64_to_clock_t(softirq),
 552                (unsigned long long)cputime64_to_clock_t(steal),
 553                (unsigned long long)cputime64_to_clock_t(guest));
 554        for_each_online_cpu(i) {
 555
 556                /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
 557                user = kstat_cpu(i).cpustat.user;
 558                nice = kstat_cpu(i).cpustat.nice;
 559                system = kstat_cpu(i).cpustat.system;
 560                idle = kstat_cpu(i).cpustat.idle;
 561                iowait = kstat_cpu(i).cpustat.iowait;
 562                irq = kstat_cpu(i).cpustat.irq;
 563                softirq = kstat_cpu(i).cpustat.softirq;
 564                steal = kstat_cpu(i).cpustat.steal;
 565                guest = kstat_cpu(i).cpustat.guest;
 566                seq_printf(p,
 567                        "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
 568                        i,
 569                        (unsigned long long)cputime64_to_clock_t(user),
 570                        (unsigned long long)cputime64_to_clock_t(nice),
 571                        (unsigned long long)cputime64_to_clock_t(system),
 572                        (unsigned long long)cputime64_to_clock_t(idle),
 573                        (unsigned long long)cputime64_to_clock_t(iowait),
 574                        (unsigned long long)cputime64_to_clock_t(irq),
 575                        (unsigned long long)cputime64_to_clock_t(softirq),
 576                        (unsigned long long)cputime64_to_clock_t(steal),
 577                        (unsigned long long)cputime64_to_clock_t(guest));
 578        }
 579        seq_printf(p, "intr %llu", (unsigned long long)sum);
 580
 581        for (i = 0; i < NR_IRQS; i++)
 582                seq_printf(p, " %u", per_irq_sum[i]);
 583
 584        seq_printf(p,
 585                "\nctxt %llu\n"
 586                "btime %lu\n"
 587                "processes %lu\n"
 588                "procs_running %lu\n"
 589                "procs_blocked %lu\n",
 590                nr_context_switches(),
 591                (unsigned long)jif,
 592                total_forks,
 593                nr_running(),
 594                nr_iowait());
 595
 596        kfree(per_irq_sum);
 597        return 0;
 598}
 599
 600static int stat_open(struct inode *inode, struct file *file)
 601{
 602        unsigned size = 4096 * (1 + num_possible_cpus() / 32);
 603        char *buf;
 604        struct seq_file *m;
 605        int res;
 606
 607        /* don't ask for more than the kmalloc() max size, currently 128 KB */
 608        if (size > 128 * 1024)
 609                size = 128 * 1024;
 610        buf = kmalloc(size, GFP_KERNEL);
 611        if (!buf)
 612                return -ENOMEM;
 613
 614        res = single_open(file, show_stat, NULL);
 615        if (!res) {
 616                m = file->private_data;
 617                m->buf = buf;
 618                m->size = size;
 619        } else
 620                kfree(buf);
 621        return res;
 622}
 623static const struct file_operations proc_stat_operations = {
 624        .open           = stat_open,
 625        .read           = seq_read,
 626        .llseek         = seq_lseek,
 627        .release        = single_release,
 628};
 629
 630/*
 631 * /proc/interrupts
 632 */
 633static void *int_seq_start(struct seq_file *f, loff_t *pos)
 634{
 635        return (*pos <= NR_IRQS) ? pos : NULL;
 636}
 637
 638static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
 639{
 640        (*pos)++;
 641        if (*pos > NR_IRQS)
 642                return NULL;
 643        return pos;
 644}
 645
 646static void int_seq_stop(struct seq_file *f, void *v)
 647{
 648        /* Nothing to do */
 649}
 650
 651
 652static const struct seq_operations int_seq_ops = {
 653        .start = int_seq_start,
 654        .next  = int_seq_next,
 655        .stop  = int_seq_stop,
 656        .show  = show_interrupts
 657};
 658
 659static int interrupts_open(struct inode *inode, struct file *filp)
 660{
 661        return seq_open(filp, &int_seq_ops);
 662}
 663
 664static const struct file_operations proc_interrupts_operations = {
 665        .open           = interrupts_open,
 666        .read           = seq_read,
 667        .llseek         = seq_lseek,
 668        .release        = seq_release,
 669};
 670
 671static int filesystems_read_proc(char *page, char **start, off_t off,
 672                                 int count, int *eof, void *data)
 673{
 674        int len = get_filesystem_list(page);
 675        return proc_calc_metrics(page, start, off, count, eof, len);
 676}
 677
 678static int cmdline_read_proc(char *page, char **start, off_t off,
 679                                 int count, int *eof, void *data)
 680{
 681        int len;
 682
 683        len = sprintf(page, "%s\n", saved_command_line);
 684        return proc_calc_metrics(page, start, off, count, eof, len);
 685}
 686
 687static int locks_open(struct inode *inode, struct file *filp)
 688{
 689        return seq_open(filp, &locks_seq_operations);
 690}
 691
 692static const struct file_operations proc_locks_operations = {
 693        .open           = locks_open,
 694        .read           = seq_read,
 695        .llseek         = seq_lseek,
 696        .release        = seq_release,
 697};
 698
 699static int execdomains_read_proc(char *page, char **start, off_t off,
 700                                 int count, int *eof, void *data)
 701{
 702        int len = get_exec_domain_list(page);
 703        return proc_calc_metrics(page, start, off, count, eof, len);
 704}
 705
 706#ifdef CONFIG_MAGIC_SYSRQ
 707/*
 708 * writing 'C' to /proc/sysrq-trigger is like sysrq-C
 709 */
 710static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
 711                                   size_t count, loff_t *ppos)
 712{
 713        if (count) {
 714                char c;
 715
 716                if (get_user(c, buf))
 717                        return -EFAULT;
 718                __handle_sysrq(c, NULL, 0);
 719        }
 720        return count;
 721}
 722
 723static const struct file_operations proc_sysrq_trigger_operations = {
 724        .write          = write_sysrq_trigger,
 725};
 726#endif
 727
 728#ifdef CONFIG_PROC_PAGE_MONITOR
 729#define KPMSIZE sizeof(u64)
 730#define KPMMASK (KPMSIZE - 1)
 731/* /proc/kpagecount - an array exposing page counts
 732 *
 733 * Each entry is a u64 representing the corresponding
 734 * physical page count.
 735 */
 736static ssize_t kpagecount_read(struct file *file, char __user *buf,
 737                             size_t count, loff_t *ppos)
 738{
 739        u64 __user *out = (u64 __user *)buf;
 740        struct page *ppage;
 741        unsigned long src = *ppos;
 742        unsigned long pfn;
 743        ssize_t ret = 0;
 744        u64 pcount;
 745
 746        pfn = src / KPMSIZE;
 747        count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
 748        if (src & KPMMASK || count & KPMMASK)
 749                return -EINVAL;
 750
 751        while (count > 0) {
 752                ppage = NULL;
 753                if (pfn_valid(pfn))
 754                        ppage = pfn_to_page(pfn);
 755                pfn++;
 756                if (!ppage)
 757                        pcount = 0;
 758                else
 759                        pcount = page_mapcount(ppage);
 760
 761                if (put_user(pcount, out++)) {
 762                        ret = -EFAULT;
 763                        break;
 764                }
 765
 766                count -= KPMSIZE;
 767        }
 768
 769        *ppos += (char __user *)out - buf;
 770        if (!ret)
 771                ret = (char __user *)out - buf;
 772        return ret;
 773}
 774
 775static struct file_operations proc_kpagecount_operations = {
 776        .llseek = mem_lseek,
 777        .read = kpagecount_read,
 778};
 779
 780/* /proc/kpageflags - an array exposing page flags
 781 *
 782 * Each entry is a u64 representing the corresponding
 783 * physical page flags.
 784 */
 785
 786/* These macros are used to decouple internal flags from exported ones */
 787
 788#define KPF_LOCKED     0
 789#define KPF_ERROR      1
 790#define KPF_REFERENCED 2
 791#define KPF_UPTODATE   3
 792#define KPF_DIRTY      4
 793#define KPF_LRU        5
 794#define KPF_ACTIVE     6
 795#define KPF_SLAB       7
 796#define KPF_WRITEBACK  8
 797#define KPF_RECLAIM    9
 798#define KPF_BUDDY     10
 799
 800#define kpf_copy_bit(flags, srcpos, dstpos) (((flags >> srcpos) & 1) << dstpos)
 801
 802static ssize_t kpageflags_read(struct file *file, char __user *buf,
 803                             size_t count, loff_t *ppos)
 804{
 805        u64 __user *out = (u64 __user *)buf;
 806        struct page *ppage;
 807        unsigned long src = *ppos;
 808        unsigned long pfn;
 809        ssize_t ret = 0;
 810        u64 kflags, uflags;
 811
 812        pfn = src / KPMSIZE;
 813        count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
 814        if (src & KPMMASK || count & KPMMASK)
 815                return -EINVAL;
 816
 817        while (count > 0) {
 818                ppage = NULL;
 819                if (pfn_valid(pfn))
 820                        ppage = pfn_to_page(pfn);
 821                pfn++;
 822                if (!ppage)
 823                        kflags = 0;
 824                else
 825                        kflags = ppage->flags;
 826
 827                uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) |
 828                        kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
 829                        kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
 830                        kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
 831                        kpf_copy_bit(kflags, KPF_DIRTY, PG_dirty) |
 832                        kpf_copy_bit(kflags, KPF_LRU, PG_lru) |
 833                        kpf_copy_bit(kflags, KPF_ACTIVE, PG_active) |
 834                        kpf_copy_bit(kflags, KPF_SLAB, PG_slab) |
 835                        kpf_copy_bit(kflags, KPF_WRITEBACK, PG_writeback) |
 836                        kpf_copy_bit(kflags, KPF_RECLAIM, PG_reclaim) |
 837                        kpf_copy_bit(kflags, KPF_BUDDY, PG_buddy);
 838
 839                if (put_user(uflags, out++)) {
 840                        ret = -EFAULT;
 841                        break;
 842                }
 843
 844                count -= KPMSIZE;
 845        }
 846
 847        *ppos += (char __user *)out - buf;
 848        if (!ret)
 849                ret = (char __user *)out - buf;
 850        return ret;
 851}
 852
 853static struct file_operations proc_kpageflags_operations = {
 854        .llseek = mem_lseek,
 855        .read = kpageflags_read,
 856};
 857#endif /* CONFIG_PROC_PAGE_MONITOR */
 858
 859struct proc_dir_entry *proc_root_kcore;
 860
 861void __init proc_misc_init(void)
 862{
 863        static struct {
 864                char *name;
 865                int (*read_proc)(char*,char**,off_t,int,int*,void*);
 866        } *p, simple_ones[] = {
 867                {"loadavg",     loadavg_read_proc},
 868                {"uptime",      uptime_read_proc},
 869                {"meminfo",     meminfo_read_proc},
 870                {"version",     version_read_proc},
 871#ifdef CONFIG_PROC_HARDWARE
 872                {"hardware",    hardware_read_proc},
 873#endif
 874#ifdef CONFIG_STRAM_PROC
 875                {"stram",       stram_read_proc},
 876#endif
 877                {"filesystems", filesystems_read_proc},
 878                {"cmdline",     cmdline_read_proc},
 879                {"execdomains", execdomains_read_proc},
 880                {NULL,}
 881        };
 882        for (p = simple_ones; p->name; p++)
 883                create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
 884
 885        proc_symlink("mounts", NULL, "self/mounts");
 886
 887        /* And now for trickier ones */
 888#ifdef CONFIG_PRINTK
 889        proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations);
 890#endif
 891        proc_create("locks", 0, NULL, &proc_locks_operations);
 892        proc_create("devices", 0, NULL, &proc_devinfo_operations);
 893        proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations);
 894#ifdef CONFIG_BLOCK
 895        proc_create("partitions", 0, NULL, &proc_partitions_operations);
 896#endif
 897        proc_create("stat", 0, NULL, &proc_stat_operations);
 898        proc_create("interrupts", 0, NULL, &proc_interrupts_operations);
 899#ifdef CONFIG_SLABINFO
 900        proc_create("slabinfo",S_IWUSR|S_IRUGO,NULL,&proc_slabinfo_operations);
 901#ifdef CONFIG_DEBUG_SLAB_LEAK
 902        proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
 903#endif
 904#endif
 905#ifdef CONFIG_MMU
 906        proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations);
 907#endif
 908        proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
 909        proc_create("pagetypeinfo", S_IRUGO, NULL, &pagetypeinfo_file_ops);
 910        proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
 911        proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
 912#ifdef CONFIG_BLOCK
 913        proc_create("diskstats", 0, NULL, &proc_diskstats_operations);
 914#endif
 915#ifdef CONFIG_MODULES
 916        proc_create("modules", 0, NULL, &proc_modules_operations);
 917#endif
 918#ifdef CONFIG_SCHEDSTATS
 919        proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
 920#endif
 921#ifdef CONFIG_PROC_KCORE
 922        proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, &proc_kcore_operations);
 923        if (proc_root_kcore)
 924                proc_root_kcore->size =
 925                                (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
 926#endif
 927#ifdef CONFIG_PROC_PAGE_MONITOR
 928        proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
 929        proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
 930#endif
 931#ifdef CONFIG_PROC_VMCORE
 932        proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
 933#endif
 934#ifdef CONFIG_MAGIC_SYSRQ
 935        proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
 936#endif
 937}
 938
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.