@@ -45,6 +45,22 @@ struct vm_area_struct *find_dst_vma(struct mm_struct *dst_mm,
4545 return dst_vma ;
4646}
4747
48+ /* Check if dst_addr is outside of file's size. Must be called with ptl held. */
49+ static bool mfill_file_over_size (struct vm_area_struct * dst_vma ,
50+ unsigned long dst_addr )
51+ {
52+ struct inode * inode ;
53+ pgoff_t offset , max_off ;
54+
55+ if (!dst_vma -> vm_file )
56+ return false;
57+
58+ inode = dst_vma -> vm_file -> f_inode ;
59+ offset = linear_page_index (dst_vma , dst_addr );
60+ max_off = DIV_ROUND_UP (i_size_read (inode ), PAGE_SIZE );
61+ return offset >= max_off ;
62+ }
63+
4864/*
4965 * Install PTEs, to map dst_addr (within dst_vma) to page.
5066 *
@@ -64,8 +80,6 @@ int mfill_atomic_install_pte(pmd_t *dst_pmd,
6480 bool page_in_cache = page_mapping (page );
6581 spinlock_t * ptl ;
6682 struct folio * folio ;
67- struct inode * inode ;
68- pgoff_t offset , max_off ;
6983
7084 _dst_pte = mk_pte (page , dst_vma -> vm_page_prot );
7185 _dst_pte = pte_mkdirty (_dst_pte );
@@ -81,14 +95,9 @@ int mfill_atomic_install_pte(pmd_t *dst_pmd,
8195 if (!dst_pte )
8296 goto out ;
8397
84- if (vma_is_shmem (dst_vma )) {
85- /* serialize against truncate with the page table lock */
86- inode = dst_vma -> vm_file -> f_inode ;
87- offset = linear_page_index (dst_vma , dst_addr );
88- max_off = DIV_ROUND_UP (i_size_read (inode ), PAGE_SIZE );
98+ if (mfill_file_over_size (dst_vma , dst_addr )) {
8999 ret = - EFAULT ;
90- if (unlikely (offset >= max_off ))
91- goto out_unlock ;
100+ goto out_unlock ;
92101 }
93102
94103 ret = - EEXIST ;
@@ -211,23 +220,16 @@ static int mfill_atomic_pte_zeropage(pmd_t *dst_pmd,
211220 pte_t _dst_pte , * dst_pte ;
212221 spinlock_t * ptl ;
213222 int ret ;
214- pgoff_t offset , max_off ;
215- struct inode * inode ;
216223
217224 _dst_pte = pte_mkspecial (pfn_pte (my_zero_pfn (dst_addr ),
218225 dst_vma -> vm_page_prot ));
219226 ret = - EAGAIN ;
220227 dst_pte = pte_offset_map_lock (dst_vma -> vm_mm , dst_pmd , dst_addr , & ptl );
221228 if (!dst_pte )
222229 goto out ;
223- if (dst_vma -> vm_file ) {
224- /* the shmem MAP_PRIVATE case requires checking the i_size */
225- inode = dst_vma -> vm_file -> f_inode ;
226- offset = linear_page_index (dst_vma , dst_addr );
227- max_off = DIV_ROUND_UP (i_size_read (inode ), PAGE_SIZE );
230+ if (mfill_file_over_size (dst_vma , dst_addr )) {
228231 ret = - EFAULT ;
229- if (unlikely (offset >= max_off ))
230- goto out_unlock ;
232+ goto out_unlock ;
231233 }
232234 ret = - EEXIST ;
233235 if (!pte_none (ptep_get (dst_pte )))
0 commit comments