diff options
| -rw-r--r-- | arch/ppc64/kernel/vdso.c | 12 | ||||
| -rw-r--r-- | arch/sparc/mm/generic.c | 3 | ||||
| -rw-r--r-- | arch/sparc64/mm/generic.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/sg.c | 12 | ||||
| -rw-r--r-- | drivers/scsi/st.c | 10 | ||||
| -rw-r--r-- | fs/direct-io.c | 4 | ||||
| -rw-r--r-- | include/linux/mm.h | 5 | ||||
| -rw-r--r-- | kernel/power/swsusp.c | 25 | ||||
| -rw-r--r-- | mm/bootmem.c | 1 | ||||
| -rw-r--r-- | mm/filemap_xip.c | 11 | ||||
| -rw-r--r-- | mm/fremap.c | 23 | ||||
| -rw-r--r-- | mm/madvise.c | 2 | ||||
| -rw-r--r-- | mm/memory.c | 131 | ||||
| -rw-r--r-- | mm/mempolicy.c | 29 | ||||
| -rw-r--r-- | mm/mmap.c | 11 | ||||
| -rw-r--r-- | mm/mprotect.c | 8 | ||||
| -rw-r--r-- | mm/msync.c | 17 | ||||
| -rw-r--r-- | mm/page_alloc.c | 14 | ||||
| -rw-r--r-- | mm/rmap.c | 14 | ||||
| -rw-r--r-- | mm/shmem.c | 4 | ||||
| -rw-r--r-- | mm/swap.c | 4 | ||||
| -rw-r--r-- | sound/core/pcm_native.c | 9 | 
22 files changed, 218 insertions, 134 deletions
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c index efa985f05aca..4aacf521e3e4 100644 --- a/arch/ppc64/kernel/vdso.c +++ b/arch/ppc64/kernel/vdso.c  | |||
| @@ -176,13 +176,13 @@ static struct page * vdso_vma_nopage(struct vm_area_struct * vma, | |||
| 176 | return NOPAGE_SIGBUS; | 176 | return NOPAGE_SIGBUS; | 
| 177 | 177 | ||
| 178 | /* | 178 | /* | 
| 179 | * Last page is systemcfg, special handling here, no get_page() a | 179 | * Last page is systemcfg. | 
| 180 | * this is a reserved page | ||
| 181 | */ | 180 | */ | 
| 182 | if ((vma->vm_end - address) <= PAGE_SIZE) | 181 | if ((vma->vm_end - address) <= PAGE_SIZE) | 
| 183 | return virt_to_page(systemcfg); | 182 | pg = virt_to_page(systemcfg); | 
| 183 | else | ||
| 184 | pg = virt_to_page(vbase + offset); | ||
| 184 | 185 | ||
| 185 | pg = virt_to_page(vbase + offset); | ||
| 186 | get_page(pg); | 186 | get_page(pg); | 
| 187 | DBG(" ->page count: %d\n", page_count(pg)); | 187 | DBG(" ->page count: %d\n", page_count(pg)); | 
| 188 | 188 | ||
| @@ -259,7 +259,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack) | |||
| 259 | * gettimeofday will be totally dead. It's fine to use that for setting | 259 | * gettimeofday will be totally dead. It's fine to use that for setting | 
| 260 | * breakpoints in the vDSO code pages though | 260 | * breakpoints in the vDSO code pages though | 
| 261 | */ | 261 | */ | 
| 262 | vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; | 262 | vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | VM_RESERVED; | 
| 263 | vma->vm_flags |= mm->def_flags; | 263 | vma->vm_flags |= mm->def_flags; | 
| 264 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | 264 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | 
| 265 | vma->vm_ops = &vdso_vmops; | 265 | vma->vm_ops = &vdso_vmops; | 
| @@ -603,6 +603,8 @@ void __init vdso_init(void) | |||
| 603 | ClearPageReserved(pg); | 603 | ClearPageReserved(pg); | 
| 604 | get_page(pg); | 604 | get_page(pg); | 
| 605 | } | 605 | } | 
| 606 | |||
| 607 | get_page(virt_to_page(systemcfg)); | ||
| 606 | } | 608 | } | 
| 607 | 609 | ||
| 608 | int in_gate_area_no_task(unsigned long addr) | 610 | int in_gate_area_no_task(unsigned long addr) | 
diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c index 20ccb957fb77..659c9a71f867 100644 --- a/arch/sparc/mm/generic.c +++ b/arch/sparc/mm/generic.c  | |||
| @@ -73,6 +73,9 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, | |||
| 73 | int space = GET_IOSPACE(pfn); | 73 | int space = GET_IOSPACE(pfn); | 
| 74 | unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; | 74 | unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; | 
| 75 | 75 | ||
| 76 | /* See comment in mm/memory.c remap_pfn_range */ | ||
| 77 | vma->vm_flags |= VM_IO | VM_RESERVED; | ||
| 78 | |||
| 76 | prot = __pgprot(pg_iobits); | 79 | prot = __pgprot(pg_iobits); | 
| 77 | offset -= from; | 80 | offset -= from; | 
| 78 | dir = pgd_offset(mm, from); | 81 | dir = pgd_offset(mm, from); | 
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c index c954d91f01d0..afc01cec701f 100644 --- a/arch/sparc64/mm/generic.c +++ b/arch/sparc64/mm/generic.c  | |||
| @@ -127,6 +127,9 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, | |||
| 127 | int space = GET_IOSPACE(pfn); | 127 | int space = GET_IOSPACE(pfn); | 
| 128 | unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; | 128 | unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; | 
| 129 | 129 | ||
| 130 | /* See comment in mm/memory.c remap_pfn_range */ | ||
| 131 | vma->vm_flags |= VM_IO | VM_RESERVED; | ||
| 132 | |||
| 130 | prot = __pgprot(pg_iobits); | 133 | prot = __pgprot(pg_iobits); | 
| 131 | offset -= from; | 134 | offset -= from; | 
| 132 | dir = pgd_offset(mm, from); | 135 | dir = pgd_offset(mm, from); | 
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 861e51375d70..2d30b46806bf 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c  | |||
| @@ -1886,13 +1886,17 @@ st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages, | |||
| 1886 | int i; | 1886 | int i; | 
| 1887 | 1887 | ||
| 1888 | for (i=0; i < nr_pages; i++) { | 1888 | for (i=0; i < nr_pages; i++) { | 
| 1889 | if (dirtied && !PageReserved(sgl[i].page)) | 1889 | struct page *page = sgl[i].page; | 
| 1890 | SetPageDirty(sgl[i].page); | 1890 | |
| 1891 | /* unlock_page(sgl[i].page); */ | 1891 | /* XXX: just for debug. Remove when PageReserved is removed */ | 
| 1892 | BUG_ON(PageReserved(page)); | ||
| 1893 | if (dirtied) | ||
| 1894 | SetPageDirty(page); | ||
| 1895 | /* unlock_page(page); */ | ||
| 1892 | /* FIXME: cache flush missing for rw==READ | 1896 | /* FIXME: cache flush missing for rw==READ | 
| 1893 | * FIXME: call the correct reference counting function | 1897 | * FIXME: call the correct reference counting function | 
| 1894 | */ | 1898 | */ | 
| 1895 | page_cache_release(sgl[i].page); | 1899 | page_cache_release(page); | 
| 1896 | } | 1900 | } | 
| 1897 | 1901 | ||
| 1898 | return 0; | 1902 | return 0; | 
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 5eb54d8019b4..da9766283bd7 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c  | |||
| @@ -4526,12 +4526,16 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p | |||
| 4526 | int i; | 4526 | int i; | 
| 4527 | 4527 | ||
| 4528 | for (i=0; i < nr_pages; i++) { | 4528 | for (i=0; i < nr_pages; i++) { | 
| 4529 | if (dirtied && !PageReserved(sgl[i].page)) | 4529 | struct page *page = sgl[i].page; | 
| 4530 | SetPageDirty(sgl[i].page); | 4530 | |
| 4531 | /* XXX: just for debug. Remove when PageReserved is removed */ | ||
| 4532 | BUG_ON(PageReserved(page)); | ||
| 4533 | if (dirtied) | ||
| 4534 | SetPageDirty(page); | ||
| 4531 | /* FIXME: cache flush missing for rw==READ | 4535 | /* FIXME: cache flush missing for rw==READ | 
| 4532 | * FIXME: call the correct reference counting function | 4536 | * FIXME: call the correct reference counting function | 
| 4533 | */ | 4537 | */ | 
| 4534 | page_cache_release(sgl[i].page); | 4538 | page_cache_release(page); | 
| 4535 | } | 4539 | } | 
| 4536 | 4540 | ||
| 4537 | return 0; | 4541 | return 0; | 
diff --git a/fs/direct-io.c b/fs/direct-io.c index 0d06097bc995..3931e7f1e6bf 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c  | |||
| @@ -162,6 +162,7 @@ static int dio_refill_pages(struct dio *dio) | |||
| 162 | up_read(¤t->mm->mmap_sem); | 162 | up_read(¤t->mm->mmap_sem); | 
| 163 | 163 | ||
| 164 | if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) { | 164 | if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) { | 
| 165 | struct page *page = ZERO_PAGE(dio->curr_user_address); | ||
| 165 | /* | 166 | /* | 
| 166 | * A memory fault, but the filesystem has some outstanding | 167 | * A memory fault, but the filesystem has some outstanding | 
| 167 | * mapped blocks. We need to use those blocks up to avoid | 168 | * mapped blocks. We need to use those blocks up to avoid | 
| @@ -169,7 +170,8 @@ static int dio_refill_pages(struct dio *dio) | |||
| 169 | */ | 170 | */ | 
| 170 | if (dio->page_errors == 0) | 171 | if (dio->page_errors == 0) | 
| 171 | dio->page_errors = ret; | 172 | dio->page_errors = ret; | 
| 172 | dio->pages[0] = ZERO_PAGE(dio->curr_user_address); | 173 | page_cache_get(page); | 
| 174 | dio->pages[0] = page; | ||
| 173 | dio->head = 0; | 175 | dio->head = 0; | 
| 174 | dio->tail = 1; | 176 | dio->tail = 1; | 
| 175 | ret = 0; | 177 | ret = 0; | 
diff --git a/include/linux/mm.h b/include/linux/mm.h index 0c64484d8ae0..da42093250c3 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h  | |||
| @@ -157,7 +157,7 @@ extern unsigned int kobjsize(const void *objp); | |||
| 157 | 157 | ||
| 158 | #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */ | 158 | #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */ | 
| 159 | #define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */ | 159 | #define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */ | 
| 160 | #define VM_RESERVED 0x00080000 /* Don't unmap it from swap_out */ | 160 | #define VM_RESERVED 0x00080000 /* Pages managed in a special way */ | 
| 161 | #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ | 161 | #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ | 
| 162 | #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ | 162 | #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ | 
| 163 | #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ | 163 | #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ | 
| @@ -338,7 +338,7 @@ static inline void get_page(struct page *page) | |||
| 338 | 338 | ||
| 339 | static inline void put_page(struct page *page) | 339 | static inline void put_page(struct page *page) | 
| 340 | { | 340 | { | 
| 341 | if (!PageReserved(page) && put_page_testzero(page)) | 341 | if (put_page_testzero(page)) | 
| 342 | __page_cache_release(page); | 342 | __page_cache_release(page); | 
| 343 | } | 343 | } | 
| 344 | 344 | ||
| @@ -723,6 +723,7 @@ void install_arg_page(struct vm_area_struct *, struct page *, unsigned long); | |||
| 723 | 723 | ||
| 724 | int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, | 724 | int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, | 
| 725 | int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); | 725 | int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); | 
| 726 | void print_bad_pte(struct vm_area_struct *, pte_t, unsigned long); | ||
| 726 | 727 | ||
| 727 | int __set_page_dirty_buffers(struct page *page); | 728 | int __set_page_dirty_buffers(struct page *page); | 
| 728 | int __set_page_dirty_nobuffers(struct page *page); | 729 | int __set_page_dirty_nobuffers(struct page *page); | 
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 10bc5ec496d7..016504ccfccf 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c  | |||
| @@ -578,15 +578,23 @@ static int save_highmem_zone(struct zone *zone) | |||
| 578 | continue; | 578 | continue; | 
| 579 | page = pfn_to_page(pfn); | 579 | page = pfn_to_page(pfn); | 
| 580 | /* | 580 | /* | 
| 581 | * This condition results from rvmalloc() sans vmalloc_32() | 581 | * PageReserved results from rvmalloc() sans vmalloc_32() | 
| 582 | * and architectural memory reservations. This should be | 582 | * and architectural memory reservations. | 
| 583 | * corrected eventually when the cases giving rise to this | 583 | * | 
| 584 | * are better understood. | 584 | * rvmalloc should not cause this, because all implementations | 
| 585 | * appear to always be using vmalloc_32 on architectures with | ||
| 586 | * highmem. This is a good thing, because we would like to save | ||
| 587 | * rvmalloc pages. | ||
| 588 | * | ||
| 589 | * It appears to be triggered by pages which do not point to | ||
| 590 | * valid memory (see arch/i386/mm/init.c:one_highpage_init(), | ||
| 591 | * which sets PageReserved if the page does not point to valid | ||
| 592 | * RAM. | ||
| 593 | * | ||
| 594 | * XXX: must remove usage of PageReserved! | ||
| 585 | */ | 595 | */ | 
| 586 | if (PageReserved(page)) { | 596 | if (PageReserved(page)) | 
| 587 | printk("highmem reserved page?!\n"); | ||
| 588 | continue; | 597 | continue; | 
| 589 | } | ||
| 590 | BUG_ON(PageNosave(page)); | 598 | BUG_ON(PageNosave(page)); | 
| 591 | if (PageNosaveFree(page)) | 599 | if (PageNosaveFree(page)) | 
| 592 | continue; | 600 | continue; | 
| @@ -672,10 +680,9 @@ static int saveable(struct zone * zone, unsigned long * zone_pfn) | |||
| 672 | return 0; | 680 | return 0; | 
| 673 | 681 | ||
| 674 | page = pfn_to_page(pfn); | 682 | page = pfn_to_page(pfn); | 
| 675 | BUG_ON(PageReserved(page) && PageNosave(page)); | ||
| 676 | if (PageNosave(page)) | 683 | if (PageNosave(page)) | 
| 677 | return 0; | 684 | return 0; | 
| 678 | if (PageReserved(page) && pfn_is_nosave(pfn)) { | 685 | if (pfn_is_nosave(pfn)) { | 
| 679 | pr_debug("[nosave pfn 0x%lx]", pfn); | 686 | pr_debug("[nosave pfn 0x%lx]", pfn); | 
| 680 | return 0; | 687 | return 0; | 
| 681 | } | 688 | } | 
diff --git a/mm/bootmem.c b/mm/bootmem.c index a58699b6579e..e8c567177dcf 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c  | |||
| @@ -305,6 +305,7 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat) | |||
| 305 | if (j + 16 < BITS_PER_LONG) | 305 | if (j + 16 < BITS_PER_LONG) | 
| 306 | prefetchw(page + j + 16); | 306 | prefetchw(page + j + 16); | 
| 307 | __ClearPageReserved(page + j); | 307 | __ClearPageReserved(page + j); | 
| 308 | set_page_count(page + j, 0); | ||
| 308 | } | 309 | } | 
| 309 | __free_pages(page, order); | 310 | __free_pages(page, order); | 
| 310 | i += BITS_PER_LONG; | 311 | i += BITS_PER_LONG; | 
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index 8c199f537732..9354ee279b13 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c  | |||
| @@ -174,6 +174,7 @@ __xip_unmap (struct address_space * mapping, | |||
| 174 | unsigned long address; | 174 | unsigned long address; | 
| 175 | pte_t *pte; | 175 | pte_t *pte; | 
| 176 | pte_t pteval; | 176 | pte_t pteval; | 
| 177 | struct page *page = ZERO_PAGE(address); | ||
| 177 | 178 | ||
| 178 | spin_lock(&mapping->i_mmap_lock); | 179 | spin_lock(&mapping->i_mmap_lock); | 
| 179 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 180 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 
| @@ -185,15 +186,17 @@ __xip_unmap (struct address_space * mapping, | |||
| 185 | * We need the page_table_lock to protect us from page faults, | 186 | * We need the page_table_lock to protect us from page faults, | 
| 186 | * munmap, fork, etc... | 187 | * munmap, fork, etc... | 
| 187 | */ | 188 | */ | 
| 188 | pte = page_check_address(ZERO_PAGE(address), mm, | 189 | pte = page_check_address(page, mm, address); | 
| 189 | address); | ||
| 190 | if (!IS_ERR(pte)) { | 190 | if (!IS_ERR(pte)) { | 
| 191 | /* Nuke the page table entry. */ | 191 | /* Nuke the page table entry. */ | 
| 192 | flush_cache_page(vma, address, pte_pfn(*pte)); | 192 | flush_cache_page(vma, address, pte_pfn(*pte)); | 
| 193 | pteval = ptep_clear_flush(vma, address, pte); | 193 | pteval = ptep_clear_flush(vma, address, pte); | 
| 194 | page_remove_rmap(page); | ||
| 195 | dec_mm_counter(mm, file_rss); | ||
| 194 | BUG_ON(pte_dirty(pteval)); | 196 | BUG_ON(pte_dirty(pteval)); | 
| 195 | pte_unmap(pte); | 197 | pte_unmap(pte); | 
| 196 | spin_unlock(&mm->page_table_lock); | 198 | spin_unlock(&mm->page_table_lock); | 
| 199 | page_cache_release(page); | ||
| 197 | } | 200 | } | 
| 198 | } | 201 | } | 
| 199 | spin_unlock(&mapping->i_mmap_lock); | 202 | spin_unlock(&mapping->i_mmap_lock); | 
| @@ -228,7 +231,7 @@ xip_file_nopage(struct vm_area_struct * area, | |||
| 228 | 231 | ||
| 229 | page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0); | 232 | page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0); | 
| 230 | if (!IS_ERR(page)) { | 233 | if (!IS_ERR(page)) { | 
| 231 | return page; | 234 | goto out; | 
| 232 | } | 235 | } | 
| 233 | if (PTR_ERR(page) != -ENODATA) | 236 | if (PTR_ERR(page) != -ENODATA) | 
| 234 | return NULL; | 237 | return NULL; | 
| @@ -249,6 +252,8 @@ xip_file_nopage(struct vm_area_struct * area, | |||
| 249 | page = ZERO_PAGE(address); | 252 | page = ZERO_PAGE(address); | 
| 250 | } | 253 | } | 
| 251 | 254 | ||
| 255 | out: | ||
| 256 | page_cache_get(page); | ||
| 252 | return page; | 257 | return page; | 
| 253 | } | 258 | } | 
| 254 | 259 | ||
diff --git a/mm/fremap.c b/mm/fremap.c index fd7f2a17ff3e..224cc1598b35 100644 --- a/mm/fremap.c +++ b/mm/fremap.c  | |||
| @@ -29,19 +29,20 @@ static inline void zap_pte(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 29 | return; | 29 | return; | 
| 30 | if (pte_present(pte)) { | 30 | if (pte_present(pte)) { | 
| 31 | unsigned long pfn = pte_pfn(pte); | 31 | unsigned long pfn = pte_pfn(pte); | 
| 32 | struct page *page; | ||
| 32 | 33 | ||
| 33 | flush_cache_page(vma, addr, pfn); | 34 | flush_cache_page(vma, addr, pfn); | 
| 34 | pte = ptep_clear_flush(vma, addr, ptep); | 35 | pte = ptep_clear_flush(vma, addr, ptep); | 
| 35 | if (pfn_valid(pfn)) { | 36 | if (unlikely(!pfn_valid(pfn))) { | 
| 36 | struct page *page = pfn_to_page(pfn); | 37 | print_bad_pte(vma, pte, addr); | 
| 37 | if (!PageReserved(page)) { | 38 | return; | 
| 38 | if (pte_dirty(pte)) | ||
| 39 | set_page_dirty(page); | ||
| 40 | page_remove_rmap(page); | ||
| 41 | page_cache_release(page); | ||
| 42 | dec_mm_counter(mm, file_rss); | ||
| 43 | } | ||
| 44 | } | 39 | } | 
| 40 | page = pfn_to_page(pfn); | ||
| 41 | if (pte_dirty(pte)) | ||
| 42 | set_page_dirty(page); | ||
| 43 | page_remove_rmap(page); | ||
| 44 | page_cache_release(page); | ||
| 45 | dec_mm_counter(mm, file_rss); | ||
| 45 | } else { | 46 | } else { | 
| 46 | if (!pte_file(pte)) | 47 | if (!pte_file(pte)) | 
| 47 | free_swap_and_cache(pte_to_swp_entry(pte)); | 48 | free_swap_and_cache(pte_to_swp_entry(pte)); | 
| @@ -65,6 +66,8 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 65 | pgd_t *pgd; | 66 | pgd_t *pgd; | 
| 66 | pte_t pte_val; | 67 | pte_t pte_val; | 
| 67 | 68 | ||
| 69 | BUG_ON(vma->vm_flags & VM_RESERVED); | ||
| 70 | |||
| 68 | pgd = pgd_offset(mm, addr); | 71 | pgd = pgd_offset(mm, addr); | 
| 69 | spin_lock(&mm->page_table_lock); | 72 | spin_lock(&mm->page_table_lock); | 
| 70 | 73 | ||
| @@ -125,6 +128,8 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 125 | pgd_t *pgd; | 128 | pgd_t *pgd; | 
| 126 | pte_t pte_val; | 129 | pte_t pte_val; | 
| 127 | 130 | ||
| 131 | BUG_ON(vma->vm_flags & VM_RESERVED); | ||
| 132 | |||
| 128 | pgd = pgd_offset(mm, addr); | 133 | pgd = pgd_offset(mm, addr); | 
| 129 | spin_lock(&mm->page_table_lock); | 134 | spin_lock(&mm->page_table_lock); | 
| 130 | 135 | ||
diff --git a/mm/madvise.c b/mm/madvise.c index 20e075d1c64c..17aaf3e16449 100644 --- a/mm/madvise.c +++ b/mm/madvise.c  | |||
| @@ -126,7 +126,7 @@ static long madvise_dontneed(struct vm_area_struct * vma, | |||
| 126 | unsigned long start, unsigned long end) | 126 | unsigned long start, unsigned long end) | 
| 127 | { | 127 | { | 
| 128 | *prev = vma; | 128 | *prev = vma; | 
| 129 | if ((vma->vm_flags & VM_LOCKED) || is_vm_hugetlb_page(vma)) | 129 | if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_RESERVED)) | 
| 130 | return -EINVAL; | 130 | return -EINVAL; | 
| 131 | 131 | ||
| 132 | if (unlikely(vma->vm_flags & VM_NONLINEAR)) { | 132 | if (unlikely(vma->vm_flags & VM_NONLINEAR)) { | 
diff --git a/mm/memory.c b/mm/memory.c index da642b5528fa..e83f9440bb66 100644 --- a/mm/memory.c +++ b/mm/memory.c  | |||
| @@ -343,6 +343,23 @@ static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss) | |||
| 343 | #define NO_RSS 2 /* Increment neither file_rss nor anon_rss */ | 343 | #define NO_RSS 2 /* Increment neither file_rss nor anon_rss */ | 
| 344 | 344 | ||
| 345 | /* | 345 | /* | 
| 346 | * This function is called to print an error when a pte in a | ||
| 347 | * !VM_RESERVED region is found pointing to an invalid pfn (which | ||
| 348 | * is an error. | ||
| 349 | * | ||
| 350 | * The calling function must still handle the error. | ||
| 351 | */ | ||
| 352 | void print_bad_pte(struct vm_area_struct *vma, pte_t pte, unsigned long vaddr) | ||
| 353 | { | ||
| 354 | printk(KERN_ERR "Bad pte = %08llx, process = %s, " | ||
| 355 | "vm_flags = %lx, vaddr = %lx\n", | ||
| 356 | (long long)pte_val(pte), | ||
| 357 | (vma->vm_mm == current->mm ? current->comm : "???"), | ||
| 358 | vma->vm_flags, vaddr); | ||
| 359 | dump_stack(); | ||
| 360 | } | ||
| 361 | |||
| 362 | /* | ||
| 346 | * copy one vm_area from one task to the other. Assumes the page tables | 363 | * copy one vm_area from one task to the other. Assumes the page tables | 
| 347 | * already present in the new task to be cleared in the whole range | 364 | * already present in the new task to be cleared in the whole range | 
| 348 | * covered by this vma. | 365 | * covered by this vma. | 
| @@ -353,9 +370,10 @@ static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss) | |||
| 353 | 370 | ||
| 354 | static inline int | 371 | static inline int | 
| 355 | copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | 372 | copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | 
| 356 | pte_t *dst_pte, pte_t *src_pte, unsigned long vm_flags, | 373 | pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *vma, | 
| 357 | unsigned long addr) | 374 | unsigned long addr) | 
| 358 | { | 375 | { | 
| 376 | unsigned long vm_flags = vma->vm_flags; | ||
| 359 | pte_t pte = *src_pte; | 377 | pte_t pte = *src_pte; | 
| 360 | struct page *page; | 378 | struct page *page; | 
| 361 | unsigned long pfn; | 379 | unsigned long pfn; | 
| @@ -375,18 +393,22 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
| 375 | goto out_set_pte; | 393 | goto out_set_pte; | 
| 376 | } | 394 | } | 
| 377 | 395 | ||
| 396 | /* If the region is VM_RESERVED, the mapping is not | ||
| 397 | * mapped via rmap - duplicate the pte as is. | ||
| 398 | */ | ||
| 399 | if (vm_flags & VM_RESERVED) | ||
| 400 | goto out_set_pte; | ||
| 401 | |||
| 378 | pfn = pte_pfn(pte); | 402 | pfn = pte_pfn(pte); | 
| 379 | /* the pte points outside of valid memory, the | 403 | /* If the pte points outside of valid memory but | 
| 380 | * mapping is assumed to be good, meaningful | 404 | * the region is not VM_RESERVED, we have a problem. | 
| 381 | * and not mapped via rmap - duplicate the | ||
| 382 | * mapping as is. | ||
| 383 | */ | 405 | */ | 
| 384 | page = NULL; | 406 | if (unlikely(!pfn_valid(pfn))) { | 
| 385 | if (pfn_valid(pfn)) | 407 | print_bad_pte(vma, pte, addr); | 
| 386 | page = pfn_to_page(pfn); | 408 | goto out_set_pte; /* try to do something sane */ | 
| 409 | } | ||
| 387 | 410 | ||
| 388 | if (!page || PageReserved(page)) | 411 | page = pfn_to_page(pfn); | 
| 389 | goto out_set_pte; | ||
| 390 | 412 | ||
| 391 | /* | 413 | /* | 
| 392 | * If it's a COW mapping, write protect it both | 414 | * If it's a COW mapping, write protect it both | 
| @@ -418,7 +440,6 @@ static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
| 418 | unsigned long addr, unsigned long end) | 440 | unsigned long addr, unsigned long end) | 
| 419 | { | 441 | { | 
| 420 | pte_t *src_pte, *dst_pte; | 442 | pte_t *src_pte, *dst_pte; | 
| 421 | unsigned long vm_flags = vma->vm_flags; | ||
| 422 | int progress = 0; | 443 | int progress = 0; | 
| 423 | int rss[NO_RSS+1], anon; | 444 | int rss[NO_RSS+1], anon; | 
| 424 | 445 | ||
| @@ -446,8 +467,7 @@ again: | |||
| 446 | progress++; | 467 | progress++; | 
| 447 | continue; | 468 | continue; | 
| 448 | } | 469 | } | 
| 449 | anon = copy_one_pte(dst_mm, src_mm, dst_pte, src_pte, | 470 | anon = copy_one_pte(dst_mm, src_mm, dst_pte, src_pte, vma,addr); | 
| 450 | vm_flags, addr); | ||
| 451 | rss[anon]++; | 471 | rss[anon]++; | 
| 452 | progress += 8; | 472 | progress += 8; | 
| 453 | } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end); | 473 | } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end); | 
| @@ -541,10 +561,12 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
| 541 | return 0; | 561 | return 0; | 
| 542 | } | 562 | } | 
| 543 | 563 | ||
| 544 | static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd, | 564 | static void zap_pte_range(struct mmu_gather *tlb, | 
| 565 | struct vm_area_struct *vma, pmd_t *pmd, | ||
| 545 | unsigned long addr, unsigned long end, | 566 | unsigned long addr, unsigned long end, | 
| 546 | struct zap_details *details) | 567 | struct zap_details *details) | 
| 547 | { | 568 | { | 
| 569 | struct mm_struct *mm = tlb->mm; | ||
| 548 | pte_t *pte; | 570 | pte_t *pte; | 
| 549 | int file_rss = 0; | 571 | int file_rss = 0; | 
| 550 | int anon_rss = 0; | 572 | int anon_rss = 0; | 
| @@ -556,11 +578,12 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd, | |||
| 556 | continue; | 578 | continue; | 
| 557 | if (pte_present(ptent)) { | 579 | if (pte_present(ptent)) { | 
| 558 | struct page *page = NULL; | 580 | struct page *page = NULL; | 
| 559 | unsigned long pfn = pte_pfn(ptent); | 581 | if (!(vma->vm_flags & VM_RESERVED)) { | 
| 560 | if (pfn_valid(pfn)) { | 582 | unsigned long pfn = pte_pfn(ptent); | 
| 561 | page = pfn_to_page(pfn); | 583 | if (unlikely(!pfn_valid(pfn))) | 
| 562 | if (PageReserved(page)) | 584 | print_bad_pte(vma, ptent, addr); | 
| 563 | page = NULL; | 585 | else | 
| 586 | page = pfn_to_page(pfn); | ||
| 564 | } | 587 | } | 
| 565 | if (unlikely(details) && page) { | 588 | if (unlikely(details) && page) { | 
| 566 | /* | 589 | /* | 
| @@ -580,7 +603,7 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd, | |||
| 580 | page->index > details->last_index)) | 603 | page->index > details->last_index)) | 
| 581 | continue; | 604 | continue; | 
| 582 | } | 605 | } | 
| 583 | ptent = ptep_get_and_clear_full(tlb->mm, addr, pte, | 606 | ptent = ptep_get_and_clear_full(mm, addr, pte, | 
| 584 | tlb->fullmm); | 607 | tlb->fullmm); | 
| 585 | tlb_remove_tlb_entry(tlb, pte, addr); | 608 | tlb_remove_tlb_entry(tlb, pte, addr); | 
| 586 | if (unlikely(!page)) | 609 | if (unlikely(!page)) | 
| @@ -588,7 +611,7 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd, | |||
| 588 | if (unlikely(details) && details->nonlinear_vma | 611 | if (unlikely(details) && details->nonlinear_vma | 
| 589 | && linear_page_index(details->nonlinear_vma, | 612 | && linear_page_index(details->nonlinear_vma, | 
| 590 | addr) != page->index) | 613 | addr) != page->index) | 
| 591 | set_pte_at(tlb->mm, addr, pte, | 614 | set_pte_at(mm, addr, pte, | 
| 592 | pgoff_to_pte(page->index)); | 615 | pgoff_to_pte(page->index)); | 
| 593 | if (PageAnon(page)) | 616 | if (PageAnon(page)) | 
| 594 | anon_rss++; | 617 | anon_rss++; | 
| @@ -611,14 +634,15 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd, | |||
| 611 | continue; | 634 | continue; | 
| 612 | if (!pte_file(ptent)) | 635 | if (!pte_file(ptent)) | 
| 613 | free_swap_and_cache(pte_to_swp_entry(ptent)); | 636 | free_swap_and_cache(pte_to_swp_entry(ptent)); | 
| 614 | pte_clear_full(tlb->mm, addr, pte, tlb->fullmm); | 637 | pte_clear_full(mm, addr, pte, tlb->fullmm); | 
| 615 | } while (pte++, addr += PAGE_SIZE, addr != end); | 638 | } while (pte++, addr += PAGE_SIZE, addr != end); | 
| 616 | 639 | ||
| 617 | add_mm_rss(tlb->mm, -file_rss, -anon_rss); | 640 | add_mm_rss(mm, -file_rss, -anon_rss); | 
| 618 | pte_unmap(pte - 1); | 641 | pte_unmap(pte - 1); | 
| 619 | } | 642 | } | 
| 620 | 643 | ||
| 621 | static inline void zap_pmd_range(struct mmu_gather *tlb, pud_t *pud, | 644 | static inline void zap_pmd_range(struct mmu_gather *tlb, | 
| 645 | struct vm_area_struct *vma, pud_t *pud, | ||
| 622 | unsigned long addr, unsigned long end, | 646 | unsigned long addr, unsigned long end, | 
| 623 | struct zap_details *details) | 647 | struct zap_details *details) | 
| 624 | { | 648 | { | 
| @@ -630,11 +654,12 @@ static inline void zap_pmd_range(struct mmu_gather *tlb, pud_t *pud, | |||
| 630 | next = pmd_addr_end(addr, end); | 654 | next = pmd_addr_end(addr, end); | 
| 631 | if (pmd_none_or_clear_bad(pmd)) | 655 | if (pmd_none_or_clear_bad(pmd)) | 
| 632 | continue; | 656 | continue; | 
| 633 | zap_pte_range(tlb, pmd, addr, next, details); | 657 | zap_pte_range(tlb, vma, pmd, addr, next, details); | 
| 634 | } while (pmd++, addr = next, addr != end); | 658 | } while (pmd++, addr = next, addr != end); | 
| 635 | } | 659 | } | 
| 636 | 660 | ||
| 637 | static inline void zap_pud_range(struct mmu_gather *tlb, pgd_t *pgd, | 661 | static inline void zap_pud_range(struct mmu_gather *tlb, | 
| 662 | struct vm_area_struct *vma, pgd_t *pgd, | ||
| 638 | unsigned long addr, unsigned long end, | 663 | unsigned long addr, unsigned long end, | 
| 639 | struct zap_details *details) | 664 | struct zap_details *details) | 
| 640 | { | 665 | { | 
| @@ -646,7 +671,7 @@ static inline void zap_pud_range(struct mmu_gather *tlb, pgd_t *pgd, | |||
| 646 | next = pud_addr_end(addr, end); | 671 | next = pud_addr_end(addr, end); | 
| 647 | if (pud_none_or_clear_bad(pud)) | 672 | if (pud_none_or_clear_bad(pud)) | 
| 648 | continue; | 673 | continue; | 
| 649 | zap_pmd_range(tlb, pud, addr, next, details); | 674 | zap_pmd_range(tlb, vma, pud, addr, next, details); | 
| 650 | } while (pud++, addr = next, addr != end); | 675 | } while (pud++, addr = next, addr != end); | 
| 651 | } | 676 | } | 
| 652 | 677 | ||
| @@ -667,7 +692,7 @@ static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma, | |||
| 667 | next = pgd_addr_end(addr, end); | 692 | next = pgd_addr_end(addr, end); | 
| 668 | if (pgd_none_or_clear_bad(pgd)) | 693 | if (pgd_none_or_clear_bad(pgd)) | 
| 669 | continue; | 694 | continue; | 
| 670 | zap_pud_range(tlb, pgd, addr, next, details); | 695 | zap_pud_range(tlb, vma, pgd, addr, next, details); | 
| 671 | } while (pgd++, addr = next, addr != end); | 696 | } while (pgd++, addr = next, addr != end); | 
| 672 | tlb_end_vma(tlb, vma); | 697 | tlb_end_vma(tlb, vma); | 
| 673 | } | 698 | } | 
| @@ -967,7 +992,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 967 | continue; | 992 | continue; | 
| 968 | } | 993 | } | 
| 969 | 994 | ||
| 970 | if (!vma || (vma->vm_flags & VM_IO) | 995 | if (!vma || (vma->vm_flags & (VM_IO | VM_RESERVED)) | 
| 971 | || !(flags & vma->vm_flags)) | 996 | || !(flags & vma->vm_flags)) | 
| 972 | return i ? : -EFAULT; | 997 | return i ? : -EFAULT; | 
| 973 | 998 | ||
| @@ -1027,8 +1052,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1027 | if (pages) { | 1052 | if (pages) { | 
| 1028 | pages[i] = page; | 1053 | pages[i] = page; | 
| 1029 | flush_dcache_page(page); | 1054 | flush_dcache_page(page); | 
| 1030 | if (!PageReserved(page)) | 1055 | page_cache_get(page); | 
| 1031 | page_cache_get(page); | ||
| 1032 | } | 1056 | } | 
| 1033 | if (vmas) | 1057 | if (vmas) | 
| 1034 | vmas[i] = vma; | 1058 | vmas[i] = vma; | 
| @@ -1051,7 +1075,11 @@ static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd, | |||
| 1051 | if (!pte) | 1075 | if (!pte) | 
| 1052 | return -ENOMEM; | 1076 | return -ENOMEM; | 
| 1053 | do { | 1077 | do { | 
| 1054 | pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(addr), prot)); | 1078 | struct page *page = ZERO_PAGE(addr); | 
| 1079 | pte_t zero_pte = pte_wrprotect(mk_pte(page, prot)); | ||
| 1080 | page_cache_get(page); | ||
| 1081 | page_add_file_rmap(page); | ||
| 1082 | inc_mm_counter(mm, file_rss); | ||
| 1055 | BUG_ON(!pte_none(*pte)); | 1083 | BUG_ON(!pte_none(*pte)); | 
| 1056 | set_pte_at(mm, addr, pte, zero_pte); | 1084 | set_pte_at(mm, addr, pte, zero_pte); | 
| 1057 | } while (pte++, addr += PAGE_SIZE, addr != end); | 1085 | } while (pte++, addr += PAGE_SIZE, addr != end); | 
| @@ -1132,8 +1160,7 @@ static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd, | |||
| 1132 | return -ENOMEM; | 1160 | return -ENOMEM; | 
| 1133 | do { | 1161 | do { | 
| 1134 | BUG_ON(!pte_none(*pte)); | 1162 | BUG_ON(!pte_none(*pte)); | 
| 1135 | if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn))) | 1163 | set_pte_at(mm, addr, pte, pfn_pte(pfn, prot)); | 
| 1136 | set_pte_at(mm, addr, pte, pfn_pte(pfn, prot)); | ||
| 1137 | pfn++; | 1164 | pfn++; | 
| 1138 | } while (pte++, addr += PAGE_SIZE, addr != end); | 1165 | } while (pte++, addr += PAGE_SIZE, addr != end); | 
| 1139 | pte_unmap(pte - 1); | 1166 | pte_unmap(pte - 1); | 
| @@ -1195,8 +1222,8 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, | |||
| 1195 | * rest of the world about it: | 1222 | * rest of the world about it: | 
| 1196 | * VM_IO tells people not to look at these pages | 1223 | * VM_IO tells people not to look at these pages | 
| 1197 | * (accesses can have side effects). | 1224 | * (accesses can have side effects). | 
| 1198 | * VM_RESERVED tells swapout not to try to touch | 1225 | * VM_RESERVED tells the core MM not to "manage" these pages | 
| 1199 | * this region. | 1226 | * (e.g. refcount, mapcount, try to swap them out). | 
| 1200 | */ | 1227 | */ | 
| 1201 | vma->vm_flags |= VM_IO | VM_RESERVED; | 1228 | vma->vm_flags |= VM_IO | VM_RESERVED; | 
| 1202 | 1229 | ||
| @@ -1256,11 +1283,13 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1256 | pte_t entry; | 1283 | pte_t entry; | 
| 1257 | int ret = VM_FAULT_MINOR; | 1284 | int ret = VM_FAULT_MINOR; | 
| 1258 | 1285 | ||
| 1286 | BUG_ON(vma->vm_flags & VM_RESERVED); | ||
| 1287 | |||
| 1259 | if (unlikely(!pfn_valid(pfn))) { | 1288 | if (unlikely(!pfn_valid(pfn))) { | 
| 1260 | /* | 1289 | /* | 
| 1261 | * Page table corrupted: show pte and kill process. | 1290 | * Page table corrupted: show pte and kill process. | 
| 1262 | */ | 1291 | */ | 
| 1263 | pte_ERROR(orig_pte); | 1292 | print_bad_pte(vma, orig_pte, address); | 
| 1264 | ret = VM_FAULT_OOM; | 1293 | ret = VM_FAULT_OOM; | 
| 1265 | goto unlock; | 1294 | goto unlock; | 
| 1266 | } | 1295 | } | 
| @@ -1284,8 +1313,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1284 | /* | 1313 | /* | 
| 1285 | * Ok, we need to copy. Oh, well.. | 1314 | * Ok, we need to copy. Oh, well.. | 
| 1286 | */ | 1315 | */ | 
| 1287 | if (!PageReserved(old_page)) | 1316 | page_cache_get(old_page); | 
| 1288 | page_cache_get(old_page); | ||
| 1289 | pte_unmap(page_table); | 1317 | pte_unmap(page_table); | 
| 1290 | spin_unlock(&mm->page_table_lock); | 1318 | spin_unlock(&mm->page_table_lock); | 
| 1291 | 1319 | ||
| @@ -1308,14 +1336,10 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1308 | spin_lock(&mm->page_table_lock); | 1336 | spin_lock(&mm->page_table_lock); | 
| 1309 | page_table = pte_offset_map(pmd, address); | 1337 | page_table = pte_offset_map(pmd, address); | 
| 1310 | if (likely(pte_same(*page_table, orig_pte))) { | 1338 | if (likely(pte_same(*page_table, orig_pte))) { | 
| 1311 | if (PageReserved(old_page)) | 1339 | page_remove_rmap(old_page); | 
| 1340 | if (!PageAnon(old_page)) { | ||
| 1312 | inc_mm_counter(mm, anon_rss); | 1341 | inc_mm_counter(mm, anon_rss); | 
| 1313 | else { | 1342 | dec_mm_counter(mm, file_rss); | 
| 1314 | page_remove_rmap(old_page); | ||
| 1315 | if (!PageAnon(old_page)) { | ||
| 1316 | inc_mm_counter(mm, anon_rss); | ||
| 1317 | dec_mm_counter(mm, file_rss); | ||
| 1318 | } | ||
| 1319 | } | 1343 | } | 
| 1320 | flush_cache_page(vma, address, pfn); | 1344 | flush_cache_page(vma, address, pfn); | 
| 1321 | entry = mk_pte(new_page, vma->vm_page_prot); | 1345 | entry = mk_pte(new_page, vma->vm_page_prot); | 
| @@ -1769,14 +1793,13 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1769 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 1793 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 
| 1770 | int write_access) | 1794 | int write_access) | 
| 1771 | { | 1795 | { | 
| 1796 | struct page *page = ZERO_PAGE(addr); | ||
| 1772 | pte_t entry; | 1797 | pte_t entry; | 
| 1773 | 1798 | ||
| 1774 | /* Mapping of ZERO_PAGE - vm_page_prot is readonly */ | 1799 | /* Mapping of ZERO_PAGE - vm_page_prot is readonly */ | 
| 1775 | entry = mk_pte(ZERO_PAGE(addr), vma->vm_page_prot); | 1800 | entry = mk_pte(page, vma->vm_page_prot); | 
| 1776 | 1801 | ||
| 1777 | if (write_access) { | 1802 | if (write_access) { | 
| 1778 | struct page *page; | ||
| 1779 | |||
| 1780 | /* Allocate our own private page. */ | 1803 | /* Allocate our own private page. */ | 
| 1781 | pte_unmap(page_table); | 1804 | pte_unmap(page_table); | 
| 1782 | spin_unlock(&mm->page_table_lock); | 1805 | spin_unlock(&mm->page_table_lock); | 
| @@ -1800,6 +1823,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1800 | lru_cache_add_active(page); | 1823 | lru_cache_add_active(page); | 
| 1801 | SetPageReferenced(page); | 1824 | SetPageReferenced(page); | 
| 1802 | page_add_anon_rmap(page, vma, address); | 1825 | page_add_anon_rmap(page, vma, address); | 
| 1826 | } else { | ||
| 1827 | inc_mm_counter(mm, file_rss); | ||
| 1828 | page_add_file_rmap(page); | ||
| 1829 | page_cache_get(page); | ||
| 1803 | } | 1830 | } | 
| 1804 | 1831 | ||
| 1805 | set_pte_at(mm, address, page_table, entry); | 1832 | set_pte_at(mm, address, page_table, entry); | 
| @@ -1916,7 +1943,7 @@ retry: | |||
| 1916 | inc_mm_counter(mm, anon_rss); | 1943 | inc_mm_counter(mm, anon_rss); | 
| 1917 | lru_cache_add_active(new_page); | 1944 | lru_cache_add_active(new_page); | 
| 1918 | page_add_anon_rmap(new_page, vma, address); | 1945 | page_add_anon_rmap(new_page, vma, address); | 
| 1919 | } else if (!PageReserved(new_page)) { | 1946 | } else if (!(vma->vm_flags & VM_RESERVED)) { | 
| 1920 | inc_mm_counter(mm, file_rss); | 1947 | inc_mm_counter(mm, file_rss); | 
| 1921 | page_add_file_rmap(new_page); | 1948 | page_add_file_rmap(new_page); | 
| 1922 | } | 1949 | } | 
| @@ -1957,7 +1984,7 @@ static int do_file_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1957 | /* | 1984 | /* | 
| 1958 | * Page table corrupted: show pte and kill process. | 1985 | * Page table corrupted: show pte and kill process. | 
| 1959 | */ | 1986 | */ | 
| 1960 | pte_ERROR(orig_pte); | 1987 | print_bad_pte(vma, orig_pte, address); | 
| 1961 | return VM_FAULT_OOM; | 1988 | return VM_FAULT_OOM; | 
| 1962 | } | 1989 | } | 
| 1963 | /* We can then assume vm->vm_ops && vma->vm_ops->populate */ | 1990 | /* We can then assume vm->vm_ops && vma->vm_ops->populate */ | 
| @@ -2232,7 +2259,7 @@ static int __init gate_vma_init(void) | |||
| 2232 | gate_vma.vm_start = FIXADDR_USER_START; | 2259 | gate_vma.vm_start = FIXADDR_USER_START; | 
| 2233 | gate_vma.vm_end = FIXADDR_USER_END; | 2260 | gate_vma.vm_end = FIXADDR_USER_END; | 
| 2234 | gate_vma.vm_page_prot = PAGE_READONLY; | 2261 | gate_vma.vm_page_prot = PAGE_READONLY; | 
| 2235 | gate_vma.vm_flags = 0; | 2262 | gate_vma.vm_flags = VM_RESERVED; | 
| 2236 | return 0; | 2263 | return 0; | 
| 2237 | } | 2264 | } | 
| 2238 | __initcall(gate_vma_init); | 2265 | __initcall(gate_vma_init); | 
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 43b1199af591..11d824f282f1 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c  | |||
| @@ -223,13 +223,13 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes) | |||
| 223 | } | 223 | } | 
| 224 | 224 | ||
| 225 | /* Ensure all existing pages follow the policy. */ | 225 | /* Ensure all existing pages follow the policy. */ | 
| 226 | static int check_pte_range(struct mm_struct *mm, pmd_t *pmd, | 226 | static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | 
| 227 | unsigned long addr, unsigned long end, nodemask_t *nodes) | 227 | unsigned long addr, unsigned long end, nodemask_t *nodes) | 
| 228 | { | 228 | { | 
| 229 | pte_t *orig_pte; | 229 | pte_t *orig_pte; | 
| 230 | pte_t *pte; | 230 | pte_t *pte; | 
| 231 | 231 | ||
| 232 | spin_lock(&mm->page_table_lock); | 232 | spin_lock(&vma->vm_mm->page_table_lock); | 
| 233 | orig_pte = pte = pte_offset_map(pmd, addr); | 233 | orig_pte = pte = pte_offset_map(pmd, addr); | 
| 234 | do { | 234 | do { | 
| 235 | unsigned long pfn; | 235 | unsigned long pfn; | 
| @@ -238,18 +238,20 @@ static int check_pte_range(struct mm_struct *mm, pmd_t *pmd, | |||
| 238 | if (!pte_present(*pte)) | 238 | if (!pte_present(*pte)) | 
| 239 | continue; | 239 | continue; | 
| 240 | pfn = pte_pfn(*pte); | 240 | pfn = pte_pfn(*pte); | 
| 241 | if (!pfn_valid(pfn)) | 241 | if (!pfn_valid(pfn)) { | 
| 242 | print_bad_pte(vma, *pte, addr); | ||
| 242 | continue; | 243 | continue; | 
| 244 | } | ||
| 243 | nid = pfn_to_nid(pfn); | 245 | nid = pfn_to_nid(pfn); | 
| 244 | if (!node_isset(nid, *nodes)) | 246 | if (!node_isset(nid, *nodes)) | 
| 245 | break; | 247 | break; | 
| 246 | } while (pte++, addr += PAGE_SIZE, addr != end); | 248 | } while (pte++, addr += PAGE_SIZE, addr != end); | 
| 247 | pte_unmap(orig_pte); | 249 | pte_unmap(orig_pte); | 
| 248 | spin_unlock(&mm->page_table_lock); | 250 | spin_unlock(&vma->vm_mm->page_table_lock); | 
| 249 | return addr != end; | 251 | return addr != end; | 
| 250 | } | 252 | } | 
| 251 | 253 | ||
| 252 | static inline int check_pmd_range(struct mm_struct *mm, pud_t *pud, | 254 | static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud, | 
| 253 | unsigned long addr, unsigned long end, nodemask_t *nodes) | 255 | unsigned long addr, unsigned long end, nodemask_t *nodes) | 
| 254 | { | 256 | { | 
| 255 | pmd_t *pmd; | 257 | pmd_t *pmd; | 
| @@ -260,13 +262,13 @@ static inline int check_pmd_range(struct mm_struct *mm, pud_t *pud, | |||
| 260 | next = pmd_addr_end(addr, end); | 262 | next = pmd_addr_end(addr, end); | 
| 261 | if (pmd_none_or_clear_bad(pmd)) | 263 | if (pmd_none_or_clear_bad(pmd)) | 
| 262 | continue; | 264 | continue; | 
| 263 | if (check_pte_range(mm, pmd, addr, next, nodes)) | 265 | if (check_pte_range(vma, pmd, addr, next, nodes)) | 
| 264 | return -EIO; | 266 | return -EIO; | 
| 265 | } while (pmd++, addr = next, addr != end); | 267 | } while (pmd++, addr = next, addr != end); | 
| 266 | return 0; | 268 | return 0; | 
| 267 | } | 269 | } | 
| 268 | 270 | ||
| 269 | static inline int check_pud_range(struct mm_struct *mm, pgd_t *pgd, | 271 | static inline int check_pud_range(struct vm_area_struct *vma, pgd_t *pgd, | 
| 270 | unsigned long addr, unsigned long end, nodemask_t *nodes) | 272 | unsigned long addr, unsigned long end, nodemask_t *nodes) | 
| 271 | { | 273 | { | 
| 272 | pud_t *pud; | 274 | pud_t *pud; | 
| @@ -277,24 +279,24 @@ static inline int check_pud_range(struct mm_struct *mm, pgd_t *pgd, | |||
| 277 | next = pud_addr_end(addr, end); | 279 | next = pud_addr_end(addr, end); | 
| 278 | if (pud_none_or_clear_bad(pud)) | 280 | if (pud_none_or_clear_bad(pud)) | 
| 279 | continue; | 281 | continue; | 
| 280 | if (check_pmd_range(mm, pud, addr, next, nodes)) | 282 | if (check_pmd_range(vma, pud, addr, next, nodes)) | 
| 281 | return -EIO; | 283 | return -EIO; | 
| 282 | } while (pud++, addr = next, addr != end); | 284 | } while (pud++, addr = next, addr != end); | 
| 283 | return 0; | 285 | return 0; | 
| 284 | } | 286 | } | 
| 285 | 287 | ||
| 286 | static inline int check_pgd_range(struct mm_struct *mm, | 288 | static inline int check_pgd_range(struct vm_area_struct *vma, | 
| 287 | unsigned long addr, unsigned long end, nodemask_t *nodes) | 289 | unsigned long addr, unsigned long end, nodemask_t *nodes) | 
| 288 | { | 290 | { | 
| 289 | pgd_t *pgd; | 291 | pgd_t *pgd; | 
| 290 | unsigned long next; | 292 | unsigned long next; | 
| 291 | 293 | ||
| 292 | pgd = pgd_offset(mm, addr); | 294 | pgd = pgd_offset(vma->vm_mm, addr); | 
| 293 | do { | 295 | do { | 
| 294 | next = pgd_addr_end(addr, end); | 296 | next = pgd_addr_end(addr, end); | 
| 295 | if (pgd_none_or_clear_bad(pgd)) | 297 | if (pgd_none_or_clear_bad(pgd)) | 
| 296 | continue; | 298 | continue; | 
| 297 | if (check_pud_range(mm, pgd, addr, next, nodes)) | 299 | if (check_pud_range(vma, pgd, addr, next, nodes)) | 
| 298 | return -EIO; | 300 | return -EIO; | 
| 299 | } while (pgd++, addr = next, addr != end); | 301 | } while (pgd++, addr = next, addr != end); | 
| 300 | return 0; | 302 | return 0; | 
| @@ -311,6 +313,8 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, | |||
| 311 | first = find_vma(mm, start); | 313 | first = find_vma(mm, start); | 
| 312 | if (!first) | 314 | if (!first) | 
| 313 | return ERR_PTR(-EFAULT); | 315 | return ERR_PTR(-EFAULT); | 
| 316 | if (first->vm_flags & VM_RESERVED) | ||
| 317 | return ERR_PTR(-EACCES); | ||
| 314 | prev = NULL; | 318 | prev = NULL; | 
| 315 | for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) { | 319 | for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) { | 
| 316 | if (!vma->vm_next && vma->vm_end < end) | 320 | if (!vma->vm_next && vma->vm_end < end) | 
| @@ -323,8 +327,7 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, | |||
| 323 | endvma = end; | 327 | endvma = end; | 
| 324 | if (vma->vm_start > start) | 328 | if (vma->vm_start > start) | 
| 325 | start = vma->vm_start; | 329 | start = vma->vm_start; | 
| 326 | err = check_pgd_range(vma->vm_mm, | 330 | err = check_pgd_range(vma, start, endvma, nodes); | 
| 327 | start, endvma, nodes); | ||
| 328 | if (err) { | 331 | if (err) { | 
| 329 | first = ERR_PTR(err); | 332 | first = ERR_PTR(err); | 
| 330 | break; | 333 | break; | 
| @@ -1088,6 +1088,17 @@ munmap_back: | |||
| 1088 | error = file->f_op->mmap(file, vma); | 1088 | error = file->f_op->mmap(file, vma); | 
| 1089 | if (error) | 1089 | if (error) | 
| 1090 | goto unmap_and_free_vma; | 1090 | goto unmap_and_free_vma; | 
| 1091 | if ((vma->vm_flags & (VM_SHARED | VM_WRITE | VM_RESERVED)) | ||
| 1092 | == (VM_WRITE | VM_RESERVED)) { | ||
| 1093 | printk(KERN_WARNING "program %s is using MAP_PRIVATE, " | ||
| 1094 | "PROT_WRITE mmap of VM_RESERVED memory, which " | ||
| 1095 | "is deprecated. Please report this to " | ||
| 1096 | "linux-kernel@vger.kernel.org\n",current->comm); | ||
| 1097 | if (vma->vm_ops && vma->vm_ops->close) | ||
| 1098 | vma->vm_ops->close(vma); | ||
| 1099 | error = -EACCES; | ||
| 1100 | goto unmap_and_free_vma; | ||
| 1101 | } | ||
| 1091 | } else if (vm_flags & VM_SHARED) { | 1102 | } else if (vm_flags & VM_SHARED) { | 
| 1092 | error = shmem_zero_setup(vma); | 1103 | error = shmem_zero_setup(vma); | 
| 1093 | if (error) | 1104 | if (error) | 
diff --git a/mm/mprotect.c b/mm/mprotect.c index b426f01c5e9c..672a76fddd5e 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c  | |||
| @@ -125,6 +125,14 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, | |||
| 125 | * a MAP_NORESERVE private mapping to writable will now reserve. | 125 | * a MAP_NORESERVE private mapping to writable will now reserve. | 
| 126 | */ | 126 | */ | 
| 127 | if (newflags & VM_WRITE) { | 127 | if (newflags & VM_WRITE) { | 
| 128 | if (oldflags & VM_RESERVED) { | ||
| 129 | BUG_ON(oldflags & VM_WRITE); | ||
| 130 | printk(KERN_WARNING "program %s is using MAP_PRIVATE, " | ||
| 131 | "PROT_WRITE mprotect of VM_RESERVED memory, " | ||
| 132 | "which is deprecated. Please report this to " | ||
| 133 | "linux-kernel@vger.kernel.org\n",current->comm); | ||
| 134 | return -EACCES; | ||
| 135 | } | ||
| 128 | if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) { | 136 | if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) { | 
| 129 | charged = nrpages; | 137 | charged = nrpages; | 
| 130 | if (security_vm_enough_memory(charged)) | 138 | if (security_vm_enough_memory(charged)) | 
diff --git a/mm/msync.c b/mm/msync.c index 3b5f1c521d4b..860395486060 100644 --- a/mm/msync.c +++ b/mm/msync.c  | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | static void msync_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | 25 | static void msync_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | 
| 26 | unsigned long addr, unsigned long end) | 26 | unsigned long addr, unsigned long end) | 
| 27 | { | 27 | { | 
| 28 | struct mm_struct *mm = vma->vm_mm; | ||
| 28 | pte_t *pte; | 29 | pte_t *pte; | 
| 29 | int progress = 0; | 30 | int progress = 0; | 
| 30 | 31 | ||
| @@ -37,7 +38,7 @@ again: | |||
| 37 | if (progress >= 64) { | 38 | if (progress >= 64) { | 
| 38 | progress = 0; | 39 | progress = 0; | 
| 39 | if (need_resched() || | 40 | if (need_resched() || | 
| 40 | need_lockbreak(&vma->vm_mm->page_table_lock)) | 41 | need_lockbreak(&mm->page_table_lock)) | 
| 41 | break; | 42 | break; | 
| 42 | } | 43 | } | 
| 43 | progress++; | 44 | progress++; | 
| @@ -46,11 +47,11 @@ again: | |||
| 46 | if (!pte_maybe_dirty(*pte)) | 47 | if (!pte_maybe_dirty(*pte)) | 
| 47 | continue; | 48 | continue; | 
| 48 | pfn = pte_pfn(*pte); | 49 | pfn = pte_pfn(*pte); | 
| 49 | if (!pfn_valid(pfn)) | 50 | if (unlikely(!pfn_valid(pfn))) { | 
| 51 | print_bad_pte(vma, *pte, addr); | ||
| 50 | continue; | 52 | continue; | 
| 53 | } | ||
| 51 | page = pfn_to_page(pfn); | 54 | page = pfn_to_page(pfn); | 
| 52 | if (PageReserved(page)) | ||
| 53 | continue; | ||
| 54 | 55 | ||
| 55 | if (ptep_clear_flush_dirty(vma, addr, pte) || | 56 | if (ptep_clear_flush_dirty(vma, addr, pte) || | 
| 56 | page_test_and_clear_dirty(page)) | 57 | page_test_and_clear_dirty(page)) | 
| @@ -58,7 +59,7 @@ again: | |||
| 58 | progress += 3; | 59 | progress += 3; | 
| 59 | } while (pte++, addr += PAGE_SIZE, addr != end); | 60 | } while (pte++, addr += PAGE_SIZE, addr != end); | 
| 60 | pte_unmap(pte - 1); | 61 | pte_unmap(pte - 1); | 
| 61 | cond_resched_lock(&vma->vm_mm->page_table_lock); | 62 | cond_resched_lock(&mm->page_table_lock); | 
| 62 | if (addr != end) | 63 | if (addr != end) | 
| 63 | goto again; | 64 | goto again; | 
| 64 | } | 65 | } | 
| @@ -102,8 +103,10 @@ static void msync_page_range(struct vm_area_struct *vma, | |||
| 102 | 103 | ||
| 103 | /* For hugepages we can't go walking the page table normally, | 104 | /* For hugepages we can't go walking the page table normally, | 
| 104 | * but that's ok, hugetlbfs is memory based, so we don't need | 105 | * but that's ok, hugetlbfs is memory based, so we don't need | 
| 105 | * to do anything more on an msync() */ | 106 | * to do anything more on an msync(). | 
| 106 | if (is_vm_hugetlb_page(vma)) | 107 | * Can't do anything with VM_RESERVED regions either. | 
| 108 | */ | ||
| 109 | if (vma->vm_flags & (VM_HUGETLB|VM_RESERVED)) | ||
| 107 | return; | 110 | return; | 
| 108 | 111 | ||
| 109 | BUG_ON(addr >= end); | 112 | BUG_ON(addr >= end); | 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 60663232fbb2..0541288ebf4b 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c  | |||
| @@ -114,7 +114,8 @@ static void bad_page(const char *function, struct page *page) | |||
| 114 | 1 << PG_reclaim | | 114 | 1 << PG_reclaim | | 
| 115 | 1 << PG_slab | | 115 | 1 << PG_slab | | 
| 116 | 1 << PG_swapcache | | 116 | 1 << PG_swapcache | | 
| 117 | 1 << PG_writeback); | 117 | 1 << PG_writeback | | 
| 118 | 1 << PG_reserved ); | ||
| 118 | set_page_count(page, 0); | 119 | set_page_count(page, 0); | 
| 119 | reset_page_mapcount(page); | 120 | reset_page_mapcount(page); | 
| 120 | page->mapping = NULL; | 121 | page->mapping = NULL; | 
| @@ -244,7 +245,6 @@ static inline int page_is_buddy(struct page *page, int order) | |||
| 244 | { | 245 | { | 
| 245 | if (PagePrivate(page) && | 246 | if (PagePrivate(page) && | 
| 246 | (page_order(page) == order) && | 247 | (page_order(page) == order) && | 
| 247 | !PageReserved(page) && | ||
| 248 | page_count(page) == 0) | 248 | page_count(page) == 0) | 
| 249 | return 1; | 249 | return 1; | 
| 250 | return 0; | 250 | return 0; | 
| @@ -327,7 +327,8 @@ static inline void free_pages_check(const char *function, struct page *page) | |||
| 327 | 1 << PG_reclaim | | 327 | 1 << PG_reclaim | | 
| 328 | 1 << PG_slab | | 328 | 1 << PG_slab | | 
| 329 | 1 << PG_swapcache | | 329 | 1 << PG_swapcache | | 
| 330 | 1 << PG_writeback ))) | 330 | 1 << PG_writeback | | 
| 331 | 1 << PG_reserved ))) | ||
| 331 | bad_page(function, page); | 332 | bad_page(function, page); | 
| 332 | if (PageDirty(page)) | 333 | if (PageDirty(page)) | 
| 333 | __ClearPageDirty(page); | 334 | __ClearPageDirty(page); | 
| @@ -455,7 +456,8 @@ static void prep_new_page(struct page *page, int order) | |||
| 455 | 1 << PG_reclaim | | 456 | 1 << PG_reclaim | | 
| 456 | 1 << PG_slab | | 457 | 1 << PG_slab | | 
| 457 | 1 << PG_swapcache | | 458 | 1 << PG_swapcache | | 
| 458 | 1 << PG_writeback ))) | 459 | 1 << PG_writeback | | 
| 460 | 1 << PG_reserved ))) | ||
| 459 | bad_page(__FUNCTION__, page); | 461 | bad_page(__FUNCTION__, page); | 
| 460 | 462 | ||
| 461 | page->flags &= ~(1 << PG_uptodate | 1 << PG_error | | 463 | page->flags &= ~(1 << PG_uptodate | 1 << PG_error | | 
| @@ -1016,7 +1018,7 @@ void __pagevec_free(struct pagevec *pvec) | |||
| 1016 | 1018 | ||
| 1017 | fastcall void __free_pages(struct page *page, unsigned int order) | 1019 | fastcall void __free_pages(struct page *page, unsigned int order) | 
| 1018 | { | 1020 | { | 
| 1019 | if (!PageReserved(page) && put_page_testzero(page)) { | 1021 | if (put_page_testzero(page)) { | 
| 1020 | if (order == 0) | 1022 | if (order == 0) | 
| 1021 | free_hot_page(page); | 1023 | free_hot_page(page); | 
| 1022 | else | 1024 | else | 
| @@ -1674,7 +1676,7 @@ void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
| 1674 | continue; | 1676 | continue; | 
| 1675 | page = pfn_to_page(pfn); | 1677 | page = pfn_to_page(pfn); | 
| 1676 | set_page_links(page, zone, nid, pfn); | 1678 | set_page_links(page, zone, nid, pfn); | 
| 1677 | set_page_count(page, 0); | 1679 | set_page_count(page, 1); | 
| 1678 | reset_page_mapcount(page); | 1680 | reset_page_mapcount(page); | 
| 1679 | SetPageReserved(page); | 1681 | SetPageReserved(page); | 
| 1680 | INIT_LIST_HEAD(&page->lru); | 1682 | INIT_LIST_HEAD(&page->lru); | 
| @@ -443,8 +443,6 @@ int page_referenced(struct page *page, int is_locked, int ignore_token) | |||
| 443 | void page_add_anon_rmap(struct page *page, | 443 | void page_add_anon_rmap(struct page *page, | 
| 444 | struct vm_area_struct *vma, unsigned long address) | 444 | struct vm_area_struct *vma, unsigned long address) | 
| 445 | { | 445 | { | 
| 446 | BUG_ON(PageReserved(page)); | ||
| 447 | |||
| 448 | if (atomic_inc_and_test(&page->_mapcount)) { | 446 | if (atomic_inc_and_test(&page->_mapcount)) { | 
| 449 | struct anon_vma *anon_vma = vma->anon_vma; | 447 | struct anon_vma *anon_vma = vma->anon_vma; | 
| 450 | 448 | ||
| @@ -468,8 +466,7 @@ void page_add_anon_rmap(struct page *page, | |||
| 468 | void page_add_file_rmap(struct page *page) | 466 | void page_add_file_rmap(struct page *page) | 
| 469 | { | 467 | { | 
| 470 | BUG_ON(PageAnon(page)); | 468 | BUG_ON(PageAnon(page)); | 
| 471 | if (!pfn_valid(page_to_pfn(page)) || PageReserved(page)) | 469 | BUG_ON(!pfn_valid(page_to_pfn(page))); | 
| 472 | return; | ||
| 473 | 470 | ||
| 474 | if (atomic_inc_and_test(&page->_mapcount)) | 471 | if (atomic_inc_and_test(&page->_mapcount)) | 
| 475 | inc_page_state(nr_mapped); | 472 | inc_page_state(nr_mapped); | 
| @@ -483,8 +480,6 @@ void page_add_file_rmap(struct page *page) | |||
| 483 | */ | 480 | */ | 
| 484 | void page_remove_rmap(struct page *page) | 481 | void page_remove_rmap(struct page *page) | 
| 485 | { | 482 | { | 
| 486 | BUG_ON(PageReserved(page)); | ||
| 487 | |||
| 488 | if (atomic_add_negative(-1, &page->_mapcount)) { | 483 | if (atomic_add_negative(-1, &page->_mapcount)) { | 
| 489 | BUG_ON(page_mapcount(page) < 0); | 484 | BUG_ON(page_mapcount(page) < 0); | 
| 490 | /* | 485 | /* | 
| @@ -640,13 +635,13 @@ static void try_to_unmap_cluster(unsigned long cursor, | |||
| 640 | continue; | 635 | continue; | 
| 641 | 636 | ||
| 642 | pfn = pte_pfn(*pte); | 637 | pfn = pte_pfn(*pte); | 
| 643 | if (!pfn_valid(pfn)) | 638 | if (unlikely(!pfn_valid(pfn))) { | 
| 639 | print_bad_pte(vma, *pte, address); | ||
| 644 | continue; | 640 | continue; | 
| 641 | } | ||
| 645 | 642 | ||
| 646 | page = pfn_to_page(pfn); | 643 | page = pfn_to_page(pfn); | 
| 647 | BUG_ON(PageAnon(page)); | 644 | BUG_ON(PageAnon(page)); | 
| 648 | if (PageReserved(page)) | ||
| 649 | continue; | ||
| 650 | 645 | ||
| 651 | if (ptep_clear_flush_young(vma, address, pte)) | 646 | if (ptep_clear_flush_young(vma, address, pte)) | 
| 652 | continue; | 647 | continue; | 
| @@ -808,7 +803,6 @@ int try_to_unmap(struct page *page) | |||
| 808 | { | 803 | { | 
| 809 | int ret; | 804 | int ret; | 
| 810 | 805 | ||
| 811 | BUG_ON(PageReserved(page)); | ||
| 812 | BUG_ON(!PageLocked(page)); | 806 | BUG_ON(!PageLocked(page)); | 
| 813 | 807 | ||
| 814 | if (PageAnon(page)) | 808 | if (PageAnon(page)) | 
diff --git a/mm/shmem.c b/mm/shmem.c index 6796311a23ef..37777f4c11f8 100644 --- a/mm/shmem.c +++ b/mm/shmem.c  | |||
| @@ -1506,8 +1506,10 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ | |||
| 1506 | */ | 1506 | */ | 
| 1507 | if (!offset) | 1507 | if (!offset) | 
| 1508 | mark_page_accessed(page); | 1508 | mark_page_accessed(page); | 
| 1509 | } else | 1509 | } else { | 
| 1510 | page = ZERO_PAGE(0); | 1510 | page = ZERO_PAGE(0); | 
| 1511 | page_cache_get(page); | ||
| 1512 | } | ||
| 1511 | 1513 | ||
| 1512 | /* | 1514 | /* | 
| 1513 | * Ok, we have the page, and it's up-to-date, so | 1515 | * Ok, we have the page, and it's up-to-date, so | 
| @@ -48,7 +48,7 @@ void put_page(struct page *page) | |||
| 48 | } | 48 | } | 
| 49 | return; | 49 | return; | 
| 50 | } | 50 | } | 
| 51 | if (!PageReserved(page) && put_page_testzero(page)) | 51 | if (put_page_testzero(page)) | 
| 52 | __page_cache_release(page); | 52 | __page_cache_release(page); | 
| 53 | } | 53 | } | 
| 54 | EXPORT_SYMBOL(put_page); | 54 | EXPORT_SYMBOL(put_page); | 
| @@ -215,7 +215,7 @@ void release_pages(struct page **pages, int nr, int cold) | |||
| 215 | struct page *page = pages[i]; | 215 | struct page *page = pages[i]; | 
| 216 | struct zone *pagezone; | 216 | struct zone *pagezone; | 
| 217 | 217 | ||
| 218 | if (PageReserved(page) || !put_page_testzero(page)) | 218 | if (!put_page_testzero(page)) | 
| 219 | continue; | 219 | continue; | 
| 220 | 220 | ||
| 221 | pagezone = page_zone(page); | 221 | pagezone = page_zone(page); | 
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 67abebabf83e..e97b2d162cc7 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c  | |||
| @@ -2949,8 +2949,7 @@ static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, uns | |||
| 2949 | return NOPAGE_OOM; | 2949 | return NOPAGE_OOM; | 
| 2950 | runtime = substream->runtime; | 2950 | runtime = substream->runtime; | 
| 2951 | page = virt_to_page(runtime->status); | 2951 | page = virt_to_page(runtime->status); | 
| 2952 | if (!PageReserved(page)) | 2952 | get_page(page); | 
| 2953 | get_page(page); | ||
| 2954 | if (type) | 2953 | if (type) | 
| 2955 | *type = VM_FAULT_MINOR; | 2954 | *type = VM_FAULT_MINOR; | 
| 2956 | return page; | 2955 | return page; | 
| @@ -2992,8 +2991,7 @@ static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, un | |||
| 2992 | return NOPAGE_OOM; | 2991 | return NOPAGE_OOM; | 
| 2993 | runtime = substream->runtime; | 2992 | runtime = substream->runtime; | 
| 2994 | page = virt_to_page(runtime->control); | 2993 | page = virt_to_page(runtime->control); | 
| 2995 | if (!PageReserved(page)) | 2994 | get_page(page); | 
| 2996 | get_page(page); | ||
| 2997 | if (type) | 2995 | if (type) | 
| 2998 | *type = VM_FAULT_MINOR; | 2996 | *type = VM_FAULT_MINOR; | 
| 2999 | return page; | 2997 | return page; | 
| @@ -3066,8 +3064,7 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsign | |||
| 3066 | vaddr = runtime->dma_area + offset; | 3064 | vaddr = runtime->dma_area + offset; | 
| 3067 | page = virt_to_page(vaddr); | 3065 | page = virt_to_page(vaddr); | 
| 3068 | } | 3066 | } | 
| 3069 | if (!PageReserved(page)) | 3067 | get_page(page); | 
| 3070 | get_page(page); | ||
| 3071 | if (type) | 3068 | if (type) | 
| 3072 | *type = VM_FAULT_MINOR; | 3069 | *type = VM_FAULT_MINOR; | 
| 3073 | return page; | 3070 | return page; | 
