]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - mm/gup.c
Merge tag 'imx-drivers-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo...
[mirror_ubuntu-jammy-kernel.git] / mm / gup.c
index 012060efddf18f8f75b8b56ad0447df9ce55d0c7..23a9f9c9d377543f9ad28d8e935a896ecbb95caa 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -384,7 +384,7 @@ retry_locked:
                spin_unlock(ptl);
                return follow_page_pte(vma, address, pmd, flags, &ctx->pgmap);
        }
-       if (flags & FOLL_SPLIT) {
+       if (flags & (FOLL_SPLIT | FOLL_SPLIT_PMD)) {
                int ret;
                page = pmd_page(*pmd);
                if (is_huge_zero_page(page)) {
@@ -393,7 +393,7 @@ retry_locked:
                        split_huge_pmd(vma, pmd, address);
                        if (pmd_trans_unstable(pmd))
                                ret = -EBUSY;
-               } else {
+               } else if (flags & FOLL_SPLIT) {
                        if (unlikely(!try_get_page(page))) {
                                spin_unlock(ptl);
                                return ERR_PTR(-ENOMEM);
@@ -405,6 +405,10 @@ retry_locked:
                        put_page(page);
                        if (pmd_none(*pmd))
                                return no_page_table(vma, flags);
+               } else {  /* flags & FOLL_SPLIT_PMD */
+                       spin_unlock(ptl);
+                       split_huge_pmd(vma, pmd, address);
+                       ret = pte_alloc(mm, pmd) ? -ENOMEM : 0;
                }
 
                return ret ? ERR_PTR(ret) :
@@ -784,6 +788,8 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        if (!nr_pages)
                return 0;
 
+       start = untagged_addr(start);
+
        VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));
 
        /*
@@ -946,6 +952,8 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
        struct vm_area_struct *vma;
        vm_fault_t ret, major = 0;
 
+       address = untagged_addr(address);
+
        if (unlocked)
                fault_flags |= FAULT_FLAG_ALLOW_RETRY;