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