aboutsummaryrefslogtreecommitdiffstats
path: root/fs/userfaultfd.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@parallels.com>2017-02-22 18:42:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 19:41:28 -0500
commit72f87654c69690ff4721bd9b4a39983f971de9a5 (patch)
tree0e607734e047d2dc7379b186c5c8c57e9276fd8a /fs/userfaultfd.c
parentd3aadc8ed4cb447981ecf34f9af71cddc6cf907d (diff)
userfaultfd: non-cooperative: add mremap() event
The event denotes that an area [start:end] moves to different location. Length change isn't reported as "new" addresses, if they appear on the uffd reader side they will not contain any data and the latter can just zeromap them. Waiting for the event ACK is also done outside of mmap sem, as for fork event. Link: http://lkml.kernel.org/r/20161216144821.5183-12-aarcange@redhat.com Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com> Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com> Cc: Hillf Danton <hillf.zj@alibaba-inc.com> Cc: Michael Rapoport <RAPOPORT@il.ibm.com> Cc: Mike Kravetz <mike.kravetz@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/userfaultfd.c')
-rw-r--r--fs/userfaultfd.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 27978f249016..68f978beefac 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -596,6 +596,43 @@ void dup_userfaultfd_complete(struct list_head *fcs)
596 } 596 }
597} 597}
598 598
599void mremap_userfaultfd_prep(struct vm_area_struct *vma,
600 struct vm_userfaultfd_ctx *vm_ctx)
601{
602 struct userfaultfd_ctx *ctx;
603
604 ctx = vma->vm_userfaultfd_ctx.ctx;
605 if (ctx && (ctx->features & UFFD_FEATURE_EVENT_REMAP)) {
606 vm_ctx->ctx = ctx;
607 userfaultfd_ctx_get(ctx);
608 }
609}
610
611void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx vm_ctx,
612 unsigned long from, unsigned long to,
613 unsigned long len)
614{
615 struct userfaultfd_ctx *ctx = vm_ctx.ctx;
616 struct userfaultfd_wait_queue ewq;
617
618 if (!ctx)
619 return;
620
621 if (to & ~PAGE_MASK) {
622 userfaultfd_ctx_put(ctx);
623 return;
624 }
625
626 msg_init(&ewq.msg);
627
628 ewq.msg.event = UFFD_EVENT_REMAP;
629 ewq.msg.arg.remap.from = from;
630 ewq.msg.arg.remap.to = to;
631 ewq.msg.arg.remap.len = len;
632
633 userfaultfd_event_wait_completion(ctx, &ewq);
634}
635
599static int userfaultfd_release(struct inode *inode, struct file *file) 636static int userfaultfd_release(struct inode *inode, struct file *file)
600{ 637{
601 struct userfaultfd_ctx *ctx = file->private_data; 638 struct userfaultfd_ctx *ctx = file->private_data;