Skip to content

Commit

Permalink
mm: re-architect the VM_UNPAGED logic
Browse files Browse the repository at this point in the history
This replaces the (in my opinion horrible) VM_UNMAPPED logic with very
explicit support for a "remapped page range" aka VM_PFNMAP.  It allows a
VM area to contain an arbitrary range of page table entries that the VM
never touches, and never considers to be normal pages.

Any user of "remap_pfn_range()" automatically gets this new
functionality, and doesn't even have to mark the pages reserved or
indeed mark them any other way.  It just works.  As a side effect, doing
mmap() on /dev/mem works for arbitrary ranges.

Sparc update from David in the next commit.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Linus Torvalds committed Nov 28, 2005
1 parent 458af54 commit 6aab341
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 146 deletions.
6 changes: 2 additions & 4 deletions arch/powerpc/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,7 @@ static void dump_vdso_pages(struct vm_area_struct * vma)
struct page *pg = virt_to_page(vdso32_kbase +
i*PAGE_SIZE);
struct page *upg = (vma && vma->vm_mm) ?
follow_page(vma->vm_mm, vma->vm_start +
i*PAGE_SIZE, 0)
follow_page(vma, vma->vm_start + i*PAGE_SIZE, 0)
: NULL;
dump_one_vdso_page(pg, upg);
}
Expand All @@ -157,8 +156,7 @@ static void dump_vdso_pages(struct vm_area_struct * vma)
struct page *pg = virt_to_page(vdso64_kbase +
i*PAGE_SIZE);
struct page *upg = (vma && vma->vm_mm) ?
follow_page(vma->vm_mm, vma->vm_start +
i*PAGE_SIZE, 0)
follow_page(vma, vma->vm_start + i*PAGE_SIZE, 0)
: NULL;
dump_one_vdso_page(pg, upg);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/char/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size)

if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0)
goto out_up;
if (vma->vm_flags & (VM_SHARED | VM_HUGETLB | VM_UNPAGED))
if (vma->vm_flags & (VM_SHARED | VM_HUGETLB))
break;
count = vma->vm_end - addr;
if (count > size)
Expand Down
7 changes: 3 additions & 4 deletions fs/proc/task_mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,11 @@ struct numa_maps {
/*
* Calculate numa node maps for a vma
*/
static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma)
static struct numa_maps *get_numa_maps(struct vm_area_struct *vma)
{
int i;
struct page *page;
unsigned long vaddr;
struct mm_struct *mm = vma->vm_mm;
int i;
struct numa_maps *md = kmalloc(sizeof(struct numa_maps), GFP_KERNEL);

if (!md)
Expand All @@ -420,7 +419,7 @@ static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma)
md->node[i] =0;

for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) {
page = follow_page(mm, vaddr, 0);
page = follow_page(vma, vaddr, 0);
if (page) {
int count = page_mapcount(page);

Expand Down
5 changes: 3 additions & 2 deletions include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ extern unsigned int kobjsize(const void *objp);
#define VM_GROWSDOWN 0x00000100 /* general info on the segment */
#define VM_GROWSUP 0x00000200
#define VM_SHM 0x00000000 /* Means nothing: delete it later */
#define VM_UNPAGED 0x00000400 /* Pages managed without map count */
#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */
#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */

#define VM_EXECUTABLE 0x00001000
Expand Down Expand Up @@ -664,6 +664,7 @@ struct zap_details {
unsigned long truncate_count; /* Compare vm_truncate_count */
};

struct page *vm_normal_page(struct vm_area_struct *, unsigned long, pte_t);
unsigned long zap_page_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size, struct zap_details *);
unsigned long unmap_vmas(struct mmu_gather **tlb,
Expand Down Expand Up @@ -953,7 +954,7 @@ unsigned long vmalloc_to_pfn(void *addr);
int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
unsigned long pfn, unsigned long size, pgprot_t);

struct page *follow_page(struct mm_struct *, unsigned long address,
struct page *follow_page(struct vm_area_struct *, unsigned long address,
unsigned int foll_flags);
#define FOLL_WRITE 0x01 /* check pte is writable */
#define FOLL_TOUCH 0x02 /* mark page accessed */
Expand Down
22 changes: 7 additions & 15 deletions mm/fremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,20 @@ static int zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
struct page *page = NULL;

if (pte_present(pte)) {
unsigned long pfn = pte_pfn(pte);
flush_cache_page(vma, addr, pfn);
flush_cache_page(vma, addr, pte_pfn(pte));
pte = ptep_clear_flush(vma, addr, ptep);
if (unlikely(!pfn_valid(pfn))) {
print_bad_pte(vma, pte, addr);
goto out;
page = vm_normal_page(vma, addr, pte);
if (page) {
if (pte_dirty(pte))
set_page_dirty(page);
page_remove_rmap(page);
page_cache_release(page);
}
page = pfn_to_page(pfn);
if (pte_dirty(pte))
set_page_dirty(page);
page_remove_rmap(page);
page_cache_release(page);
} else {
if (!pte_file(pte))
free_swap_and_cache(pte_to_swp_entry(pte));
pte_clear(mm, addr, ptep);
}
out:
return !!page;
}

Expand All @@ -65,8 +61,6 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma,
pte_t pte_val;
spinlock_t *ptl;

BUG_ON(vma->vm_flags & VM_UNPAGED);

pgd = pgd_offset(mm, addr);
pud = pud_alloc(mm, pgd, addr);
if (!pud)
Expand Down Expand Up @@ -122,8 +116,6 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma,
pte_t pte_val;
spinlock_t *ptl;

BUG_ON(vma->vm_flags & VM_UNPAGED);

pgd = pgd_offset(mm, addr);
pud = pud_alloc(mm, pgd, addr);
if (!pud)
Expand Down
2 changes: 1 addition & 1 deletion mm/madvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static long madvise_dontneed(struct vm_area_struct * vma,
unsigned long start, unsigned long end)
{
*prev = vma;
if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_UNPAGED))
if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP))
return -EINVAL;

if (unlikely(vma->vm_flags & VM_NONLINEAR)) {
Expand Down
Loading

0 comments on commit 6aab341

Please sign in to comment.