mm: special mapping nopage

Convert special mapping install from nopage to fault.

Because the "vm_file" is NULL for the special mapping, the generic VM
code has messed up "vm_pgoff" thinking that it's an anonymous mapping
and the offset does't matter. For that reason, we need to undo the
vm_pgoff offset that got added into vmf->pgoff.

[ We _really_ should clean that up - either by making this whole special
mapping code just use a real file entry rather than that ugly array of
"struct page" pointers, or by just making the VM code realize that
even if vm_file is NULL it may not be a regular anonymous mmap.
- Linus ]

Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Nick Piggin and committed by Linus Torvalds b1d0e4f5 6a306e8b

+16 -9
+16 -9
mm/mmap.c
··· 2165 } 2166 2167 2168 - static struct page *special_mapping_nopage(struct vm_area_struct *vma, 2169 - unsigned long address, int *type) 2170 { 2171 struct page **pages; 2172 2173 - BUG_ON(address < vma->vm_start || address >= vma->vm_end); 2174 2175 - address -= vma->vm_start; 2176 - for (pages = vma->vm_private_data; address > 0 && *pages; ++pages) 2177 - address -= PAGE_SIZE; 2178 2179 if (*pages) { 2180 struct page *page = *pages; 2181 get_page(page); 2182 - return page; 2183 } 2184 2185 - return NOPAGE_SIGBUS; 2186 } 2187 2188 /* ··· 2201 2202 static struct vm_operations_struct special_mapping_vmops = { 2203 .close = special_mapping_close, 2204 - .nopage = special_mapping_nopage, 2205 }; 2206 2207 /*
··· 2165 } 2166 2167 2168 + static int special_mapping_fault(struct vm_area_struct *vma, 2169 + struct vm_fault *vmf) 2170 { 2171 + pgoff_t pgoff; 2172 struct page **pages; 2173 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; 2181 2182 + for (pages = vma->vm_private_data; pgoff && *pages; ++pages) 2183 + pgoff--; 2184 2185 if (*pages) { 2186 struct page *page = *pages; 2187 get_page(page); 2188 + vmf->page = page; 2189 + return 0; 2190 } 2191 2192 + return VM_FAULT_SIGBUS; 2193 } 2194 2195 /* ··· 2194 2195 static struct vm_operations_struct special_mapping_vmops = { 2196 .close = special_mapping_close, 2197 + .fault = special_mapping_fault, 2198 }; 2199 2200 /*