Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.25-rc4 910 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_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}