From ef3a1632f95a077928a51b2f9aae7119d1b9e1a0 Mon Sep 17 00:00:00 2001 From: ZhangPeng Date: Thu, 18 May 2023 19:16:16 +0800 Subject: [PATCH] userswap: introduce new flag to determine the first page fault hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6CAIM -------------------------------- Introduce new flag to determine the first page fault. Signed-off-by: ZhangPeng --- fs/userfaultfd.c | 4 ++++ include/linux/userswap.h | 7 +++++++ include/uapi/linux/userfaultfd.h | 1 + mm/memory.c | 14 ++++++++++++++ 4 files changed, 26 insertions(+) diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 4b20f0fd949e..8a916c96d967 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -485,6 +485,10 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason) uwq.wq.private = current; uwq.msg = userfault_msg(vmf->address, vmf->flags, reason, ctx->features); +#ifdef CONFIG_USERSWAP + if (reason & VM_USWAP && pte_none(vmf->orig_pte)) + uwq.msg.arg.pagefault.flags |= UFFD_PAGEFAULT_FLAG_FPF; +#endif uwq.ctx = ctx; uwq.waken = false; diff --git a/include/linux/userswap.h b/include/linux/userswap.h index 6c96cef2ec9b..29a3bead95d0 100644 --- a/include/linux/userswap.h +++ b/include/linux/userswap.h @@ -59,6 +59,13 @@ static inline bool uswap_vm_flag_bug_on(unsigned long reason) return !(reason & VM_UFFD_MISSING) ^ !!(reason & VM_UFFD_WP); } +static inline bool uswap_missing(struct vm_area_struct *vma) +{ + if (vma->vm_flags & VM_USWAP && vma->vm_flags & VM_UFFD_MISSING) + return true; + return false; +} + #endif /* CONFIG_USERSWAP */ #endif /* _LINUX_USERSWAP_H */ diff --git a/include/uapi/linux/userfaultfd.h b/include/uapi/linux/userfaultfd.h index 4de57e12cdff..b8689050455d 100644 --- a/include/uapi/linux/userfaultfd.h +++ b/include/uapi/linux/userfaultfd.h @@ -127,6 +127,7 @@ struct uffd_msg { /* flags for UFFD_EVENT_PAGEFAULT */ #define UFFD_PAGEFAULT_FLAG_WRITE (1<<0) /* If this was a write fault */ #define UFFD_PAGEFAULT_FLAG_WP (1<<1) /* If reason is VM_UFFD_WP */ +#define UFFD_PAGEFAULT_FLAG_FPF (1<<10) /* If this was the first page fault */ struct uffdio_api { /* userland asks for an API number and the features to enable */ diff --git a/mm/memory.c b/mm/memory.c index 8f7d4531c763..ed017586db1f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -73,6 +73,7 @@ #include #include #include +#include #include @@ -3689,6 +3690,12 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf) if (ret) goto unlock; /* Deliver the page fault to userland, check inside PT lock */ +#ifdef CONFIG_USERSWAP + if (uswap_missing(vma)) { + pte_unmap_unlock(vmf->pte, vmf->ptl); + return handle_userfault(vmf, VM_UFFD_MISSING|VM_USWAP); + } +#endif if (userfaultfd_missing(vma)) { pte_unmap_unlock(vmf->pte, vmf->ptl); return handle_userfault(vmf, VM_UFFD_MISSING); @@ -3731,6 +3738,13 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf) goto release; /* Deliver the page fault to userland, check inside PT lock */ +#ifdef CONFIG_USERSWAP + if (uswap_missing(vma)) { + pte_unmap_unlock(vmf->pte, vmf->ptl); + put_page(page); + return handle_userfault(vmf, VM_UFFD_MISSING | VM_USWAP); + } +#endif if (userfaultfd_missing(vma)) { pte_unmap_unlock(vmf->pte, vmf->ptl); put_page(page); -- GitLab