summaryrefslogtreecommitdiffstats
path: root/fs/userfaultfd.c
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2018-01-19 18:32:05 +0100
committerSean Paul <seanpaul@chromium.org>2018-01-19 18:32:05 +0100
commit54156da8937c9f5f84b4215e239a61ecc7c29275 (patch)
tree7fb1e07ebedc5fbd35a29f5d450dee538763efdb /fs/userfaultfd.c
parentdrm: add kernel doc for exported gem dmabuf_ops (diff)
parentBackMerge tag 'v4.15-rc8' into drm-next (diff)
downloadlinux-54156da8937c9f5f84b4215e239a61ecc7c29275.tar.xz
linux-54156da8937c9f5f84b4215e239a61ecc7c29275.zip
Merge airlied/drm-next into drm-misc-next
It's been a while since we've backmerged drm-next. Dave just brought back 4.15-rc8, so now's a good time to freshen things up around here. Signed-off-by: Sean Paul <seanpaul@chromium.org>
Diffstat (limited to 'fs/userfaultfd.c')
-rw-r--r--fs/userfaultfd.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index ac9a4e65ca49..41a75f9f23fd 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -570,11 +570,14 @@ out:
static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
struct userfaultfd_wait_queue *ewq)
{
+ struct userfaultfd_ctx *release_new_ctx;
+
if (WARN_ON_ONCE(current->flags & PF_EXITING))
goto out;
ewq->ctx = ctx;
init_waitqueue_entry(&ewq->wq, current);
+ release_new_ctx = NULL;
spin_lock(&ctx->event_wqh.lock);
/*
@@ -601,8 +604,7 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
new = (struct userfaultfd_ctx *)
(unsigned long)
ewq->msg.arg.reserved.reserved1;
-
- userfaultfd_ctx_put(new);
+ release_new_ctx = new;
}
break;
}
@@ -617,6 +619,20 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
__set_current_state(TASK_RUNNING);
spin_unlock(&ctx->event_wqh.lock);
+ if (release_new_ctx) {
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = release_new_ctx->mm;
+
+ /* the various vma->vm_userfaultfd_ctx still points to it */
+ down_write(&mm->mmap_sem);
+ for (vma = mm->mmap; vma; vma = vma->vm_next)
+ if (vma->vm_userfaultfd_ctx.ctx == release_new_ctx)
+ vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
+ up_write(&mm->mmap_sem);
+
+ userfaultfd_ctx_put(release_new_ctx);
+ }
+
/*
* ctx may go away after this if the userfault pseudo fd is
* already released.