lkml.org 
[lkml]   [2006]   [Apr]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    SubjectRe: [patch] do_no_pfn handler
    From
    Date
    Hi,

    Ingo Oeser suggested reorganizing the hangle_pte_fault code in a way
    that simplifies the code deciding which fault handler to call. It
    makes the call to ->nopfn and ->nopage a lot clearer.

    It doesn't address Nick's suggestion as whether to recheck for someone
    else faulting it as I didn't see a consensus on that yet.

    Updated patch attached.

    Cheers,
    Jes

    Implement do_no_pfn() for handling mapping of memory without a struct
    page backing it. This avoids creating fake page table entries for
    regions which are not backed by real memory.

    Signed-off-by: Jes Sorensen <jes@sgi.com>

    ---
    include/linux/mm.h | 1
    mm/memory.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++-----
    2 files changed, 57 insertions(+), 5 deletions(-)

    Index: linux-2.6/include/linux/mm.h
    ===================================================================
    --- linux-2.6.orig/include/linux/mm.h
    +++ linux-2.6/include/linux/mm.h
    @@ -199,6 +199,7 @@
    void (*open)(struct vm_area_struct * area);
    void (*close)(struct vm_area_struct * area);
    struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type);
    + long (*nopfn)(struct vm_area_struct * area, unsigned long address, int *type);
    int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
    #ifdef CONFIG_NUMA
    int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
    Index: linux-2.6/mm/memory.c
    ===================================================================
    --- linux-2.6.orig/mm/memory.c
    +++ linux-2.6/mm/memory.c
    @@ -2146,6 +2146,51 @@
    }

    /*
    + * do_no_pfn() tries to create a new page mapping for a page without
    + * a struct_page backing it
    + *
    + * As this is called only for pages that do not currently exist, we
    + * do not need to flush old virtual caches or the TLB.
    + *
    + * We enter with non-exclusive mmap_sem (to exclude vma changes,
    + * but allow concurrent faults), and pte mapped but not yet locked.
    + * We return with mmap_sem still held, but pte unmapped and unlocked.
    + *
    + * It is expected that the ->nopfn handler always returns the same pfn
    + * for a given virtual mapping.
    + */
    +static int do_no_pfn(struct mm_struct *mm, struct vm_area_struct *vma,
    + unsigned long address, pte_t *page_table, pmd_t *pmd,
    + int write_access)
    +{
    + spinlock_t *ptl;
    + pte_t entry;
    + long pfn;
    + int ret = VM_FAULT_MINOR;
    +
    + pte_unmap(page_table);
    + BUG_ON(!(vma->vm_flags & VM_PFNMAP));
    +
    + pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK, &ret);
    + if (pfn == -ENOMEM)
    + return VM_FAULT_OOM;
    + if (pfn == -EFAULT)
    + return VM_FAULT_SIGBUS;
    + if (pfn < 0)
    + return VM_FAULT_SIGBUS;
    +
    + page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
    +
    + entry = pfn_pte(pfn, vma->vm_page_prot);
    + if (write_access)
    + entry = maybe_mkwrite(pte_mkdirty(entry), vma);
    + set_pte_at(mm, address, page_table, entry);
    +
    + pte_unmap_unlock(page_table, ptl);
    + return ret;
    +}
    +
    +/*
    * Fault of a previously existing named mapping. Repopulate the pte
    * from the encoded file_pte if possible. This enables swappable
    * nonlinear vmas.
    @@ -2207,11 +2252,17 @@
    old_entry = entry = *pte;
    if (!pte_present(entry)) {
    if (pte_none(entry)) {
    - if (!vma->vm_ops || !vma->vm_ops->nopage)
    - return do_anonymous_page(mm, vma, address,
    - pte, pmd, write_access);
    - return do_no_page(mm, vma, address,
    - pte, pmd, write_access);
    + if (vma->vm_ops) {
    + if (vma->vm_ops->nopfn)
    + return do_no_pfn(mm, vma, address, pte,
    + pmd, write_access);
    + if (vma->vm_ops->nopage)
    + return do_no_page(mm, vma, address,
    + pte, pmd,
    + write_access);
    + }
    + return do_anonymous_page(mm, vma, address,
    + pte, pmd, write_access);
    }
    if (pte_file(entry))
    return do_file_page(mm, vma, address,
    -
    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: 2006-04-04 13:00    [W:0.027 / U:60.808 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site