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.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 19b69f931bef..fd751ea37fce 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -699,7 +699,10 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
699 return -EIO; 699 return -EIO;
700 700
701 while (count > 0) { 701 while (count > 0) {
702 ppage = pfn_to_page(pfn++); 702 ppage = NULL;
703 if (pfn_valid(pfn))
704 ppage = pfn_to_page(pfn);
705 pfn++;
703 if (!ppage) 706 if (!ppage)
704 pcount = 0; 707 pcount = 0;
705 else 708 else
@@ -724,6 +727,84 @@ static struct file_operations proc_kpagecount_operations = {
724 .read = kpagecount_read, 727 .read = kpagecount_read,
725}; 728};
726 729
730/* /proc/kpageflags - an array exposing page flags
731 *
732 * Each entry is a u64 representing the corresponding
733 * physical page flags.
734 */
735
736/* These macros are used to decouple internal flags from exported ones */
737
738#define KPF_LOCKED 0
739#define KPF_ERROR 1
740#define KPF_REFERENCED 2
741#define KPF_UPTODATE 3
742#define KPF_DIRTY 4
743#define KPF_LRU 5
744#define KPF_ACTIVE 6
745#define KPF_SLAB 7
746#define KPF_WRITEBACK 8
747#define KPF_RECLAIM 9
748#define KPF_BUDDY 10
749
750#define kpf_copy_bit(flags, srcpos, dstpos) (((flags >> srcpos) & 1) << dstpos)
751
752static ssize_t kpageflags_read(struct file *file, char __user *buf,
753 size_t count, loff_t *ppos)
754{
755 u64 __user *out = (u64 __user *)buf;
756 struct page *ppage;
757 unsigned long src = *ppos;
758 unsigned long pfn;
759 ssize_t ret = 0;
760 u64 kflags, uflags;
761
762 pfn = src / KPMSIZE;
763 count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
764 if (src & KPMMASK || count & KPMMASK)
765 return -EIO;
766
767 while (count > 0) {
768 ppage = NULL;
769 if (pfn_valid(pfn))
770 ppage = pfn_to_page(pfn);
771 pfn++;
772 if (!ppage)
773 kflags = 0;
774 else
775 kflags = ppage->flags;
776
777 uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) |
778 kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
779 kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
780 kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
781 kpf_copy_bit(kflags, KPF_DIRTY, PG_dirty) |
782 kpf_copy_bit(kflags, KPF_LRU, PG_lru) |
783 kpf_copy_bit(kflags, KPF_ACTIVE, PG_active) |
784 kpf_copy_bit(kflags, KPF_SLAB, PG_slab) |
785 kpf_copy_bit(kflags, KPF_WRITEBACK, PG_writeback) |
786 kpf_copy_bit(kflags, KPF_RECLAIM, PG_reclaim) |
787 kpf_copy_bit(kflags, KPF_BUDDY, PG_buddy);
788
789 if (put_user(uflags, out++)) {
790 ret = -EFAULT;
791 break;
792 }
793
794 count -= KPMSIZE;
795 }
796
797 *ppos += (char __user *)out - buf;
798 if (!ret)
799 ret = (char __user *)out - buf;
800 return ret;
801}
802
803static struct file_operations proc_kpageflags_operations = {
804 .llseek = mem_lseek,
805 .read = kpageflags_read,
806};
807
727struct proc_dir_entry *proc_root_kcore; 808struct proc_dir_entry *proc_root_kcore;
728 809
729void create_seq_entry(char *name, mode_t mode, const struct file_operations *f) 810void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
@@ -805,6 +886,7 @@ void __init proc_misc_init(void)
805 } 886 }
806#endif 887#endif
807 create_seq_entry("kpagecount", S_IRUSR, &proc_kpagecount_operations); 888 create_seq_entry("kpagecount", S_IRUSR, &proc_kpagecount_operations);
889 create_seq_entry("kpageflags", S_IRUSR, &proc_kpageflags_operations);
808#ifdef CONFIG_PROC_VMCORE 890#ifdef CONFIG_PROC_VMCORE
809 proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL); 891 proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
810 if (proc_vmcore) 892 if (proc_vmcore)