* Global checks live here, specific checks are in the callback.
*/
static inline ssize_t
-uffd_ctx_lock_and_validate_dst(struct userfaultfd_ctx *ctx,
- struct uffd_info *info)
+uffd_ctx_lock_and_validate_dst(struct uffd_info *info)
{
/*
* If memory mappings are changing because of non-cooperative
* operation (e.g. mremap) running in parallel, bail out and
* request the user to retry later
*/
- down_read(&ctx->map_changing_lock);
- if (atomic_read(&ctx->mmap_changing))
+ down_read(&info->ctx->map_changing_lock);
+ if (atomic_read(&info->ctx->mmap_changing))
return -EAGAIN;
/*
if (info->wp && !(info->dst_vma->vm_flags & VM_UFFD_WP))
return -EINVAL;
- WARN_ON_ONCE(!info->uffd_ops->is_dst_valid);
- return info->uffd_ops->is_dst_valid(info->dst_vma, info->dst_addr,
- info->len);
+ return 0;
}
ssize_t
if (err)
goto out;
+
+ err = uffd_ctx_lock_and_validate_dst(&info);
+ if (err)
+ goto out_unlock;
+
dst_vma = info.dst_vma;
info.uffd_ops = vma_get_uffd_ops(dst_vma);
- if (WARN_ON_ONCE(!info.uffd_ops->increment)) {
- info.increment = PAGE_SIZE;
- } else {
- info.increment = info.uffd_ops->increment(dst_vma);
- }
+ WARN_ON_ONCE(!info.uffd_ops->increment);
+ WARN_ON_ONCE(!info.uffd_ops->is_dst_valid);
- err = uffd_ctx_lock_and_validate_dst(ctx, &info);
+ info.increment = info.uffd_ops->increment(info.dst_vma);
+ err = info.uffd_ops->is_dst_valid(info.dst_vma, info.dst_addr,
+ info.len);
if (err)
goto out_unlock;
-
/*
* For shmem mappings, khugepaged is allowed to remove page
* tables under us; pte_offset_map_lock() will deal with that.