diff options
Diffstat (limited to 'mm/filemap_xip.c')
| -rw-r--r-- | mm/filemap_xip.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index 8c199f537732..9cf687e4a29a 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c | |||
| @@ -174,6 +174,8 @@ __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 | spinlock_t *ptl; | ||
| 178 | struct page *page; | ||
| 177 | 179 | ||
| 178 | spin_lock(&mapping->i_mmap_lock); | 180 | spin_lock(&mapping->i_mmap_lock); |
| 179 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 181 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { |
| @@ -181,19 +183,17 @@ __xip_unmap (struct address_space * mapping, | |||
| 181 | address = vma->vm_start + | 183 | address = vma->vm_start + |
| 182 | ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); | 184 | ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); |
| 183 | BUG_ON(address < vma->vm_start || address >= vma->vm_end); | 185 | BUG_ON(address < vma->vm_start || address >= vma->vm_end); |
| 184 | /* | 186 | page = ZERO_PAGE(address); |
| 185 | * We need the page_table_lock to protect us from page faults, | 187 | pte = page_check_address(page, mm, address, &ptl); |
| 186 | * munmap, fork, etc... | 188 | if (pte) { |
| 187 | */ | ||
| 188 | pte = page_check_address(ZERO_PAGE(address), mm, | ||
| 189 | address); | ||
| 190 | if (!IS_ERR(pte)) { | ||
| 191 | /* Nuke the page table entry. */ | 189 | /* Nuke the page table entry. */ |
| 192 | flush_cache_page(vma, address, pte_pfn(*pte)); | 190 | flush_cache_page(vma, address, pte_pfn(*pte)); |
| 193 | pteval = ptep_clear_flush(vma, address, pte); | 191 | pteval = ptep_clear_flush(vma, address, pte); |
| 192 | page_remove_rmap(page); | ||
| 193 | dec_mm_counter(mm, file_rss); | ||
| 194 | BUG_ON(pte_dirty(pteval)); | 194 | BUG_ON(pte_dirty(pteval)); |
| 195 | pte_unmap(pte); | 195 | pte_unmap_unlock(pte, ptl); |
| 196 | spin_unlock(&mm->page_table_lock); | 196 | page_cache_release(page); |
| 197 | } | 197 | } |
| 198 | } | 198 | } |
| 199 | spin_unlock(&mapping->i_mmap_lock); | 199 | spin_unlock(&mapping->i_mmap_lock); |
| @@ -228,7 +228,7 @@ xip_file_nopage(struct vm_area_struct * area, | |||
| 228 | 228 | ||
| 229 | page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0); | 229 | page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0); |
| 230 | if (!IS_ERR(page)) { | 230 | if (!IS_ERR(page)) { |
| 231 | return page; | 231 | goto out; |
| 232 | } | 232 | } |
| 233 | if (PTR_ERR(page) != -ENODATA) | 233 | if (PTR_ERR(page) != -ENODATA) |
| 234 | return NULL; | 234 | return NULL; |
| @@ -249,6 +249,8 @@ xip_file_nopage(struct vm_area_struct * area, | |||
| 249 | page = ZERO_PAGE(address); | 249 | page = ZERO_PAGE(address); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | out: | ||
| 253 | page_cache_get(page); | ||
| 252 | return page; | 254 | return page; |
| 253 | } | 255 | } |
| 254 | 256 | ||
