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