/* The set of all possible UFFD-related VM flags. */ #define __VM_UFFD_FLAGS (VM_UFFD_MISSING | VM_UFFD_WP | VM_UFFD_MINOR)
/* * CAREFUL: Check include/uapi/asm-generic/fcntl.h when defining * new flags, since they might collide with O_* ones. We want * to re-use O_* flags that couldn't possibly have a meaning * from userfaultfd, in order to leave a free define-space for * shared O_* flags.
*/ #define UFFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
/* * Start with fault_pending_wqh and fault_wqh so they're more likely * to be in the same cacheline. * * Locking order: * fd_wqh.lock * fault_pending_wqh.lock * fault_wqh.lock * event_wqh.lock * * To avoid deadlocks, IRQs must be disabled when taking any of the above locks, * since fd_wqh.lock is taken by aio_poll() while it's holding a lock that's * also taken in IRQ context.
*/ struct userfaultfd_ctx { /* waitqueue head for the pending (i.e. not read) userfaults */
wait_queue_head_t fault_pending_wqh; /* waitqueue head for the userfaults */
wait_queue_head_t fault_wqh; /* waitqueue head for the pseudo fd to wakeup poll/read */
wait_queue_head_t fd_wqh; /* waitqueue head for events */
wait_queue_head_t event_wqh; /* a refile sequence protected by fault_pending_wqh lock */
seqcount_spinlock_t refile_seq; /* pseudo fd refcounting */
refcount_t refcount; /* userfaultfd syscall flags */ unsignedint flags; /* features requested from the userspace */ unsignedint features; /* released */ bool released; /* * Prevents userfaultfd operations (fill/move/wp) from happening while * some non-cooperative event(s) is taking place. Increments are done * in write-mode. Whereas, userfaultfd operations, which includes * reading mmap_changing, is done under read-mode.
*/ struct rw_semaphore map_changing_lock; /* memory mappings are changing because of non-cooperative event */
atomic_t mmap_changing; /* mm with one ore more vmas attached to this userfaultfd_ctx */ struct mm_struct *mm;
};
/* * Never enable huge pmd sharing on some uffd registered vmas: * * - VM_UFFD_WP VMAs, because write protect information is per pgtable entry. * * - VM_UFFD_MINOR VMAs, because otherwise we would never get minor faults for * VMAs which share huge pmds. (If you have two mappings to the same * underlying pages, and fault in the non-UFFD-registered one with a write, * with huge pmd sharing this would *also* setup the second UFFD-registered * mapping, and we'd not get minor faults.)
*/ staticinlinebool uffd_disable_huge_pmd_share(struct vm_area_struct *vma)
{ return vma->vm_flags & (VM_UFFD_WP | VM_UFFD_MINOR);
}
/* * Don't do fault around for either WP or MINOR registered uffd range. For * MINOR registered range, fault around will be a total disaster and ptes can * be installed without notifications; for WP it should mostly be fine as long * as the fault around checks for pte_none() before the installation, however * to be super safe we just forbid it.
*/ staticinlinebool uffd_disable_fault_around(struct vm_area_struct *vma)
{ return vma->vm_flags & (VM_UFFD_WP | VM_UFFD_MINOR);
}
if ((vm_flags & VM_UFFD_MINOR) &&
(!is_vm_hugetlb_page(vma) && !vma_is_shmem(vma))) returnfalse;
/* * If wp async enabled, and WP is the only mode enabled, allow any * memory type.
*/ if (wp_async && (vm_flags == VM_UFFD_WP)) returntrue;
#ifndef CONFIG_PTE_MARKER_UFFD_WP /* * If user requested uffd-wp but not enabled pte markers for * uffd-wp, then shmem & hugetlbfs are not supported but only * anonymous.
*/ if ((vm_flags & VM_UFFD_WP) && !vma_is_anonymous(vma)) returnfalse; #endif
/* By default, allow any of anon|shmem|hugetlb */ return vma_is_anonymous(vma) || is_vm_hugetlb_page(vma) ||
vma_is_shmem(vma);
}
staticinlinebool userfaultfd_wp_use_markers(struct vm_area_struct *vma)
{ /* Only wr-protect mode uses pte markers */ if (!userfaultfd_wp(vma)) returnfalse;
/* File-based uffd-wp always need markers */ if (!vma_is_anonymous(vma)) returntrue;
/* * Anonymous uffd-wp only needs the markers if WP_UNPOPULATED * enabled (to apply markers on zero pages).
*/ return userfaultfd_wp_unpopulated(vma);
}
/* * Returns true if this is a swap pte and was uffd-wp wr-protected in either * forms (pte marker or a normal swap pte), false otherwise.
*/ staticinlinebool pte_swp_uffd_wp_any(pte_t pte)
{ #ifdef CONFIG_PTE_MARKER_UFFD_WP if (!is_swap_pte(pte)) returnfalse;
if (pte_swp_uffd_wp(pte)) returntrue;
if (pte_marker_uffd_wp(pte)) returntrue; #endif returnfalse;
}
#endif/* _LINUX_USERFAULTFD_K_H */
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.