@@ -2145,19 +2145,39 @@ static int validate_page_before_insert(struct vm_area_struct *vma,
21452145}
21462146
21472147static int insert_page_into_pte_locked (struct vm_area_struct * vma , pte_t * pte ,
2148- unsigned long addr , struct page * page , pgprot_t prot )
2148+ unsigned long addr , struct page * page ,
2149+ pgprot_t prot , bool mkwrite )
21492150{
21502151 struct folio * folio = page_folio (page );
2151- pte_t pteval ;
2152+ pte_t pteval = ptep_get (pte );
2153+
2154+ if (!pte_none (pteval )) {
2155+ if (!mkwrite )
2156+ return - EBUSY ;
2157+
2158+ /* see insert_pfn(). */
2159+ if (pte_pfn (pteval ) != page_to_pfn (page )) {
2160+ WARN_ON_ONCE (!is_zero_pfn (pte_pfn (pteval )));
2161+ return - EFAULT ;
2162+ }
2163+ pteval = maybe_mkwrite (pteval , vma );
2164+ pteval = pte_mkyoung (pteval );
2165+ if (ptep_set_access_flags (vma , addr , pte , pteval , 1 ))
2166+ update_mmu_cache (vma , addr , pte );
2167+ return 0 ;
2168+ }
21522169
2153- if (!pte_none (ptep_get (pte )))
2154- return - EBUSY ;
21552170 /* Ok, finally just insert the thing.. */
21562171 pteval = mk_pte (page , prot );
21572172 if (unlikely (is_zero_folio (folio ))) {
21582173 pteval = pte_mkspecial (pteval );
21592174 } else {
21602175 folio_get (folio );
2176+ pteval = mk_pte (page , prot );
2177+ if (mkwrite ) {
2178+ pteval = pte_mkyoung (pteval );
2179+ pteval = maybe_mkwrite (pte_mkdirty (pteval ), vma );
2180+ }
21612181 inc_mm_counter (vma -> vm_mm , mm_counter_file (folio ));
21622182 folio_add_file_rmap_pte (folio , page , vma );
21632183 }
@@ -2166,7 +2186,7 @@ static int insert_page_into_pte_locked(struct vm_area_struct *vma, pte_t *pte,
21662186}
21672187
21682188static int insert_page (struct vm_area_struct * vma , unsigned long addr ,
2169- struct page * page , pgprot_t prot )
2189+ struct page * page , pgprot_t prot , bool mkwrite )
21702190{
21712191 int retval ;
21722192 pte_t * pte ;
@@ -2179,7 +2199,8 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
21792199 pte = get_locked_pte (vma -> vm_mm , addr , & ptl );
21802200 if (!pte )
21812201 goto out ;
2182- retval = insert_page_into_pte_locked (vma , pte , addr , page , prot );
2202+ retval = insert_page_into_pte_locked (vma , pte , addr , page , prot ,
2203+ mkwrite );
21832204 pte_unmap_unlock (pte , ptl );
21842205out :
21852206 return retval ;
@@ -2193,7 +2214,7 @@ static int insert_page_in_batch_locked(struct vm_area_struct *vma, pte_t *pte,
21932214 err = validate_page_before_insert (vma , page );
21942215 if (err )
21952216 return err ;
2196- return insert_page_into_pte_locked (vma , pte , addr , page , prot );
2217+ return insert_page_into_pte_locked (vma , pte , addr , page , prot , false );
21972218}
21982219
21992220/* insert_pages() amortizes the cost of spinlock operations
@@ -2329,7 +2350,7 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
23292350 BUG_ON (vma -> vm_flags & VM_PFNMAP );
23302351 vm_flags_set (vma , VM_MIXEDMAP );
23312352 }
2332- return insert_page (vma , addr , page , vma -> vm_page_prot );
2353+ return insert_page (vma , addr , page , vma -> vm_page_prot , false );
23332354}
23342355EXPORT_SYMBOL (vm_insert_page );
23352356
@@ -2609,7 +2630,7 @@ static vm_fault_t __vm_insert_mixed(struct vm_area_struct *vma,
26092630 * result in pfn_t_has_page() == false.
26102631 */
26112632 page = pfn_to_page (pfn_t_to_pfn (pfn ));
2612- err = insert_page (vma , addr , page , pgprot );
2633+ err = insert_page (vma , addr , page , pgprot , mkwrite );
26132634 } else {
26142635 return insert_pfn (vma , addr , pfn , pgprot , mkwrite );
26152636 }
0 commit comments