diff -upN reference/fs/proc/base.c current/fs/proc/base.c --- reference/fs/proc/base.c 2004-03-11 14:35:11.000000000 -0800 +++ current/fs/proc/base.c 2004-04-29 10:39:26.000000000 -0700 @@ -58,6 +58,7 @@ enum pid_directory_inos { PROC_TGID_STAT, PROC_TGID_STATM, PROC_TGID_MAPS, + PROC_TGID_MAPS_STATS, PROC_TGID_MOUNTS, PROC_TGID_WCHAN, #ifdef CONFIG_SECURITY @@ -81,6 +82,7 @@ enum pid_directory_inos { PROC_TID_STAT, PROC_TID_STATM, PROC_TID_MAPS, + PROC_TID_MAPS_STATS, PROC_TID_MOUNTS, PROC_TID_WCHAN, #ifdef CONFIG_SECURITY @@ -112,6 +114,7 @@ static struct pid_entry tgid_base_stuff[ E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO), E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO), E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO), + E(PROC_TGID_MAPS_STATS,"maps_stats", S_IFREG|S_IRUGO), E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), E(PROC_TGID_CWD, "cwd", S_IFLNK|S_IRWXUGO), E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), @@ -134,6 +137,7 @@ static struct pid_entry tid_base_stuff[] E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO), E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO), E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO), + E(PROC_TID_MAPS_STATS, "maps_stats", S_IFREG|S_IRUGO), E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), E(PROC_TID_CWD, "cwd", S_IFLNK|S_IRWXUGO), E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), @@ -473,6 +477,25 @@ static struct file_operations proc_maps_ .release = seq_release, }; +extern struct seq_operations proc_pid_maps_stats_op; +static int maps_stats_open(struct inode *inode, struct file *file) +{ + struct task_struct *task = proc_task(inode); + int ret = seq_open(file, &proc_pid_maps_stats_op); + if (!ret) { + struct seq_file *m = file->private_data; + m->private = task; + } + return ret; +} + +static struct file_operations proc_maps_stats_operations = { + .open = maps_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + extern struct seq_operations mounts_op; static int mounts_open(struct inode *inode, struct file *file) { @@ -1353,6 +1376,10 @@ static struct dentry *proc_pident_lookup case PROC_TGID_MAPS: inode->i_fop = &proc_maps_operations; break; + case PROC_TID_MAPS_STATS: + case PROC_TGID_MAPS_STATS: + inode->i_fop = &proc_maps_stats_operations; + break; case PROC_TID_MEM: case PROC_TGID_MEM: inode->i_op = &proc_mem_inode_operations; diff -upN reference/fs/proc/task_mmu.c current/fs/proc/task_mmu.c --- reference/fs/proc/task_mmu.c 2004-02-04 16:24:24.000000000 -0800 +++ current/fs/proc/task_mmu.c 2004-04-29 10:39:26.000000000 -0700 @@ -112,6 +112,115 @@ static int show_map(struct seq_file *m, return 0; } +static int show_map_stats(struct seq_file *m, void *v) +{ + unsigned long pfn, vaddr, vma_end, end, pgds = 0, pmds = 0, ptes = 0; + unsigned long total_pages = 0, zero_pages = 0, not_present = 0; + unsigned long mapping = 0, multi_count = 0, single_count = 0, none = 0; + unsigned long node_pages[MAX_NUMNODES]; + struct vm_area_struct *vma = v; + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgd_p, *pgd_start, *pgd_end; + pmd_t *pmd_p, *pmd_start, *pmd_end; + pte_t *pte_p, *pte_start, *pte_end; + pte_t pte; + struct page *page; + int node; + + show_map(m, v); + + for (node = 0; node < numnodes; ++node) + node_pages[node] = 0; + + if (!mm) { + seq_printf(m, "mm is NULL!\n"); + return 0; + } + if (is_vm_hugetlb_page(vma)) + return 0; + + spin_lock(&mm->page_table_lock); + + vaddr = vma->vm_start & PAGE_MASK; + /* "vma->vm_end - 1" is the last valid address. */ + vma_end = (vma->vm_end - 1) & PAGE_MASK; + + /* Loop over the pgd entries */ + pgd_start = pgd_offset(mm, vaddr); + pgd_end = pgd_offset(mm, vma_end); + for (pgd_p = pgd_start; pgd_p <= pgd_end; pgd_p++, + vaddr = (vaddr+PGDIR_SIZE) & PGDIR_MASK) { + ++pgds; + + if (pgd_none(*pgd_p) || pgd_bad(*pgd_p)) + continue; + + /* Loop over the pmd entries */ + pmd_start = pmd_offset(pgd_p, vaddr); + end = min(vma_end, ((vaddr+PGDIR_SIZE) & PGDIR_MASK) - 1); + pmd_end = pmd_offset(pgd_p, end); + for (pmd_p = pmd_start; pmd_p <= pmd_end; pmd_p++, + vaddr = (vaddr+PMD_SIZE) & PMD_MASK) { + ++pmds; + + if (pmd_none(*pmd_p) || pmd_bad (*pmd_p)) + continue; + + /* Loop over the pte entries */ + pte_start = pte_offset_map(pmd_p, vaddr); + end = min(vma_end, ((vaddr+PMD_SIZE) & PMD_MASK) - 1); + pte_end = pte_offset_kernel(pmd_p, end); + for (pte_p = pte_start; pte_p <= pte_end; pte_p++, + vaddr += PAGE_SIZE) { + ++ptes; + + pte = *pte_p; + ++total_pages; + if (pte_none(pte)) { + ++none; + continue; + } + if (pte_present(pte)) { + pfn = pte_pfn(pte); + if (!pfn) { + ++zero_pages; + continue; + } + if (!pfn_valid(pfn)) { + continue; + } + node_pages[pfn_to_nid(pfn)]++; + page = pfn_to_page(pfn); + /* if (PageDirect(page)) + * single_count++; + * else + * multi_count++; + */ + /* all mapping should be the same */ + mapping = (unsigned long) page->mapping; + } else { + ++not_present; + } + } + pte_unmap(pte_start); + } + } + spin_unlock(&mm->page_table_lock); + + seq_printf(m, " mapping: %08lx\n", mapping); + seq_printf(m, "%5lu zero:%lu none:%lu absent:%lu single:%lu multi:%lu\n", + total_pages, none, zero_pages, not_present, + single_count, multi_count); +#ifdef CONFIG_NUMA + seq_printf(m, " NUMA: "); + for (node = 0; node < numnodes; ++node) + seq_printf(m, "%d:%lu ", node, node_pages[node]); + seq_printf(m, "\n"); +#endif + + return 0; +} + static void *m_start(struct seq_file *m, loff_t *pos) { struct task_struct *task = m->private; @@ -165,3 +274,11 @@ struct seq_operations proc_pid_maps_op = .stop = m_stop, .show = show_map }; + +struct seq_operations proc_pid_maps_stats_op = { + .start = m_start, + .next = m_next, + .stop = m_stop, + .show = show_map_stats +}; + diff -upN reference/include/linux/rmap.h current/include/linux/rmap.h --- reference/include/linux/rmap.h 2004-04-29 10:39:10.000000000 -0700 +++ current/include/linux/rmap.h 2004-04-29 10:39:26.000000000 -0700 @@ -8,8 +8,8 @@ #include #include -#define rmap_lock(page) bit_spin_lock(PG_rmaplock, &(page)->flags) -#define rmap_unlock(page) bit_spin_unlock(PG_rmaplock, &(page)->flags) +#define rmap_lock(page) bit_spin_lock(PG_rmaplock, (unsigned long *)&(page)->flags) +#define rmap_unlock(page) bit_spin_unlock(PG_rmaplock, (unsigned long *)&(page)->flags) #ifdef CONFIG_MMU