aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@engr.sgi.com>2006-03-06 18:42:53 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-06 21:40:45 -0500
commit397874dfe9862b494e1fdcd2baef4ac432d224c8 (patch)
treea6eff78eb0f3ba641e3c57f24fb8071cb295212c /mm
parent2fbf182ed00a71c35e53329c2010df2baf8a89c6 (diff)
[PATCH] numa_maps update
Change the format of numa_maps to be more compact and contain additional information that is useful for managing and troubleshooting memory on a NUMA system. Numa_maps can now also support huge pages. Fixes: 1. More compact format. Only display fields if they contain additional information. 2. Always display information for all vmas. The old numa_maps did not display vma with no mapped entries. This was a bit confusing because page migration removes ptes for file backed vmas. After page migration a part of the vmas vanished. 3. Rename maxref to maxmap. This is the maximum mapcount of all the pages in a vma and may be used as an indicator as to how many processes may be using a certain vma. 4. Include the ability to scan over huge page vmas. New items shown: dirty Number of pages in a vma that have either the dirty bit set in the page_struct or in the pte. file=<filename> The file backing the pages if any stack Stack area heap Heap area huge Huge page area. The number of pages shows is the number of huge pages not the regular sized pages. swapcache Number of pages with swap references. Must be >0 in order to be shown. active Number of active pages. Only displayed if different from the number of pages mapped. writeback Number of pages under writeback. Only displayed if >0. Sample ouput of a process using huge pages: 00000000 default 2000000000000000 default file=/lib/ld-2.3.90.so mapped=13 mapmax=30 N0=13 2000000000044000 default file=/lib/ld-2.3.90.so anon=2 dirty=2 swapcache=2 N2=2 2000000000064000 default file=/lib/librt-2.3.90.so mapped=2 active=1 N1=1 N3=1 2000000000074000 default file=/lib/librt-2.3.90.so 2000000000080000 default file=/lib/librt-2.3.90.so anon=1 swapcache=1 N2=1 2000000000084000 default 2000000000088000 default file=/lib/libc-2.3.90.so mapped=52 mapmax=32 active=48 N0=52 20000000002bc000 default file=/lib/libc-2.3.90.so 20000000002c8000 default file=/lib/libc-2.3.90.so anon=3 dirty=2 swapcache=3 active=2 N1=1 N2=2 20000000002d4000 default anon=1 swapcache=1 N1=1 20000000002d8000 default file=/lib/libpthread-2.3.90.so mapped=8 mapmax=3 active=7 N2=2 N3=6 20000000002fc000 default file=/lib/libpthread-2.3.90.so 2000000000308000 default file=/lib/libpthread-2.3.90.so anon=1 dirty=1 swapcache=1 N1=1 200000000030c000 default anon=1 dirty=1 swapcache=1 N1=1 2000000000320000 default anon=1 dirty=1 N1=1 200000000071c000 default 2000000000720000 default anon=2 dirty=2 swapcache=1 N1=1 N2=1 2000000000f1c000 default 2000000000f20000 default anon=2 dirty=2 swapcache=1 active=1 N2=1 N3=1 200000000171c000 default 2000000001720000 default anon=1 dirty=1 swapcache=1 N1=1 2000000001b20000 default 2000000001b38000 default file=/lib/libgcc_s.so.1 mapped=2 N1=2 2000000001b48000 default file=/lib/libgcc_s.so.1 2000000001b54000 default file=/lib/libgcc_s.so.1 anon=1 dirty=1 active=0 N1=1 2000000001b58000 default file=/lib/libunwind.so.7.0.0 mapped=2 active=1 N1=2 2000000001b74000 default file=/lib/libunwind.so.7.0.0 2000000001b80000 default file=/lib/libunwind.so.7.0.0 2000000001b84000 default 4000000000000000 default file=/media/huge/test9 mapped=1 N1=1 6000000000000000 default file=/media/huge/test9 anon=1 dirty=1 active=0 N1=1 6000000000004000 default heap 607fffff7fffc000 default anon=1 dirty=1 swapcache=1 N2=1 607fffffff06c000 default stack anon=1 dirty=1 active=0 N1=1 8000000060000000 default file=/mnt/huge/test0 huge dirty=3 N1=3 8000000090000000 default file=/mnt/huge/test1 huge dirty=3 N0=1 N2=2 80000000c0000000 default file=/mnt/huge/test2 huge dirty=3 N1=1 N3=2 Signed-off-by: Christoph Lameter <clameter@sgi.com> Cc: Andi Kleen <ak@muc.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/mempolicy.c120
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
200static void gather_stats(struct page *, void *); 200static void gather_stats(struct page *, void *, int pte_dirty);
201static void migrate_page_add(struct page *page, struct list_head *pagelist, 201static 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)
1753struct numa_maps { 1753struct 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
1761static void gather_stats(struct page *page, void *private) 1764static 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
1792static 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
1781int show_numa_map(struct seq_file *m, void *v) 1818int 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]);
1885out:
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)