Skip to content

Commit 7c9580f

Browse files
Kiryl Shutsemauakpm00
authored andcommitted
mm/filemap: fix logic around SIGBUS in filemap_map_pages()
Chris noticed that filemap_map_pages() calculates can_map_large only once for the first page in the fault around range. The value is not valid for the following pages in the range and must be recalculated. Instead of recalculating can_map_large on each iteration, pass down file_end to filemap_map_folio_range() and let it make the decision on what can be mapped. Link: https://lkml.kernel.org/r/20251120161411.859078-1-kirill@shutemov.name Fixes: 74207de ("mm/memory: do not populate page table entries beyond i_size")h Signed-off-by: Kiryl Shutsemau <kas@kernel.org> Reported-by: Chris Mason <clm@meta.com> Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Chris Mason <clm@meta.com> Cc: Christian Brauner <brauner@kernel.org> Cc: "Darrick J. Wong" <djwong@kernel.org> Cc: Dave Chinner <david@fromorbit.com> Cc: David Hildenbrand <david@redhat.com> Cc: Hugh Dickins <hughd@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Rik van Riel <riel@surriel.com> Cc: Shakeel Butt <shakeel.butt@linux.dev> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent cff47b9 commit 7c9580f

1 file changed

Lines changed: 14 additions & 13 deletions

File tree

mm/filemap.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,8 +3682,9 @@ static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf,
36823682
struct folio *folio, unsigned long start,
36833683
unsigned long addr, unsigned int nr_pages,
36843684
unsigned long *rss, unsigned short *mmap_miss,
3685-
bool can_map_large)
3685+
pgoff_t file_end)
36863686
{
3687+
struct address_space *mapping = folio->mapping;
36873688
unsigned int ref_from_caller = 1;
36883689
vm_fault_t ret = 0;
36893690
struct page *page = folio_page(folio, start);
@@ -3692,12 +3693,16 @@ static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf,
36923693
unsigned long addr0;
36933694

36943695
/*
3695-
* Map the large folio fully where possible.
3696+
* Map the large folio fully where possible:
36963697
*
3697-
* The folio must not cross VMA or page table boundary.
3698+
* - The folio is fully within size of the file or belong
3699+
* to shmem/tmpfs;
3700+
* - The folio doesn't cross VMA boundary;
3701+
* - The folio doesn't cross page table boundary;
36983702
*/
36993703
addr0 = addr - start * PAGE_SIZE;
3700-
if (can_map_large && folio_within_vma(folio, vmf->vma) &&
3704+
if ((file_end >= folio_next_index(folio) || shmem_mapping(mapping)) &&
3705+
folio_within_vma(folio, vmf->vma) &&
37013706
(addr0 & PMD_MASK) == ((addr0 + folio_size(folio) - 1) & PMD_MASK)) {
37023707
vmf->pte -= start;
37033708
page -= start;
@@ -3812,7 +3817,6 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
38123817
unsigned long rss = 0;
38133818
unsigned int nr_pages = 0, folio_type;
38143819
unsigned short mmap_miss = 0, mmap_miss_saved;
3815-
bool can_map_large;
38163820

38173821
rcu_read_lock();
38183822
folio = next_uptodate_folio(&xas, mapping, end_pgoff);
@@ -3823,16 +3827,14 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
38233827
end_pgoff = min(end_pgoff, file_end);
38243828

38253829
/*
3826-
* Do not allow to map with PTEs beyond i_size and with PMD
3827-
* across i_size to preserve SIGBUS semantics.
3830+
* Do not allow to map with PMD across i_size to preserve
3831+
* SIGBUS semantics.
38283832
*
38293833
* Make an exception for shmem/tmpfs that for long time
38303834
* intentionally mapped with PMDs across i_size.
38313835
*/
3832-
can_map_large = shmem_mapping(mapping) ||
3833-
file_end >= folio_next_index(folio);
3834-
3835-
if (can_map_large && filemap_map_pmd(vmf, folio, start_pgoff)) {
3836+
if ((file_end >= folio_next_index(folio) || shmem_mapping(mapping)) &&
3837+
filemap_map_pmd(vmf, folio, start_pgoff)) {
38363838
ret = VM_FAULT_NOPAGE;
38373839
goto out;
38383840
}
@@ -3861,8 +3863,7 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
38613863
else
38623864
ret |= filemap_map_folio_range(vmf, folio,
38633865
xas.xa_index - folio->index, addr,
3864-
nr_pages, &rss, &mmap_miss,
3865-
can_map_large);
3866+
nr_pages, &rss, &mmap_miss, file_end);
38663867

38673868
folio_unlock(folio);
38683869
} while ((folio = next_uptodate_folio(&xas, mapping, end_pgoff)) != NULL);

0 commit comments

Comments
 (0)