diff options
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 120 |
1 files changed, 95 insertions, 25 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 1a210088ad80..d80fa7d8f720 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -197,7 +197,7 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes) | |||
197 | return policy; | 197 | return policy; |
198 | } | 198 | } |
199 | 199 | ||
200 | static void gather_stats(struct page *, void *); | 200 | static void gather_stats(struct page *, void *, int pte_dirty); |
201 | static void migrate_page_add(struct page *page, struct list_head *pagelist, | 201 | static void migrate_page_add(struct page *page, struct list_head *pagelist, |
202 | unsigned long flags); | 202 | unsigned long flags); |
203 | 203 | ||
@@ -239,7 +239,7 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | |||
239 | continue; | 239 | continue; |
240 | 240 | ||
241 | if (flags & MPOL_MF_STATS) | 241 | if (flags & MPOL_MF_STATS) |
242 | gather_stats(page, private); | 242 | gather_stats(page, private, pte_dirty(*pte)); |
243 | else if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) | 243 | else if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) |
244 | migrate_page_add(page, private, flags); | 244 | migrate_page_add(page, private, flags); |
245 | else | 245 | else |
@@ -1753,67 +1753,137 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) | |||
1753 | struct numa_maps { | 1753 | struct numa_maps { |
1754 | unsigned long pages; | 1754 | unsigned long pages; |
1755 | unsigned long anon; | 1755 | unsigned long anon; |
1756 | unsigned long mapped; | 1756 | unsigned long active; |
1757 | unsigned long writeback; | ||
1757 | unsigned long mapcount_max; | 1758 | unsigned long mapcount_max; |
1759 | unsigned long dirty; | ||
1760 | unsigned long swapcache; | ||
1758 | unsigned long node[MAX_NUMNODES]; | 1761 | unsigned long node[MAX_NUMNODES]; |
1759 | }; | 1762 | }; |
1760 | 1763 | ||
1761 | static void gather_stats(struct page *page, void *private) | 1764 | static void gather_stats(struct page *page, void *private, int pte_dirty) |
1762 | { | 1765 | { |
1763 | struct numa_maps *md = private; | 1766 | struct numa_maps *md = private; |
1764 | int count = page_mapcount(page); | 1767 | int count = page_mapcount(page); |
1765 | 1768 | ||
1766 | if (count) | 1769 | md->pages++; |
1767 | md->mapped++; | 1770 | if (pte_dirty || PageDirty(page)) |
1771 | md->dirty++; | ||
1768 | 1772 | ||
1769 | if (count > md->mapcount_max) | 1773 | if (PageSwapCache(page)) |
1770 | md->mapcount_max = count; | 1774 | md->swapcache++; |
1771 | 1775 | ||
1772 | md->pages++; | 1776 | if (PageActive(page)) |
1777 | md->active++; | ||
1778 | |||
1779 | if (PageWriteback(page)) | ||
1780 | md->writeback++; | ||
1773 | 1781 | ||
1774 | if (PageAnon(page)) | 1782 | if (PageAnon(page)) |
1775 | md->anon++; | 1783 | md->anon++; |
1776 | 1784 | ||
1785 | if (count > md->mapcount_max) | ||
1786 | md->mapcount_max = count; | ||
1787 | |||
1777 | md->node[page_to_nid(page)]++; | 1788 | md->node[page_to_nid(page)]++; |
1778 | cond_resched(); | 1789 | cond_resched(); |
1779 | } | 1790 | } |
1780 | 1791 | ||
1792 | static void check_huge_range(struct vm_area_struct *vma, | ||
1793 | unsigned long start, unsigned long end, | ||
1794 | struct numa_maps *md) | ||
1795 | { | ||
1796 | unsigned long addr; | ||
1797 | struct page *page; | ||
1798 | |||
1799 | for (addr = start; addr < end; addr += HPAGE_SIZE) { | ||
1800 | pte_t *ptep = huge_pte_offset(vma->vm_mm, addr & HPAGE_MASK); | ||
1801 | pte_t pte; | ||
1802 | |||
1803 | if (!ptep) | ||
1804 | continue; | ||
1805 | |||
1806 | pte = *ptep; | ||
1807 | if (pte_none(pte)) | ||
1808 | continue; | ||
1809 | |||
1810 | page = pte_page(pte); | ||
1811 | if (!page) | ||
1812 | continue; | ||
1813 | |||
1814 | gather_stats(page, md, pte_dirty(*ptep)); | ||
1815 | } | ||
1816 | } | ||
1817 | |||
1781 | int show_numa_map(struct seq_file *m, void *v) | 1818 | int show_numa_map(struct seq_file *m, void *v) |
1782 | { | 1819 | { |
1783 | struct task_struct *task = m->private; | 1820 | struct task_struct *task = m->private; |
1784 | struct vm_area_struct *vma = v; | 1821 | struct vm_area_struct *vma = v; |
1785 | struct numa_maps *md; | 1822 | struct numa_maps *md; |
1823 | struct file *file = vma->vm_file; | ||
1824 | struct mm_struct *mm = vma->vm_mm; | ||
1786 | int n; | 1825 | int n; |
1787 | char buffer[50]; | 1826 | char buffer[50]; |
1788 | 1827 | ||
1789 | if (!vma->vm_mm) | 1828 | if (!mm) |
1790 | return 0; | 1829 | return 0; |
1791 | 1830 | ||
1792 | md = kzalloc(sizeof(struct numa_maps), GFP_KERNEL); | 1831 | md = kzalloc(sizeof(struct numa_maps), GFP_KERNEL); |
1793 | if (!md) | 1832 | if (!md) |
1794 | return 0; | 1833 | return 0; |
1795 | 1834 | ||
1796 | if (!is_vm_hugetlb_page(vma)) | 1835 | mpol_to_str(buffer, sizeof(buffer), |
1836 | get_vma_policy(task, vma, vma->vm_start)); | ||
1837 | |||
1838 | seq_printf(m, "%08lx %s", vma->vm_start, buffer); | ||
1839 | |||
1840 | if (file) { | ||
1841 | seq_printf(m, " file="); | ||
1842 | seq_path(m, file->f_vfsmnt, file->f_dentry, "\n\t= "); | ||
1843 | } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { | ||
1844 | seq_printf(m, " heap"); | ||
1845 | } else if (vma->vm_start <= mm->start_stack && | ||
1846 | vma->vm_end >= mm->start_stack) { | ||
1847 | seq_printf(m, " stack"); | ||
1848 | } | ||
1849 | |||
1850 | if (is_vm_hugetlb_page(vma)) { | ||
1851 | check_huge_range(vma, vma->vm_start, vma->vm_end, md); | ||
1852 | seq_printf(m, " huge"); | ||
1853 | } else { | ||
1797 | check_pgd_range(vma, vma->vm_start, vma->vm_end, | 1854 | check_pgd_range(vma, vma->vm_start, vma->vm_end, |
1798 | &node_online_map, MPOL_MF_STATS, md); | 1855 | &node_online_map, MPOL_MF_STATS, md); |
1856 | } | ||
1857 | |||
1858 | if (!md->pages) | ||
1859 | goto out; | ||
1799 | 1860 | ||
1800 | if (md->pages) { | 1861 | if (md->anon) |
1801 | mpol_to_str(buffer, sizeof(buffer), | 1862 | seq_printf(m," anon=%lu",md->anon); |
1802 | get_vma_policy(task, vma, vma->vm_start)); | ||
1803 | 1863 | ||
1804 | seq_printf(m, "%08lx %s pages=%lu mapped=%lu maxref=%lu", | 1864 | if (md->dirty) |
1805 | vma->vm_start, buffer, md->pages, | 1865 | seq_printf(m," dirty=%lu",md->dirty); |
1806 | md->mapped, md->mapcount_max); | ||
1807 | 1866 | ||
1808 | if (md->anon) | 1867 | if (md->pages != md->anon && md->pages != md->dirty) |
1809 | seq_printf(m," anon=%lu",md->anon); | 1868 | seq_printf(m, " mapped=%lu", md->pages); |
1810 | 1869 | ||
1811 | for_each_online_node(n) | 1870 | if (md->mapcount_max > 1) |
1812 | if (md->node[n]) | 1871 | seq_printf(m, " mapmax=%lu", md->mapcount_max); |
1813 | seq_printf(m, " N%d=%lu", n, md->node[n]); | ||
1814 | 1872 | ||
1815 | seq_putc(m, '\n'); | 1873 | if (md->swapcache) |
1816 | } | 1874 | seq_printf(m," swapcache=%lu", md->swapcache); |
1875 | |||
1876 | if (md->active < md->pages && !is_vm_hugetlb_page(vma)) | ||
1877 | seq_printf(m," active=%lu", md->active); | ||
1878 | |||
1879 | if (md->writeback) | ||
1880 | seq_printf(m," writeback=%lu", md->writeback); | ||
1881 | |||
1882 | for_each_online_node(n) | ||
1883 | if (md->node[n]) | ||
1884 | seq_printf(m, " N%d=%lu", n, md->node[n]); | ||
1885 | out: | ||
1886 | seq_putc(m, '\n'); | ||
1817 | kfree(md); | 1887 | kfree(md); |
1818 | 1888 | ||
1819 | if (m->count < m->size) | 1889 | if (m->count < m->size) |