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/proc_fs.h>
  28#include <linux/ioport.h>
  29#include <linux/mm.h>
  30#include <linux/mmzone.h>
  31#include <linux/pagemap.h>
  32#include <linux/swap.h>
  33#include <linux/slab.h>
  34#include <linux/smp.h>
  35#include <linux/signal.h>
  36#include <linux/module.h>
  37#include <linux/init.h>
  38#include <linux/seq_file.h>
  39#include <linux/times.h>
  40#include <linux/profile.h>
  41#include <linux/utsname.h>
  42#include <linux/blkdev.h>
  43#include <linux/hugetlb.h>
  44#include <linux/jiffies.h>
  45#include <linux/sysrq.h>
  46#include <linux/vmalloc.h>
  47#include <linux/crash_dump.h>
  48#include <linux/pid_namespace.h>
  49#include <asm/uaccess.h>
  50#include <asm/pgtable.h>
  51#include <asm/io.h>
  52#include <asm/tlb.h>
  53#include <asm/div64.h>
  54#include "internal.h"
  55
  56#define LOAD_INT(x) ((x) >> FSHIFT)
  57#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
  58/*
  59 * Warning: stuff below (imported functions) assumes that its output will fit
  60 * into one page. For some of those functions it may be wrong. Moreover, we
  61 * have a way to deal with that gracefully. Right now I used straightforward
  62 * wrappers, but this needs further analysis wrt potential overflows.
  63 */
  64extern int get_hardware_list(char *);
  65extern int get_stram_list(char *);
  66extern int get_filesystem_list(char *);
  67extern int get_exec_domain_list(char *);
  68extern int get_dma_list(char *);
  69
  70static int proc_calc_metrics(char *page, char **start, off_t off,
  71                                 int count, int *eof, int len)
  72{
  73        if (len <= off+count) *eof = 1;
  74        *start = page + off;
  75        len -= off;
  76        if (len>count) len = count;
  77        if (len<0) len = 0;
  78        return len;
  79}
  80
  81static int loadavg_read_proc(char *page, char **start, off_t off,
  82                                 int count, int *eof, void *data)
  83{
  84        int a, b, c;
  85        int len;
  86
  87        a = avenrun[0] + (FIXED_1/200);
  88        b = avenrun[1] + (FIXED_1/200);
  89        c = avenrun[2] + (FIXED_1/200);
  90        len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
  91                LOAD_INT(a), LOAD_FRAC(a),
  92                LOAD_INT(b), LOAD_FRAC(b),
  93                LOAD_INT(c), LOAD_FRAC(c),
  94                nr_running(), nr_threads,
  95                task_active_pid_ns(current)->last_pid);
  96        return proc_calc_metrics(page, start, off, count, eof, len);
  97}
  98
  99static int uptime_read_proc(char *page, char **start, off_t off,
 100                                 int count, int *eof, void *data)
 101{
 102        struct timespec uptime;
 103        struct timespec idle;
 104        int len;
 105        cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
 106
 107        do_posix_clock_monotonic_gettime(&uptime);
 108        monotonic_to_bootbased(&uptime);
 109        cputime_to_timespec(idletime, &idle);
 110        len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
 111                        (unsigned long) uptime.tv_sec,
 112                        (uptime.tv_nsec / (NSEC_PER_SEC / 100)),
 113                        (unsigned long) idle.tv_sec,
 114                        (idle.tv_nsec / (NSEC_PER_SEC / 100)));
 115
 116        return proc_calc_metrics(page, start, off, count, eof, len);
 117}
 118
 119static int meminfo_read_proc(char *page, char **start, off_t off,
 120                                 int count, int *eof, void *data)
 121{
 122        struct sysinfo i;
 123        int len;
 124        unsigned long committed;
 125        unsigned long allowed;
 126        struct vmalloc_info vmi;
 127        long cached;
 128
 129/*
 130 * display in kilobytes.
 131 */
 132#define K(x) ((x) << (PAGE_SHIFT - 10))
 133        si_meminfo(&i);
 134        si_swapinfo(&i);
 135        committed = atomic_read(&vm_committed_space);
 136        allowed = ((totalram_pages - hugetlb_total_pages())
 137                * sysctl_overcommit_ratio / 100) + total_swap_pages;
 138
 139        cached = global_page_state(NR_FILE_PAGES) -
 140                        total_swapcache_pages - i.bufferram;
 141        if (cached < 0)
 142                cached = 0;
 143
 144        get_vmalloc_info(&vmi);
 145
 146        /*
 147         * Tagged format, for easy grepping and expansion.
 148         */
 149        len = sprintf(page,
 150                "MemTotal:     %8lu kB\n"
 151                "MemFree:      %8lu kB\n"
 152                "Buffers:      %8lu kB\n"
 153                "Cached:       %8lu kB\n"
 154                "SwapCached:   %8lu kB\n"
 155                "Active:       %8lu kB\n"
 156                "Inactive:     %8lu kB\n"
 157#ifdef CONFIG_HIGHMEM
 158                "HighTotal:    %8lu kB\n"
 159                "HighFree:     %8lu kB\n"
 160                "LowTotal:     %8lu kB\n"
 161                "LowFree:      %8lu kB\n"
 162#endif
 163                "SwapTotal:    %8lu kB\n"
 164                "SwapFree:     %8lu kB\n"
 165                "Dirty:        %8lu kB\n"
 166                "Writeback:    %8lu kB\n"
 167                "AnonPages:    %8lu kB\n"
 168                "Mapped:       %8lu kB\n"
 169                "Slab:         %8lu kB\n"
 170                "SReclaimable: %8lu kB\n"
 171                "SUnreclaim:   %8lu kB\n"
 172                "PageTables:   %8lu kB\n"
 173                "NFS_Unstable: %8lu kB\n"
 174                "Bounce:       %8lu kB\n"
 175                "CommitLimit:  %8lu kB\n"
 176                "Committed_AS: %8lu kB\n"
 177                "VmallocTotal: %8lu kB\n"
 178                "VmallocUsed:  %8lu kB\n"
 179                "VmallocChunk: %8lu kB\n",
 180                K(i.totalram),
 181                K(i.freeram),
 182                K(i.bufferram),
 183                K(cached),
 184                K(total_swapcache_pages),
 185                K(global_page_state(NR_ACTIVE)),
 186                K(global_page_state(NR_INACTIVE)),
 187#ifdef CONFIG_HIGHMEM
 188                K(i.totalhigh),
 189                K(i.freehigh),
 190                K(i.totalram-i.totalhigh),
 191                K(i.freeram-i.freehigh),
 192#endif
 193                K(i.totalswap),
 194                K(i.freeswap),
 195                K(global_page_state(NR_FILE_DIRTY)),
 196                K(global_page_state(NR_WRITEBACK)),
 197                K(global_page_state(NR_ANON_PAGES)),
 198                K(global_page_state(NR_FILE_MAPPED)),
 199                K(global_page_state(NR_SLAB_RECLAIMABLE) +
 200                                global_page_state(NR_SLAB_UNRECLAIMABLE)),
 201                K(global_page_state(NR_SLAB_RECLAIMABLE)),
 202                K(global_page_state(NR_SLAB_UNRECLAIMABLE)),
 203                K(global_page_state(NR_PAGETABLE)),
 204                K(global_page_state(NR_UNSTABLE_NFS)),
 205                K(global_page_state(NR_BOUNCE)),
 206                K(allowed),
 207                K(committed),
 208                (unsigned long)VMALLOC_TOTAL >> 10,
 209                vmi.used >> 10,
 210                vmi.largest_chunk >> 10
 211                );
 212
 213                len += hugetlb_report_meminfo(page + len);
 214
 215        return proc_calc_metrics(page, start, off, count, eof, len);
 216#undef K
 217}
 218
 219extern struct seq_operations fragmentation_op;
 220static int fragmentation_open(struct inode *inode, struct file *file)
 221{
 222        (void)inode;
 223        return seq_open(file, &fragmentation_op);
 224}
 225
 226static const struct file_operations fragmentation_file_operations = {
 227        .open           = fragmentation_open,
 228        .read           = seq_read,
 229        .llseek         = seq_lseek,
 230        .release        = seq_release,
 231};
 232
 233extern struct seq_operations pagetypeinfo_op;
 234static int pagetypeinfo_open(struct inode *inode, struct file *file)
 235{
 236        return seq_open(file, &pagetypeinfo_op);
 237}
 238
 239static const struct file_operations pagetypeinfo_file_ops = {
 240        .open           = pagetypeinfo_open,
 241        .read           = seq_read,
 242        .llseek         = seq_lseek,
 243        .release        = seq_release,
 244};
 245
 246extern struct seq_operations zoneinfo_op;
 247static int zoneinfo_open(struct inode *inode, struct file *file)
 248{
 249        return seq_open(file, &zoneinfo_op);
 250}
 251
 252static const struct file_operations proc_zoneinfo_file_operations = {
 253        .open           = zoneinfo_open,
 254        .read           = seq_read,
 255        .llseek         = seq_lseek,
 256        .release        = seq_release,
 257};
 258
 259static int version_read_proc(char *page, char **start, off_t off,
 260                                 int count, int *eof, void *data)
 261{
 262        int len;
 263
 264        len = snprintf(page, PAGE_SIZE, linux_proc_banner,
 265                utsname()->sysname,
 266                utsname()->release,
 267                utsname()->version);
 268        return proc_calc_metrics(page, start, off, count, eof, len);
 269}
 270
 271extern struct seq_operations cpuinfo_op;
 272static int cpuinfo_open(struct inode *inode, struct file *file)
 273{
 274        return seq_open(file, &cpuinfo_op);
 275}
 276
 277static const struct file_operations proc_cpuinfo_operations = {
 278        .open           = cpuinfo_open,
 279        .read           = seq_read,
 280        .llseek         = seq_lseek,
 281        .release        = seq_release,
 282};
 283
 284static int devinfo_show(struct seq_file *f, void *v)
 285{
 286        int i = *(loff_t *) v;
 287
 288        if (i < CHRDEV_MAJOR_HASH_SIZE) {
 289                if (i == 0)
 290                        seq_printf(f, "Character devices:\n");
 291                chrdev_show(f, i);
 292        }
 293#ifdef CONFIG_BLOCK
 294        else {
 295                i -= CHRDEV_MAJOR_HASH_SIZE;
 296                if (i == 0)
 297                        seq_printf(f, "\nBlock devices:\n");
 298                blkdev_show(f, i);
 299        }
 300#endif
 301        return 0;
 302}
 303
 304static void *devinfo_start(struct seq_file *f, loff_t *pos)
 305{
 306        if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
 307                return pos;
 308        return NULL;
 309}
 310
 311static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
 312{
 313        (*pos)++;
 314        if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
 315                return NULL;
 316        return pos;
 317}
 318
 319static void devinfo_stop(struct seq_file *f, void *v)
 320{
 321        /* Nothing to do */
 322}
 323
 324static struct seq_operations devinfo_ops = {
 325        .start = devinfo_start,
 326        .next  = devinfo_next,
 327        .stop  = devinfo_stop,
 328        .show  = devinfo_show
 329};
 330
 331static int devinfo_open(struct inode *inode, struct file *filp)
 332{
 333        return seq_open(filp, &devinfo_ops);
 334}
 335
 336static const struct file_operations proc_devinfo_operations = {
 337        .open           = devinfo_open,
 338        .read           = seq_read,
 339        .llseek         = seq_lseek,
 340        .release        = seq_release,
 341};
 342
 343extern struct seq_operations vmstat_op;
 344static int vmstat_open(struct inode *inode, struct file *file)
 345{
 346        return seq_open(file, &vmstat_op);
 347}
 348static const struct file_operations proc_vmstat_file_operations = {
 349        .open           = vmstat_open,
 350        .read           = seq_read,
 351        .llseek         = seq_lseek,
 352        .release        = seq_release,
 353};
 354
 355#ifdef CONFIG_PROC_HARDWARE
 356static int hardware_read_proc(char *page, char **start, off_t off,
 357                                 int count, int *eof, void *data)
 358{
 359        int len = get_hardware_list(page);
 360        return proc_calc_metrics(page, start, off, count, eof, len);
 361}
 362#endif
 363
 364#ifdef CONFIG_STRAM_PROC
 365static int stram_read_proc(char *page, char **start, off_t off,
 366                                 int count, int *eof, void *data)
 367{
 368        int len = get_stram_list(page);
 369        return proc_calc_metrics(page, start, off, count, eof, len);
 370}
 371#endif
 372
 373#ifdef CONFIG_BLOCK
 374extern struct seq_operations partitions_op;
 375static int partitions_open(struct inode *inode, struct file *file)
 376{
 377        return seq_open(file, &partitions_op);
 378}
 379static const struct file_operations proc_partitions_operations = {
 380        .open           = partitions_open,
 381        .read           = seq_read,
 382        .llseek         = seq_lseek,
 383        .release        = seq_release,
 384};
 385
 386extern struct seq_operations diskstats_op;
 387static int diskstats_open(struct inode *inode, struct file *file)
 388{
 389        return seq_open(file, &diskstats_op);
 390}
 391static const struct file_operations proc_diskstats_operations = {
 392        .open           = diskstats_open,
 393        .read           = seq_read,
 394        .llseek         = seq_lseek,
 395        .release        = seq_release,
 396};
 397#endif
 398
 399#ifdef CONFIG_MODULES
 400extern struct seq_operations modules_op;
 401static int modules_open(struct inode *inode, struct file *file)
 402{
 403        return seq_open(file, &modules_op);
 404}
 405static const struct file_operations proc_modules_operations = {
 406        .open           = modules_open,
 407        .read           = seq_read,
 408        .llseek         = seq_lseek,
 409        .release        = seq_release,
 410};
 411#endif
 412
 413#ifdef CONFIG_SLABINFO
 414static int slabinfo_open(struct inode *inode, struct file *file)
 415{
 416        return seq_open(file, &slabinfo_op);
 417}
 418static const struct file_operations proc_slabinfo_operations = {
 419        .open           = slabinfo_open,
 420        .read           = seq_read,
 421        .write          = slabinfo_write,
 422        .llseek         = seq_lseek,
 423        .release        = seq_release,
 424};
 425
 426#ifdef CONFIG_DEBUG_SLAB_LEAK
 427extern struct seq_operations slabstats_op;
 428static int slabstats_open(struct inode *inode, struct file *file)
 429{
 430        unsigned long *n = kzalloc(PAGE_SIZE, GFP_KERNEL);
 431        int ret = -ENOMEM;
 432        if (n) {
 433                ret = seq_open(file, &slabstats_op);
 434                if (!ret) {
 435                        struct seq_file *m = file->private_data;
 436                        *n = PAGE_SIZE / (2 * sizeof(unsigned long));
 437                        m->private = n;
 438                        n = NULL;
 439                }
 440                kfree(n);
 441        }
 442        return ret;
 443}
 444
 445static const struct file_operations proc_slabstats_operations = {
 446        .open           = slabstats_open,
 447        .read           = seq_read,
 448        .llseek         = seq_lseek,
 449        .release        = seq_release_private,
 450};
 451#endif
 452#endif
 453
 454static int show_stat(struct seq_file *p, void *v)
 455{
 456        int i;
 457        unsigned long jif;
 458        cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
 459        cputime64_t guest;
 460        u64 sum = 0;
 461        struct timespec boottime;
 462        unsigned int *per_irq_sum;
 463
 464        per_irq_sum = kzalloc(sizeof(unsigned int)*NR_IRQS, GFP_KERNEL);
 465        if (!per_irq_sum)
 466                return -ENOMEM;
 467
 468        user = nice = system = idle = iowait =
 469                irq = softirq = steal = cputime64_zero;
 470        guest = cputime64_zero;
 471        getboottime(&boottime);
 472        jif = boottime.tv_sec;
 473
 474        for_each_possible_cpu(i) {
 475                int j;
 476
 477                user = cputime64_add(user, kstat_cpu(i).cpustat.user);
 478                nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
 479                system = cputime64_add(system, kstat_cpu(i).cpustat.system);
 480                idle = cputime64_add(idle, kstat_cpu(i).cpustat.idle);
 481                iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait);
 482                irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq);
 483                softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
 484                steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
 485                guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
 486                for (j = 0; j < NR_IRQS; j++) {
 487                        unsigned int temp = kstat_cpu(i).irqs[j];
 488                        sum += temp;
 489                        per_irq_sum[j] += temp;
 490                }
 491        }
 492
 493        seq_printf(p, "cpu  %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
 494                (unsigned long long)cputime64_to_clock_t(user),
 495                (unsigned long long)cputime64_to_clock_t(nice),
 496                (unsigned long long)cputime64_to_clock_t(system),
 497                (unsigned long long)cputime64_to_clock_t(idle),
 498                (unsigned long long)cputime64_to_clock_t(iowait),
 499                (unsigned long long)cputime64_to_clock_t(irq),
 500                (unsigned long long)cputime64_to_clock_t(softirq),
 501                (unsigned long long)cputime64_to_clock_t(steal),
 502                (unsigned long long)cputime64_to_clock_t(guest));
 503        for_each_online_cpu(i) {
 504
 505                /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
 506                user = kstat_cpu(i).cpustat.user;
 507                nice = kstat_cpu(i).cpustat.nice;
 508                system = kstat_cpu(i).cpustat.system;
 509                idle = kstat_cpu(i).cpustat.idle;
 510                iowait = kstat_cpu(i).cpustat.iowait;
 511                irq = kstat_cpu(i).cpustat.irq;
 512                softirq = kstat_cpu(i).cpustat.softirq;
 513                steal = kstat_cpu(i).cpustat.steal;
 514                guest = kstat_cpu(i).cpustat.guest;
 515                seq_printf(p,
 516                        "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
 517                        i,
 518                        (unsigned long long)cputime64_to_clock_t(user),
 519                        (unsigned long long)cputime64_to_clock_t(nice),
 520                        (unsigned long long)cputime64_to_clock_t(system),
 521                        (unsigned long long)cputime64_to_clock_t(idle),
 522                        (unsigned long long)cputime64_to_clock_t(iowait),
 523                        (unsigned long long)cputime64_to_clock_t(irq),
 524                        (unsigned long long)cputime64_to_clock_t(softirq),
 525                        (unsigned long long)cputime64_to_clock_t(steal),
 526                        (unsigned long long)cputime64_to_clock_t(guest));
 527        }
 528        seq_printf(p, "intr %llu", (unsigned long long)sum);
 529
 530        for (i = 0; i < NR_IRQS; i++)
 531                seq_printf(p, " %u", per_irq_sum[i]);
 532
 533        seq_printf(p,
 534                "\nctxt %llu\n"
 535                "btime %lu\n"
 536                "processes %lu\n"
 537                "procs_running %lu\n"
 538                "procs_blocked %lu\n",
 539                nr_context_switches(),
 540                (unsigned long)jif,
 541                total_forks,
 542                nr_running(),
 543                nr_iowait());
 544
 545        kfree(per_irq_sum);
 546        return 0;
 547}
 548
 549static int stat_open(struct inode *inode, struct file *file)
 550{
 551        unsigned size = 4096 * (1 + num_possible_cpus() / 32);
 552        char *buf;
 553        struct seq_file *m;
 554        int res;
 555
 556        /* don't ask for more than the kmalloc() max size, currently 128 KB */
 557        if (size > 128 * 1024)
 558                size = 128 * 1024;
 559        buf = kmalloc(size, GFP_KERNEL);
 560        if (!buf)
 561                return -ENOMEM;
 562
 563        res = single_open(file, show_stat, NULL);
 564        if (!res) {
 565                m = file->private_data;
 566                m->buf = buf;
 567                m->size = size;
 568        } else
 569                kfree(buf);
 570        return res;
 571}
 572static const struct file_operations proc_stat_operations = {
 573        .open           = stat_open,
 574        .read           = seq_read,
 575        .llseek         = seq_lseek,
 576        .release        = single_release,
 577};
 578
 579/*
 580 * /proc/interrupts
 581 */
 582static void *int_seq_start(struct seq_file *f, loff_t *pos)
 583{
 584        return (*pos <= NR_IRQS) ? pos : NULL;
 585}
 586
 587static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
 588{
 589        (*pos)++;
 590        if (*pos > NR_IRQS)
 591                return NULL;
 592        return pos;
 593}
 594
 595static void int_seq_stop(struct seq_file *f, void *v)
 596{
 597        /* Nothing to do */
 598}
 599
 600
 601extern int show_interrupts(struct seq_file *f, void *v); /* In arch code */
 602static struct seq_operations int_seq_ops = {
 603        .start = int_seq_start,
 604        .next  = int_seq_next,
 605        .stop  = int_seq_stop,
 606        .show  = show_interrupts
 607};
 608
 609static int interrupts_open(struct inode *inode, struct file *filp)
 610{
 611        return seq_open(filp, &int_seq_ops);
 612}
 613
 614static const struct file_operations proc_interrupts_operations = {
 615        .open           = interrupts_open,
 616        .read           = seq_read,
 617        .llseek         = seq_lseek,
 618        .release        = seq_release,
 619};
 620
 621static int filesystems_read_proc(char *page, char **start, off_t off,
 622                                 int count, int *eof, void *data)
 623{
 624        int len = get_filesystem_list(page);
 625        return proc_calc_metrics(page, start, off, count, eof, len);
 626}
 627
 628static int cmdline_read_proc(char *page, char **start, off_t off,
 629                                 int count, int *eof, void *data)
 630{
 631        int len;
 632
 633        len = sprintf(page, "%s\n", saved_command_line);
 634        return proc_calc_metrics(page, start, off, count, eof, len);
 635}
 636
 637static int locks_open(struct inode *inode, struct file *filp)
 638{
 639        return seq_open(filp, &locks_seq_operations);
 640}
 641
 642static const struct file_operations proc_locks_operations = {
 643        .open           = locks_open,
 644        .read           = seq_read,
 645        .llseek         = seq_lseek,
 646        .release        = seq_release,
 647};
 648
 649static int execdomains_read_proc(char *page, char **start, off_t off,
 650                                 int count, int *eof, void *data)
 651{
 652        int len = get_exec_domain_list(page);
 653        return proc_calc_metrics(page, start, off, count, eof, len);
 654}
 655
 656#ifdef CONFIG_MAGIC_SYSRQ
 657/*
 658 * writing 'C' to /proc/sysrq-trigger is like sysrq-C
 659 */
 660static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
 661                                   size_t count, loff_t *ppos)
 662{
 663        if (count) {
 664                char c;
 665
 666                if (get_user(c, buf))
 667                        return -EFAULT;
 668                __handle_sysrq(c, NULL, 0);
 669        }
 670        return count;
 671}
 672
 673static const struct file_operations proc_sysrq_trigger_operations = {
 674        .write          = write_sysrq_trigger,
 675};
 676#endif
 677
 678struct proc_dir_entry *proc_root_kcore;
 679
 680void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
 681{
 682        struct proc_dir_entry *entry;
 683        entry = create_proc_entry(name, mode, NULL);
 684        if (entry)
 685                entry->proc_fops = f;
 686}
 687
 688void __init proc_misc_init(void)
 689{
 690        static struct {
 691                char *name;
 692                int (*read_proc)(char*,char**,off_t,int,int*,void*);
 693        } *p, simple_ones[] = {
 694                {"loadavg",     loadavg_read_proc},
 695                {"uptime",      uptime_read_proc},
 696                {"meminfo",     meminfo_read_proc},
 697                {"version",     version_read_proc},
 698#ifdef CONFIG_PROC_HARDWARE
 699                {"hardware",    hardware_read_proc},
 700#endif
 701#ifdef CONFIG_STRAM_PROC
 702                {"stram",       stram_read_proc},
 703#endif
 704                {"filesystems", filesystems_read_proc},
 705                {"cmdline",     cmdline_read_proc},
 706                {"execdomains", execdomains_read_proc},
 707                {NULL,}
 708        };
 709        for (p = simple_ones; p->name; p++)
 710                create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
 711
 712        proc_symlink("mounts", NULL, "self/mounts");
 713
 714        /* And now for trickier ones */
 715#ifdef CONFIG_PRINTK
 716        {
 717                struct proc_dir_entry *entry;
 718                entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
 719                if (entry)
 720                        entry->proc_fops = &proc_kmsg_operations;
 721        }
 722#endif
 723        create_seq_entry("locks", 0, &proc_locks_operations);
 724        create_seq_entry("devices", 0, &proc_devinfo_operations);
 725        create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
 726#ifdef CONFIG_BLOCK
 727        create_seq_entry("partitions", 0, &proc_partitions_operations);
 728#endif
 729        create_seq_entry("stat", 0, &proc_stat_operations);
 730        create_seq_entry("interrupts", 0, &proc_interrupts_operations);
 731#ifdef CONFIG_SLABINFO
 732        create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
 733#ifdef CONFIG_DEBUG_SLAB_LEAK
 734        create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
 735#endif
 736#endif
 737        create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
 738        create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops);
 739        create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
 740        create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
 741#ifdef CONFIG_BLOCK
 742        create_seq_entry("diskstats", 0, &proc_diskstats_operations);
 743#endif
 744#ifdef CONFIG_MODULES
 745        create_seq_entry("modules", 0, &proc_modules_operations);
 746#endif
 747#ifdef CONFIG_SCHEDSTATS
 748        create_seq_entry("schedstat", 0, &proc_schedstat_operations);
 749#endif
 750#ifdef CONFIG_PROC_KCORE
 751        proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
 752        if (proc_root_kcore) {
 753                proc_root_kcore->proc_fops = &proc_kcore_operations;
 754                proc_root_kcore->size =
 755                                (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
 756        }
 757#endif
 758#ifdef CONFIG_PROC_VMCORE
 759        proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
 760        if (proc_vmcore)
 761                proc_vmcore->proc_fops = &proc_vmcore_operations;
 762#endif
 763#ifdef CONFIG_MAGIC_SYSRQ
 764        {
 765                struct proc_dir_entry *entry;
 766                entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
 767                if (entry)
 768                        entry->proc_fops = &proc_sysrq_trigger_operations;
 769        }
 770#endif
 771}
 772