diff options
Diffstat (limited to 'mm/mmap.c')
| -rw-r--r-- | mm/mmap.c | 25 |
1 files changed, 16 insertions, 9 deletions
| @@ -2165,24 +2165,31 @@ int may_expand_vm(struct mm_struct *mm, unsigned long npages) | |||
| 2165 | } | 2165 | } |
| 2166 | 2166 | ||
| 2167 | 2167 | ||
| 2168 | static struct page *special_mapping_nopage(struct vm_area_struct *vma, | 2168 | static int special_mapping_fault(struct vm_area_struct *vma, |
| 2169 | unsigned long address, int *type) | 2169 | struct vm_fault *vmf) |
| 2170 | { | 2170 | { |
| 2171 | pgoff_t pgoff; | ||
| 2171 | struct page **pages; | 2172 | struct page **pages; |
| 2172 | 2173 | ||
| 2173 | BUG_ON(address < vma->vm_start || address >= vma->vm_end); | 2174 | /* |
| 2175 | * special mappings have no vm_file, and in that case, the mm | ||
| 2176 | * uses vm_pgoff internally. So we have to subtract it from here. | ||
| 2177 | * We are allowed to do this because we are the mm; do not copy | ||
| 2178 | * this code into drivers! | ||
| 2179 | */ | ||
| 2180 | pgoff = vmf->pgoff - vma->vm_pgoff; | ||
| 2174 | 2181 | ||
| 2175 | address -= vma->vm_start; | 2182 | for (pages = vma->vm_private_data; pgoff && *pages; ++pages) |
| 2176 | for (pages = vma->vm_private_data; address > 0 && *pages; ++pages) | 2183 | pgoff--; |
| 2177 | address -= PAGE_SIZE; | ||
| 2178 | 2184 | ||
| 2179 | if (*pages) { | 2185 | if (*pages) { |
| 2180 | struct page *page = *pages; | 2186 | struct page *page = *pages; |
| 2181 | get_page(page); | 2187 | get_page(page); |
| 2182 | return page; | 2188 | vmf->page = page; |
| 2189 | return 0; | ||
| 2183 | } | 2190 | } |
| 2184 | 2191 | ||
| 2185 | return NOPAGE_SIGBUS; | 2192 | return VM_FAULT_SIGBUS; |
| 2186 | } | 2193 | } |
| 2187 | 2194 | ||
| 2188 | /* | 2195 | /* |
| @@ -2194,7 +2201,7 @@ static void special_mapping_close(struct vm_area_struct *vma) | |||
| 2194 | 2201 | ||
| 2195 | static struct vm_operations_struct special_mapping_vmops = { | 2202 | static struct vm_operations_struct special_mapping_vmops = { |
| 2196 | .close = special_mapping_close, | 2203 | .close = special_mapping_close, |
| 2197 | .nopage = special_mapping_nopage, | 2204 | .fault = special_mapping_fault, |
| 2198 | }; | 2205 | }; |
| 2199 | 2206 | ||
| 2200 | /* | 2207 | /* |
