aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/proc_misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/proc_misc.c')
-rw-r--r--fs/proc/proc_misc.c172
1 files changed, 156 insertions, 16 deletions
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 3462bfde89f6..468805d40e2b 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -29,6 +29,7 @@
29#include <linux/mm.h> 29#include <linux/mm.h>
30#include <linux/mmzone.h> 30#include <linux/mmzone.h>
31#include <linux/pagemap.h> 31#include <linux/pagemap.h>
32#include <linux/interrupt.h>
32#include <linux/swap.h> 33#include <linux/swap.h>
33#include <linux/slab.h> 34#include <linux/slab.h>
34#include <linux/smp.h> 35#include <linux/smp.h>
@@ -46,6 +47,7 @@
46#include <linux/vmalloc.h> 47#include <linux/vmalloc.h>
47#include <linux/crash_dump.h> 48#include <linux/crash_dump.h>
48#include <linux/pid_namespace.h> 49#include <linux/pid_namespace.h>
50#include <linux/bootmem.h>
49#include <asm/uaccess.h> 51#include <asm/uaccess.h>
50#include <asm/pgtable.h> 52#include <asm/pgtable.h>
51#include <asm/io.h> 53#include <asm/io.h>
@@ -63,7 +65,6 @@
63 */ 65 */
64extern int get_hardware_list(char *); 66extern int get_hardware_list(char *);
65extern int get_stram_list(char *); 67extern int get_stram_list(char *);
66extern int get_filesystem_list(char *);
67extern int get_exec_domain_list(char *); 68extern int get_exec_domain_list(char *);
68extern int get_dma_list(char *); 69extern int get_dma_list(char *);
69 70
@@ -83,10 +84,15 @@ static int loadavg_read_proc(char *page, char **start, off_t off,
83{ 84{
84 int a, b, c; 85 int a, b, c;
85 int len; 86 int len;
87 unsigned long seq;
88
89 do {
90 seq = read_seqbegin(&xtime_lock);
91 a = avenrun[0] + (FIXED_1/200);
92 b = avenrun[1] + (FIXED_1/200);
93 c = avenrun[2] + (FIXED_1/200);
94 } while (read_seqretry(&xtime_lock, seq));
86 95
87 a = avenrun[0] + (FIXED_1/200);
88 b = avenrun[1] + (FIXED_1/200);
89 c = avenrun[2] + (FIXED_1/200);
90 len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n", 96 len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
91 LOAD_INT(a), LOAD_FRAC(a), 97 LOAD_INT(a), LOAD_FRAC(a),
92 LOAD_INT(b), LOAD_FRAC(b), 98 LOAD_INT(b), LOAD_FRAC(b),
@@ -216,7 +222,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
216#undef K 222#undef K
217} 223}
218 224
219extern struct seq_operations fragmentation_op; 225extern const struct seq_operations fragmentation_op;
220static int fragmentation_open(struct inode *inode, struct file *file) 226static int fragmentation_open(struct inode *inode, struct file *file)
221{ 227{
222 (void)inode; 228 (void)inode;
@@ -230,7 +236,7 @@ static const struct file_operations fragmentation_file_operations = {
230 .release = seq_release, 236 .release = seq_release,
231}; 237};
232 238
233extern struct seq_operations pagetypeinfo_op; 239extern const struct seq_operations pagetypeinfo_op;
234static int pagetypeinfo_open(struct inode *inode, struct file *file) 240static int pagetypeinfo_open(struct inode *inode, struct file *file)
235{ 241{
236 return seq_open(file, &pagetypeinfo_op); 242 return seq_open(file, &pagetypeinfo_op);
@@ -243,7 +249,7 @@ static const struct file_operations pagetypeinfo_file_ops = {
243 .release = seq_release, 249 .release = seq_release,
244}; 250};
245 251
246extern struct seq_operations zoneinfo_op; 252extern const struct seq_operations zoneinfo_op;
247static int zoneinfo_open(struct inode *inode, struct file *file) 253static int zoneinfo_open(struct inode *inode, struct file *file)
248{ 254{
249 return seq_open(file, &zoneinfo_op); 255 return seq_open(file, &zoneinfo_op);
@@ -268,7 +274,7 @@ static int version_read_proc(char *page, char **start, off_t off,
268 return proc_calc_metrics(page, start, off, count, eof, len); 274 return proc_calc_metrics(page, start, off, count, eof, len);
269} 275}
270 276
271extern struct seq_operations cpuinfo_op; 277extern const struct seq_operations cpuinfo_op;
272static int cpuinfo_open(struct inode *inode, struct file *file) 278static int cpuinfo_open(struct inode *inode, struct file *file)
273{ 279{
274 return seq_open(file, &cpuinfo_op); 280 return seq_open(file, &cpuinfo_op);
@@ -321,7 +327,7 @@ static void devinfo_stop(struct seq_file *f, void *v)
321 /* Nothing to do */ 327 /* Nothing to do */
322} 328}
323 329
324static struct seq_operations devinfo_ops = { 330static const struct seq_operations devinfo_ops = {
325 .start = devinfo_start, 331 .start = devinfo_start,
326 .next = devinfo_next, 332 .next = devinfo_next,
327 .stop = devinfo_stop, 333 .stop = devinfo_stop,
@@ -340,7 +346,7 @@ static const struct file_operations proc_devinfo_operations = {
340 .release = seq_release, 346 .release = seq_release,
341}; 347};
342 348
343extern struct seq_operations vmstat_op; 349extern const struct seq_operations vmstat_op;
344static int vmstat_open(struct inode *inode, struct file *file) 350static int vmstat_open(struct inode *inode, struct file *file)
345{ 351{
346 return seq_open(file, &vmstat_op); 352 return seq_open(file, &vmstat_op);
@@ -371,7 +377,7 @@ static int stram_read_proc(char *page, char **start, off_t off,
371#endif 377#endif
372 378
373#ifdef CONFIG_BLOCK 379#ifdef CONFIG_BLOCK
374extern struct seq_operations partitions_op; 380extern const struct seq_operations partitions_op;
375static int partitions_open(struct inode *inode, struct file *file) 381static int partitions_open(struct inode *inode, struct file *file)
376{ 382{
377 return seq_open(file, &partitions_op); 383 return seq_open(file, &partitions_op);
@@ -383,7 +389,7 @@ static const struct file_operations proc_partitions_operations = {
383 .release = seq_release, 389 .release = seq_release,
384}; 390};
385 391
386extern struct seq_operations diskstats_op; 392extern const struct seq_operations diskstats_op;
387static int diskstats_open(struct inode *inode, struct file *file) 393static int diskstats_open(struct inode *inode, struct file *file)
388{ 394{
389 return seq_open(file, &diskstats_op); 395 return seq_open(file, &diskstats_op);
@@ -397,7 +403,7 @@ static const struct file_operations proc_diskstats_operations = {
397#endif 403#endif
398 404
399#ifdef CONFIG_MODULES 405#ifdef CONFIG_MODULES
400extern struct seq_operations modules_op; 406extern const struct seq_operations modules_op;
401static int modules_open(struct inode *inode, struct file *file) 407static int modules_open(struct inode *inode, struct file *file)
402{ 408{
403 return seq_open(file, &modules_op); 409 return seq_open(file, &modules_op);
@@ -424,7 +430,7 @@ static const struct file_operations proc_slabinfo_operations = {
424}; 430};
425 431
426#ifdef CONFIG_DEBUG_SLAB_LEAK 432#ifdef CONFIG_DEBUG_SLAB_LEAK
427extern struct seq_operations slabstats_op; 433extern const struct seq_operations slabstats_op;
428static int slabstats_open(struct inode *inode, struct file *file) 434static int slabstats_open(struct inode *inode, struct file *file)
429{ 435{
430 unsigned long *n = kzalloc(PAGE_SIZE, GFP_KERNEL); 436 unsigned long *n = kzalloc(PAGE_SIZE, GFP_KERNEL);
@@ -598,8 +604,7 @@ static void int_seq_stop(struct seq_file *f, void *v)
598} 604}
599 605
600 606
601extern int show_interrupts(struct seq_file *f, void *v); /* In arch code */ 607static const struct seq_operations int_seq_ops = {
602static struct seq_operations int_seq_ops = {
603 .start = int_seq_start, 608 .start = int_seq_start,
604 .next = int_seq_next, 609 .next = int_seq_next,
605 .stop = int_seq_stop, 610 .stop = int_seq_stop,
@@ -675,6 +680,137 @@ static const struct file_operations proc_sysrq_trigger_operations = {
675}; 680};
676#endif 681#endif
677 682
683#ifdef CONFIG_PROC_PAGE_MONITOR
684#define KPMSIZE sizeof(u64)
685#define KPMMASK (KPMSIZE - 1)
686/* /proc/kpagecount - an array exposing page counts
687 *
688 * Each entry is a u64 representing the corresponding
689 * physical page count.
690 */
691static ssize_t kpagecount_read(struct file *file, char __user *buf,
692 size_t count, loff_t *ppos)
693{
694 u64 __user *out = (u64 __user *)buf;
695 struct page *ppage;
696 unsigned long src = *ppos;
697 unsigned long pfn;
698 ssize_t ret = 0;
699 u64 pcount;
700
701 pfn = src / KPMSIZE;
702 count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
703 if (src & KPMMASK || count & KPMMASK)
704 return -EIO;
705
706 while (count > 0) {
707 ppage = NULL;
708 if (pfn_valid(pfn))
709 ppage = pfn_to_page(pfn);
710 pfn++;
711 if (!ppage)
712 pcount = 0;
713 else
714 pcount = atomic_read(&ppage->_count);
715
716 if (put_user(pcount, out++)) {
717 ret = -EFAULT;
718 break;
719 }
720
721 count -= KPMSIZE;
722 }
723
724 *ppos += (char __user *)out - buf;
725 if (!ret)
726 ret = (char __user *)out - buf;
727 return ret;
728}
729
730static struct file_operations proc_kpagecount_operations = {
731 .llseek = mem_lseek,
732 .read = kpagecount_read,
733};
734
735/* /proc/kpageflags - an array exposing page flags
736 *
737 * Each entry is a u64 representing the corresponding
738 * physical page flags.
739 */
740
741/* These macros are used to decouple internal flags from exported ones */
742
743#define KPF_LOCKED 0
744#define KPF_ERROR 1
745#define KPF_REFERENCED 2
746#define KPF_UPTODATE 3
747#define KPF_DIRTY 4
748#define KPF_LRU 5
749#define KPF_ACTIVE 6
750#define KPF_SLAB 7
751#define KPF_WRITEBACK 8
752#define KPF_RECLAIM 9
753#define KPF_BUDDY 10
754
755#define kpf_copy_bit(flags, srcpos, dstpos) (((flags >> srcpos) & 1) << dstpos)
756
757static ssize_t kpageflags_read(struct file *file, char __user *buf,
758 size_t count, loff_t *ppos)
759{
760 u64 __user *out = (u64 __user *)buf;
761 struct page *ppage;
762 unsigned long src = *ppos;
763 unsigned long pfn;
764 ssize_t ret = 0;
765 u64 kflags, uflags;
766
767 pfn = src / KPMSIZE;
768 count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
769 if (src & KPMMASK || count & KPMMASK)
770 return -EIO;
771
772 while (count > 0) {
773 ppage = NULL;
774 if (pfn_valid(pfn))
775 ppage = pfn_to_page(pfn);
776 pfn++;
777 if (!ppage)
778 kflags = 0;
779 else
780 kflags = ppage->flags;
781
782 uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) |
783 kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
784 kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
785 kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
786 kpf_copy_bit(kflags, KPF_DIRTY, PG_dirty) |
787 kpf_copy_bit(kflags, KPF_LRU, PG_lru) |
788 kpf_copy_bit(kflags, KPF_ACTIVE, PG_active) |
789 kpf_copy_bit(kflags, KPF_SLAB, PG_slab) |
790 kpf_copy_bit(kflags, KPF_WRITEBACK, PG_writeback) |
791 kpf_copy_bit(kflags, KPF_RECLAIM, PG_reclaim) |
792 kpf_copy_bit(kflags, KPF_BUDDY, PG_buddy);
793
794 if (put_user(uflags, out++)) {
795 ret = -EFAULT;
796 break;
797 }
798
799 count -= KPMSIZE;
800 }
801
802 *ppos += (char __user *)out - buf;
803 if (!ret)
804 ret = (char __user *)out - buf;
805 return ret;
806}
807
808static struct file_operations proc_kpageflags_operations = {
809 .llseek = mem_lseek,
810 .read = kpageflags_read,
811};
812#endif /* CONFIG_PROC_PAGE_MONITOR */
813
678struct proc_dir_entry *proc_root_kcore; 814struct proc_dir_entry *proc_root_kcore;
679 815
680void create_seq_entry(char *name, mode_t mode, const struct file_operations *f) 816void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
@@ -755,6 +891,10 @@ void __init proc_misc_init(void)
755 (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE; 891 (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
756 } 892 }
757#endif 893#endif
894#ifdef CONFIG_PROC_PAGE_MONITOR
895 create_seq_entry("kpagecount", S_IRUSR, &proc_kpagecount_operations);
896 create_seq_entry("kpageflags", S_IRUSR, &proc_kpageflags_operations);
897#endif
758#ifdef CONFIG_PROC_VMCORE 898#ifdef CONFIG_PROC_VMCORE
759 proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL); 899 proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
760 if (proc_vmcore) 900 if (proc_vmcore)