lkml.org 
[lkml]   [2007]   [Apr]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 13/13] maps: Add /proc/kpagemap interface
    Date
    Add /proc/kpagemap interface

    This makes physical page flags and counts available to userspace.
    Together with /proc/pid/pagemap and /proc/pid/clear_refs, this can be
    used to measure memory usage on a per-page basis.

    Signed-off-by: Matt Mackall <mpm@selenic.com>

    Index: mm/fs/proc/proc_misc.c
    ===================================================================
    --- mm.orig/fs/proc/proc_misc.c 2007-04-03 14:47:45.000000000 -0500
    +++ mm/fs/proc/proc_misc.c 2007-04-03 17:57:14.000000000 -0500
    @@ -46,6 +46,8 @@
    #include <linux/vmalloc.h>
    #include <linux/crash_dump.h>
    #include <linux/pid_namespace.h>
    +#include <linux/ptrace.h>
    +#include <linux/bootmem.h>
    #include <asm/uaccess.h>
    #include <asm/pgtable.h>
    #include <asm/io.h>
    @@ -733,6 +735,72 @@ static struct file_operations proc_page_
    };
    #endif

    +#ifdef CONFIG_PROC_KPAGEMAP
    +#define KPMSIZE (sizeof(unsigned long) * 2)
    +#define KPMMASK (KPMSIZE - 1)
    +/* /proc/kpagemap - an array exposing page flags and counts
    + *
    + * Each entry is a pair of unsigned longs representing the
    + * corresponding physical page, the first containing the page flags
    + * and the second containing the page use count.
    + */
    +static ssize_t kpagemap_read(struct file *file, char __user *buf,
    + size_t count, loff_t *ppos)
    +{
    + unsigned long *page;
    + struct page *ppage;
    + unsigned long src = *ppos;
    + unsigned long pfn;
    + ssize_t ret = 0;
    + int chunk, i;
    +
    + pfn = src / KPMSIZE;
    + count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
    + if (src & KPMMASK || count & KPMMASK)
    + return -EIO;
    +
    + page = (unsigned long *)__get_free_page(GFP_USER);
    + if (!page)
    + return -ENOMEM;
    +
    + while (count > 0) {
    + chunk = min_t(size_t, count, PAGE_SIZE);
    + for (i = 0; i < 2 * chunk / KPMSIZE; i += 2) {
    + ppage = pfn_to_page(pfn);
    + if (!ppage) {
    + page[i] = 0;
    + page[i + 1] = 0;
    + } else {
    + page[i] = ppage->flags;
    + page[i + 1] = atomic_read(&ppage->_count);
    + }
    + pfn++;
    + }
    + chunk = (i / 2) * KPMSIZE;
    +
    + if (copy_to_user(buf, page, chunk)) {
    + ret = -EFAULT;
    + break;
    + }
    + ret += chunk;
    + src += chunk;
    + buf += chunk;
    + count -= chunk;
    + cond_resched();
    + }
    + *ppos = src;
    +
    + free_page((unsigned long)page);
    + return ret;
    +}
    +
    +struct proc_dir_entry *proc_kpagemap;
    +static struct file_operations proc_kpagemap_operations = {
    + .llseek = mem_lseek,
    + .read = kpagemap_read,
    +};
    +#endif
    +
    struct proc_dir_entry *proc_root_kcore;

    void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
    @@ -812,6 +880,11 @@ void __init proc_misc_init(void)
    (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
    }
    #endif
    +#ifdef CONFIG_PROC_KPAGEMAP
    + proc_kpagemap = create_proc_entry("kpagemap", S_IRUSR, NULL);
    + if (proc_kpagemap)
    + proc_kpagemap->proc_fops = &proc_kpagemap_operations;
    +#endif
    #ifdef CONFIG_PROC_VMCORE
    proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
    if (proc_vmcore)
    Index: mm/init/Kconfig
    ===================================================================
    --- mm.orig/init/Kconfig 2007-04-03 14:50:33.000000000 -0500
    +++ mm/init/Kconfig 2007-04-03 14:50:33.000000000 -0500
    @@ -612,6 +612,15 @@ config PROC_PAGEMAP
    with other processes. Disabling this interface will reduce the
    size of the kernel for small machines.

    +config PROC_KPAGEMAP
    + default y
    + bool "Enable /proc/kpagemap support" if EMBEDDED && PROC_FS
    + help
    + The /proc/pid/kpagemap interface allows reading the
    + kernel's per-page flag and usage counts to gather precise
    + information on page-level memory usage. Disabling this interface
    + will reduce the size of the kernel for small machines.
    +
    endmenu # General setup

    config RT_MUTEXES
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2007-04-04 04:47    [W:4.494 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site