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