]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm/memory: enhance insert_page_into_pte_locked() to create writable mappings
authorAlistair Popple <apopple@nvidia.com>
Tue, 18 Feb 2025 03:55:28 +0000 (14:55 +1100)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 28 Feb 2025 01:00:14 +0000 (17:00 -0800)
In preparation for using insert_page() for DAX, enhance
insert_page_into_pte_locked() to handle establishing writable mappings.
Recall that DAX returns VM_FAULT_NOPAGE after installing a PTE which
bypasses the typical set_pte_range() in finish_fault.

Link: https://lkml.kernel.org/r/ee748e555fb0dc190994a0fd59a57b9c43a17dc9.1739850794.git-series.apopple@nvidia.com
Signed-off-by: Alistair Popple <apopple@nvidia.com>
Suggested-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: David Hildenbrand <david@redhat.com>
Tested-by: Alison Schofield <alison.schofield@intel.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Asahi Lina <lina@asahilina.net>
Cc: Balbir Singh <balbirs@nvidia.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Chunyan Zhang <zhang.lyra@gmail.com>
Cc: "Darrick J. Wong" <djwong@kernel.org>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Logan Gunthorpe <logang@deltatee.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Ted Ts'o <tytso@mit.edu>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: WANG Xuerui <kernel@xen0n.name>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/memory.c

index f0fa2a6340696de1afc673f55f33444ce08bae4f..188dff7990704daf8e491b7153c82530b07bf031 100644 (file)
@@ -2126,19 +2126,39 @@ static int validate_page_before_insert(struct vm_area_struct *vma,
 }
 
 static int insert_page_into_pte_locked(struct vm_area_struct *vma, pte_t *pte,
-                       unsigned long addr, struct page *page, pgprot_t prot)
+                               unsigned long addr, struct page *page,
+                               pgprot_t prot, bool mkwrite)
 {
        struct folio *folio = page_folio(page);
-       pte_t pteval;
+       pte_t pteval = ptep_get(pte);
+
+       if (!pte_none(pteval)) {
+               if (!mkwrite)
+                       return -EBUSY;
+
+               /* see insert_pfn(). */
+               if (pte_pfn(pteval) != page_to_pfn(page)) {
+                       WARN_ON_ONCE(!is_zero_pfn(pte_pfn(pteval)));
+                       return -EFAULT;
+               }
+               pteval = maybe_mkwrite(pteval, vma);
+               pteval = pte_mkyoung(pteval);
+               if (ptep_set_access_flags(vma, addr, pte, pteval, 1))
+                       update_mmu_cache(vma, addr, pte);
+               return 0;
+       }
 
-       if (!pte_none(ptep_get(pte)))
-               return -EBUSY;
        /* Ok, finally just insert the thing.. */
        pteval = mk_pte(page, prot);
        if (unlikely(is_zero_folio(folio))) {
                pteval = pte_mkspecial(pteval);
        } else {
                folio_get(folio);
+               pteval = mk_pte(page, prot);
+               if (mkwrite) {
+                       pteval = pte_mkyoung(pteval);
+                       pteval = maybe_mkwrite(pte_mkdirty(pteval), vma);
+               }
                inc_mm_counter(vma->vm_mm, mm_counter_file(folio));
                folio_add_file_rmap_pte(folio, page, vma);
        }
@@ -2147,7 +2167,7 @@ static int insert_page_into_pte_locked(struct vm_area_struct *vma, pte_t *pte,
 }
 
 static int insert_page(struct vm_area_struct *vma, unsigned long addr,
-                       struct page *page, pgprot_t prot)
+                       struct page *page, pgprot_t prot, bool mkwrite)
 {
        int retval;
        pte_t *pte;
@@ -2160,7 +2180,8 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
        pte = get_locked_pte(vma->vm_mm, addr, &ptl);
        if (!pte)
                goto out;
-       retval = insert_page_into_pte_locked(vma, pte, addr, page, prot);
+       retval = insert_page_into_pte_locked(vma, pte, addr, page, prot,
+                                       mkwrite);
        pte_unmap_unlock(pte, ptl);
 out:
        return retval;
@@ -2174,7 +2195,7 @@ static int insert_page_in_batch_locked(struct vm_area_struct *vma, pte_t *pte,
        err = validate_page_before_insert(vma, page);
        if (err)
                return err;
-       return insert_page_into_pte_locked(vma, pte, addr, page, prot);
+       return insert_page_into_pte_locked(vma, pte, addr, page, prot, false);
 }
 
 /* insert_pages() amortizes the cost of spinlock operations
@@ -2310,7 +2331,7 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
                BUG_ON(vma->vm_flags & VM_PFNMAP);
                vm_flags_set(vma, VM_MIXEDMAP);
        }
-       return insert_page(vma, addr, page, vma->vm_page_prot);
+       return insert_page(vma, addr, page, vma->vm_page_prot, false);
 }
 EXPORT_SYMBOL(vm_insert_page);
 
@@ -2590,7 +2611,7 @@ static vm_fault_t __vm_insert_mixed(struct vm_area_struct *vma,
                 * result in pfn_t_has_page() == false.
                 */
                page = pfn_to_page(pfn_t_to_pfn(pfn));
-               err = insert_page(vma, addr, page, pgprot);
+               err = insert_page(vma, addr, page, pgprot, mkwrite);
        } else {
                return insert_pfn(vma, addr, pfn, pgprot, mkwrite);
        }