169 lines
3.9 KiB
C
169 lines
3.9 KiB
C
|
#ifndef _LINUX_ASYNC_FORK_H
|
||
|
#define _LINUX_ASYNC_FORK_H
|
||
|
|
||
|
#ifdef CONFIG_ASYNC_FORK
|
||
|
|
||
|
#define ASYNC_FORK_CANDIDATE 0
|
||
|
#define ASYNC_FORK_PENDING 1
|
||
|
#define ASYNC_FORK_FALLBACK 2
|
||
|
|
||
|
DECLARE_STATIC_KEY_FALSE(async_fork_enabled_key);
|
||
|
DECLARE_STATIC_KEY_FALSE(async_fork_staging_key);
|
||
|
|
||
|
void async_fork_mm_bind(struct mm_struct *oldmm, struct mm_struct *mm,
|
||
|
int err);
|
||
|
void async_fork_rest(struct mm_struct *mm);
|
||
|
void async_fork_fast_done(struct mm_struct *mm, int err);
|
||
|
int async_fork_prepare(struct mm_struct *oldmm, struct mm_struct *mm);
|
||
|
int __async_fork_fixup_pmd(struct vm_area_struct *mpnt, pmd_t *pmd,
|
||
|
unsigned long addr);
|
||
|
void __async_fork_fixup_vma(struct vm_area_struct *mpnt);
|
||
|
void __async_fork_madvise_vma(struct vm_area_struct *mpnt,
|
||
|
unsigned long start,
|
||
|
unsigned long end);
|
||
|
int __async_fork_fast(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
||
|
struct vm_area_struct *dst_vma,
|
||
|
struct vm_area_struct *src_vma);
|
||
|
void async_fork_fixup_vmas(struct mm_struct *mm);
|
||
|
|
||
|
static inline bool async_fork_enabled(void)
|
||
|
{
|
||
|
return static_branch_unlikely(&async_fork_enabled_key);
|
||
|
}
|
||
|
|
||
|
static inline bool async_fork_staging(void)
|
||
|
{
|
||
|
return static_branch_unlikely(&async_fork_staging_key);
|
||
|
}
|
||
|
|
||
|
static inline int
|
||
|
async_fork_fast(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
||
|
struct vm_area_struct *dst_vma,
|
||
|
struct vm_area_struct *src_vma)
|
||
|
{
|
||
|
return __copy_page_range(dst_mm, src_mm, dst_vma, src_vma,
|
||
|
__async_fork_fast);
|
||
|
}
|
||
|
|
||
|
static inline bool is_pmd_async_fork(pmd_t pmd)
|
||
|
{
|
||
|
if (is_swap_pmd(pmd) || pmd_trans_huge(pmd) || pmd_devmap(pmd))
|
||
|
return false;
|
||
|
|
||
|
return !pmd_none(pmd) && !pmd_write(pmd);
|
||
|
}
|
||
|
|
||
|
static inline bool is_async_fork_pending(struct mm_struct *mm)
|
||
|
{
|
||
|
return mm && test_bit(ASYNC_FORK_PENDING, &mm->async_fork_flags);
|
||
|
}
|
||
|
|
||
|
static inline bool is_async_fork_fallback(struct mm_struct *mm)
|
||
|
{
|
||
|
return mm && test_bit(ASYNC_FORK_FALLBACK, &mm->async_fork_flags);
|
||
|
}
|
||
|
|
||
|
static inline bool is_vma_async_fork(struct vm_area_struct *vma)
|
||
|
{
|
||
|
return !!vma->async_fork_vma;
|
||
|
}
|
||
|
|
||
|
static inline void async_fork_set_flags(struct mm_struct *mm, int flags)
|
||
|
{
|
||
|
set_bit(flags, &mm->async_fork_flags);
|
||
|
}
|
||
|
|
||
|
static inline void
|
||
|
async_fork_fixup_pmd(struct vm_area_struct *mpnt, pmd_t *pmd,
|
||
|
unsigned long addr)
|
||
|
{
|
||
|
if (async_fork_staging() && is_vma_async_fork(mpnt) &&
|
||
|
is_pmd_async_fork(*pmd))
|
||
|
__async_fork_fixup_pmd(mpnt, pmd, addr);
|
||
|
}
|
||
|
|
||
|
static inline void async_fork_fixup_vma(struct vm_area_struct *mpnt)
|
||
|
{
|
||
|
if (async_fork_staging() && is_vma_async_fork(mpnt))
|
||
|
__async_fork_fixup_vma(mpnt);
|
||
|
}
|
||
|
|
||
|
static inline void
|
||
|
async_fork_madvise_vma(struct vm_area_struct *mpnt, unsigned long start,
|
||
|
unsigned long end)
|
||
|
{
|
||
|
if (async_fork_staging() && is_vma_async_fork(mpnt))
|
||
|
__async_fork_madvise_vma(mpnt, start, end);
|
||
|
}
|
||
|
|
||
|
static inline struct mutex
|
||
|
*async_fork_vma_lock(struct vm_area_struct *vma)
|
||
|
{
|
||
|
return (void *)&vma->async_fork_lock;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
static inline bool async_fork_enabled(void)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static inline bool async_fork_staging(void)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static inline int
|
||
|
async_fork_fast(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
||
|
struct vm_area_struct *dst_vma,
|
||
|
struct vm_area_struct *src_vma)
|
||
|
{
|
||
|
return -EOPNOTSUPP;
|
||
|
}
|
||
|
|
||
|
static inline void
|
||
|
async_fork_mm_bind(struct mm_struct *oldmm, struct mm_struct *mm, int err)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static inline void async_fork_rest(struct mm_struct *mm)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static inline void async_fork_fast_done(struct mm_struct *mm, int err)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static inline bool is_pmd_async_fork(pmd_t pmd)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static inline void
|
||
|
async_fork_fixup_pmd(struct vm_area_struct *mpnt, pmd_t *pmd,
|
||
|
unsigned long addr)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static inline void async_fork_fixup_vma(struct vm_area_struct *mpnt)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static inline int
|
||
|
async_fork_prepare(struct mm_struct *oldmm, struct mm_struct *mm)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static inline void
|
||
|
async_fork_madvise_vma(struct vm_area_struct *mpnt, unsigned long start,
|
||
|
unsigned long end)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static inline void async_fork_fixup_vmas(struct mm_struct *mm)
|
||
|
{
|
||
|
}
|
||
|
#endif /* CONFIG_ASYNC_FORK */
|
||
|
#endif /* _LINUX_ASYNC_FORK_H */
|