static int hugetlb_mfill_pte_poison(struct uffd_info *info);
static int hugetlb_mfill_pte_continue(struct uffd_info *info);
static int hugetlb_mfill_atomic_pte_copy(struct uffd_info *info);
+int hugetlb_uffd_writeprotect(struct uffd_info *info);
static const struct vm_uffd_ops hugetlb_uffd_ops = {
.copy = hugetlb_mfill_atomic_pte_copy,
.zeropage = NULL,
.cont = hugetlb_mfill_pte_continue,
.poison = hugetlb_mfill_pte_poison,
- .writeprotect = uffd_writeprotect,
+ .writeprotect = hugetlb_uffd_writeprotect,
.is_dst_valid = hugetlb_is_dst_valid,
.increment = hugetlb_mfill_size,
.failed_do_unlock = hugetlb_failed_do_unlock,
goto out;
}
+int hugetlb_uffd_writeprotect(struct uffd_info *info)
+{
+ long err;
+ struct vm_area_struct *dst_vma;
+ unsigned long end = info->src_addr + info->len;
+ unsigned long _start, _end;
+ unsigned long page_mask;
+
+ dst_vma = info->dst_vma;
+ if (!userfaultfd_wp(dst_vma)) {
+ return -ENOENT;
+ }
+
+ page_mask = vma_kernel_pagesize(dst_vma) - 1;
+ if ((info->src_addr & page_mask) || (info->len & page_mask))
+ return -EINVAL;
+
+ _start = max(dst_vma->vm_start, info->src_addr);
+ _end = min(dst_vma->vm_end, end);
+
+ err = uffd_wp_range(dst_vma, _start, _end - _start, info->wp);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
/*
* Used by userfaultfd UFFDIO_* ioctls. Based on userfaultfd's mfill_atomic_pte
* with modifications for hugetlb pages.
if (!userfaultfd_wp(dst_vma))
return -ENOENT;
- if (is_vm_hugetlb_page(dst_vma)) {
- unsigned long page_mask;
- page_mask = vma_kernel_pagesize(dst_vma) - 1;
- if ((info->src_addr & page_mask) || (info->len & page_mask))
- return -EINVAL;
- }
-
_start = max(dst_vma->vm_start, info->src_addr);
_end = min(dst_vma->vm_end, end);