提交 4a55c5b4 编写于 作者: Z ZhangPeng 提交者: Ma Wupeng

userswap: move userswap feature code into mm/userswap.c

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I6CAIM

--------------------------------

This patch moves the code related to enable_userswap and CONFIG_USERSWAP
to mm/userswap.c. This allows for better encapsulation and easier
maintenance.
Signed-off-by: NZhangPeng <zhangpeng362@huawei.com>
上级 2ca987f1
......@@ -335,8 +335,7 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx,
* changes under us.
*/
#ifdef CONFIG_USERSWAP
if ((reason & VM_USWAP) && (!pte_present(*pte)))
ret = true;
uswap_must_wait(reason, *pte, &ret);
#endif
if (pte_none(*pte))
ret = true;
......@@ -875,8 +874,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
for (vma = mm->mmap; vma; vma = vma->vm_next) {
userfault_flags = VM_UFFD_MISSING | VM_UFFD_WP;
#ifdef CONFIG_USERSWAP
if (enable_userswap)
userfault_flags |= VM_USWAP;
uswap_release(&userfault_flags);
#endif
cond_resched();
BUG_ON(!!vma->vm_userfaultfd_ctx.ctx ^
......@@ -1297,26 +1295,8 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
goto out;
vm_flags = 0;
#ifdef CONFIG_USERSWAP
/*
* register the whole vma overlapping with the address range to avoid
* splitting the vma.
*/
if (enable_userswap && (uffdio_register.mode & UFFDIO_REGISTER_MODE_USWAP)) {
uffdio_register.mode &= ~UFFDIO_REGISTER_MODE_USWAP;
if (!uffdio_register.mode)
goto out;
vm_flags |= VM_USWAP;
end = uffdio_register.range.start + uffdio_register.range.len - 1;
vma = find_vma(mm, uffdio_register.range.start);
if (!vma)
goto out;
uffdio_register.range.start = vma->vm_start;
vma = find_vma(mm, end);
if (!vma)
goto out;
uffdio_register.range.len = vma->vm_end - uffdio_register.range.start;
}
if (!uswap_register(&uffdio_register, &vm_flags, mm))
goto out;
#endif
if (uffdio_register.mode & ~(UFFDIO_REGISTER_MODE_MISSING|
UFFDIO_REGISTER_MODE_WP))
......@@ -2041,15 +2021,6 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)
return fd;
}
#ifdef CONFIG_USERSWAP
static int __init enable_userswap_setup(char *str)
{
enable_userswap = true;
return 1;
}
__setup("enable_userswap", enable_userswap_setup);
#endif
static int __init userfaultfd_init(void)
{
userfaultfd_ctx_cachep = kmem_cache_create("userfaultfd_ctx_cache",
......
......@@ -28,6 +28,12 @@ int mfill_atomic_pte_nocopy(struct mm_struct *dst_mm,
unsigned long uswap_mremap(unsigned long old_addr, unsigned long old_len,
unsigned long new_addr, unsigned long new_len);
bool uswap_register(struct uffdio_register *uffdio_register,
unsigned long *vm_flags, struct mm_struct *mm);
bool do_uswap_page(swp_entry_t entry, struct vm_fault *vmf,
struct vm_area_struct *vma, vm_fault_t *ret);
static inline bool uswap_check_copy_mode(struct vm_area_struct *vma, __u64 mode)
{
if (!(vma->vm_flags & VM_USWAP) && (mode & UFFDIO_COPY_MODE_DIRECT_MAP))
......@@ -72,6 +78,18 @@ static inline void uswap_get_cpu_id(unsigned long reason, struct uffd_msg *msg)
msg->reserved3 = smp_processor_id();
}
static inline void uswap_release(unsigned long *userfault_flags)
{
if (enable_userswap)
*userfault_flags |= VM_USWAP;
}
static inline void uswap_must_wait(unsigned long reason, pte_t pte, bool *ret)
{
if ((reason & VM_USWAP) && (!pte_present(pte)))
*ret = true;
}
#endif /* CONFIG_USERSWAP */
#endif /* _LINUX_USERSWAP_H */
......@@ -3396,22 +3396,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
entry = pte_to_swp_entry(vmf->orig_pte);
#ifdef CONFIG_USERSWAP
if (swp_type(entry) == SWP_USERSWAP_ENTRY) {
/* print error if we come across a nested fault */
if (!strncmp(current->comm, "uswap", 5)) {
pr_err("USWAP: fault %lx is triggered by %s\n",
vmf->address, current->comm);
return VM_FAULT_SIGBUS;
}
if (!(vma->vm_flags & VM_UFFD_MISSING)) {
pr_err("USWAP: addr %lx flags %lx is not a user swap page",
vmf->address, vma->vm_flags);
goto skip_uswap;
}
ret = handle_userfault(vmf, VM_UFFD_MISSING | VM_USWAP);
if (!do_uswap_page(entry, vmf, vma, &ret))
return ret;
}
skip_uswap:
#endif
if (unlikely(non_swap_entry(entry))) {
if (is_migration_entry(entry)) {
......
......@@ -10,6 +10,7 @@
#include <linux/rmap.h>
#include <linux/mmu_notifier.h>
#include <linux/userswap.h>
#include <linux/userfaultfd_k.h>
#include "internal.h"
......@@ -458,3 +459,67 @@ int mfill_atomic_pte_nocopy(struct mm_struct *mm,
put_page(page);
return ret;
}
/*
* register the whole vma overlapping with the address range to avoid splitting
* the vma.
*/
bool uswap_register(struct uffdio_register *uffdio_register,
unsigned long *vm_flags, struct mm_struct *mm)
{
struct vm_area_struct *vma;
unsigned long end;
if (!enable_userswap)
return true;
if (!(uffdio_register->mode & UFFDIO_REGISTER_MODE_USWAP))
return true;
uffdio_register->mode &= ~UFFDIO_REGISTER_MODE_USWAP;
if (!uffdio_register->mode)
return false;
end = uffdio_register->range.start + uffdio_register->range.len - 1;
vma = find_vma(mm, uffdio_register->range.start);
if (!vma)
return false;
uffdio_register->range.start = vma->vm_start;
vma = find_vma(mm, end);
if (!vma)
return false;
uffdio_register->range.len = vma->vm_end - uffdio_register->range.start;
*vm_flags |= VM_USWAP;
return true;
}
bool do_uswap_page(swp_entry_t entry, struct vm_fault *vmf,
struct vm_area_struct *vma, vm_fault_t *ret)
{
if (swp_type(entry) != SWP_USERSWAP_ENTRY)
return true;
/* print error if we come across a nested fault */
if (!strncmp(current->comm, "uswap", 5)) {
pr_err("USWAP: fault %lx is triggered by %s\n", vmf->address,
current->comm);
*ret = VM_FAULT_SIGBUS;
return false;
}
if (!(vma->vm_flags & VM_UFFD_MISSING)) {
pr_err("USWAP: addr %lx flags %lx is not a user swap page",
vmf->address, vma->vm_flags);
return true;
}
*ret = handle_userfault(vmf, VM_UFFD_MISSING | VM_USWAP);
return false;
}
static int __init enable_userswap_setup(char *str)
{
enable_userswap = true;
return 1;
}
__setup("enable_userswap", enable_userswap_setup);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册