page.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include <linux/bootmem.h>
  2. #include <linux/compiler.h>
  3. #include <linux/fs.h>
  4. #include <linux/init.h>
  5. #include <linux/mm.h>
  6. #include <linux/mmzone.h>
  7. #include <linux/proc_fs.h>
  8. #include <linux/seq_file.h>
  9. #include <asm/uaccess.h>
  10. #include "internal.h"
  11. #define KPMSIZE sizeof(u64)
  12. #define KPMMASK (KPMSIZE - 1)
  13. /* /proc/kpagecount - an array exposing page counts
  14. *
  15. * Each entry is a u64 representing the corresponding
  16. * physical page count.
  17. */
  18. static ssize_t kpagecount_read(struct file *file, char __user *buf,
  19. size_t count, loff_t *ppos)
  20. {
  21. u64 __user *out = (u64 __user *)buf;
  22. struct page *ppage;
  23. unsigned long src = *ppos;
  24. unsigned long pfn;
  25. ssize_t ret = 0;
  26. u64 pcount;
  27. pfn = src / KPMSIZE;
  28. count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
  29. if (src & KPMMASK || count & KPMMASK)
  30. return -EINVAL;
  31. while (count > 0) {
  32. ppage = NULL;
  33. if (pfn_valid(pfn))
  34. ppage = pfn_to_page(pfn);
  35. pfn++;
  36. if (!ppage)
  37. pcount = 0;
  38. else
  39. pcount = page_mapcount(ppage);
  40. if (put_user(pcount, out++)) {
  41. ret = -EFAULT;
  42. break;
  43. }
  44. count -= KPMSIZE;
  45. }
  46. *ppos += (char __user *)out - buf;
  47. if (!ret)
  48. ret = (char __user *)out - buf;
  49. return ret;
  50. }
  51. static const struct file_operations proc_kpagecount_operations = {
  52. .llseek = mem_lseek,
  53. .read = kpagecount_read,
  54. };
  55. /* /proc/kpageflags - an array exposing page flags
  56. *
  57. * Each entry is a u64 representing the corresponding
  58. * physical page flags.
  59. */
  60. /* These macros are used to decouple internal flags from exported ones */
  61. #define KPF_LOCKED 0
  62. #define KPF_ERROR 1
  63. #define KPF_REFERENCED 2
  64. #define KPF_UPTODATE 3
  65. #define KPF_DIRTY 4
  66. #define KPF_LRU 5
  67. #define KPF_ACTIVE 6
  68. #define KPF_SLAB 7
  69. #define KPF_WRITEBACK 8
  70. #define KPF_RECLAIM 9
  71. #define KPF_BUDDY 10
  72. #define kpf_copy_bit(flags, dstpos, srcpos) (((flags >> srcpos) & 1) << dstpos)
  73. static ssize_t kpageflags_read(struct file *file, char __user *buf,
  74. size_t count, loff_t *ppos)
  75. {
  76. u64 __user *out = (u64 __user *)buf;
  77. struct page *ppage;
  78. unsigned long src = *ppos;
  79. unsigned long pfn;
  80. ssize_t ret = 0;
  81. u64 kflags, uflags;
  82. pfn = src / KPMSIZE;
  83. count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
  84. if (src & KPMMASK || count & KPMMASK)
  85. return -EINVAL;
  86. while (count > 0) {
  87. ppage = NULL;
  88. if (pfn_valid(pfn))
  89. ppage = pfn_to_page(pfn);
  90. pfn++;
  91. if (!ppage)
  92. kflags = 0;
  93. else
  94. kflags = ppage->flags;
  95. uflags = kpf_copy_bit(kflags, KPF_LOCKED, PG_locked) |
  96. kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
  97. kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
  98. kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
  99. kpf_copy_bit(kflags, KPF_DIRTY, PG_dirty) |
  100. kpf_copy_bit(kflags, KPF_LRU, PG_lru) |
  101. kpf_copy_bit(kflags, KPF_ACTIVE, PG_active) |
  102. kpf_copy_bit(kflags, KPF_SLAB, PG_slab) |
  103. kpf_copy_bit(kflags, KPF_WRITEBACK, PG_writeback) |
  104. kpf_copy_bit(kflags, KPF_RECLAIM, PG_reclaim) |
  105. kpf_copy_bit(kflags, KPF_BUDDY, PG_buddy);
  106. if (put_user(uflags, out++)) {
  107. ret = -EFAULT;
  108. break;
  109. }
  110. count -= KPMSIZE;
  111. }
  112. *ppos += (char __user *)out - buf;
  113. if (!ret)
  114. ret = (char __user *)out - buf;
  115. return ret;
  116. }
  117. static const struct file_operations proc_kpageflags_operations = {
  118. .llseek = mem_lseek,
  119. .read = kpageflags_read,
  120. };
  121. static int __init proc_page_init(void)
  122. {
  123. proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
  124. proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
  125. return 0;
  126. }
  127. module_init(proc_page_init);