summaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@parallels.com>2017-02-22 18:42:27 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 19:41:28 -0500
commit893e26e61d04eac974ded0c11e1647b335c8cb7b (patch)
treed75bbbd621a08130e8794dffcedc71f4a6ff50cc /kernel/fork.c
parent656031445d5a855e1c13b291dedae32579d0f3f2 (diff)
userfaultfd: non-cooperative: Add fork() event
When the mm with uffd-ed vmas fork()-s the respective vmas notify their uffds with the event which contains a descriptor with new uffd. This new descriptor can then be used to get events from the child and populate its mm with data. Note, that there can be different uffd-s controlling different vmas within one mm, so first we should collect all those uffds (and ctx-s) in a list and then notify them all one by one but only once per fork(). The context is created at fork() time but the descriptor, file struct and anon inode object is created at event read time. So some trickery is added to the userfaultfd_ctx_read() to handle the ctx queues' locking vs file creation. Another thing worth noticing is that the task that fork()-s waits for the uffd event to get processed WITHOUT the mmap sem. [aarcange@redhat.com: build warning fix] Link: http://lkml.kernel.org/r/20161216144821.5183-10-aarcange@redhat.com Link: http://lkml.kernel.org/r/20161216144821.5183-9-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 'kernel/fork.c')
-rw-r--r--kernel/fork.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index ff82e24573b6..d12fcc4db8a3 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -55,6 +55,7 @@
55#include <linux/rmap.h> 55#include <linux/rmap.h>
56#include <linux/ksm.h> 56#include <linux/ksm.h>
57#include <linux/acct.h> 57#include <linux/acct.h>
58#include <linux/userfaultfd_k.h>
58#include <linux/tsacct_kern.h> 59#include <linux/tsacct_kern.h>
59#include <linux/cn_proc.h> 60#include <linux/cn_proc.h>
60#include <linux/freezer.h> 61#include <linux/freezer.h>
@@ -561,6 +562,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
561 struct rb_node **rb_link, *rb_parent; 562 struct rb_node **rb_link, *rb_parent;
562 int retval; 563 int retval;
563 unsigned long charge; 564 unsigned long charge;
565 LIST_HEAD(uf);
564 566
565 uprobe_start_dup_mmap(); 567 uprobe_start_dup_mmap();
566 if (down_write_killable(&oldmm->mmap_sem)) { 568 if (down_write_killable(&oldmm->mmap_sem)) {
@@ -617,12 +619,13 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
617 if (retval) 619 if (retval)
618 goto fail_nomem_policy; 620 goto fail_nomem_policy;
619 tmp->vm_mm = mm; 621 tmp->vm_mm = mm;
622 retval = dup_userfaultfd(tmp, &uf);
623 if (retval)
624 goto fail_nomem_anon_vma_fork;
620 if (anon_vma_fork(tmp, mpnt)) 625 if (anon_vma_fork(tmp, mpnt))
621 goto fail_nomem_anon_vma_fork; 626 goto fail_nomem_anon_vma_fork;
622 tmp->vm_flags &= 627 tmp->vm_flags &= ~(VM_LOCKED | VM_LOCKONFAULT);
623 ~(VM_LOCKED|VM_LOCKONFAULT|VM_UFFD_MISSING|VM_UFFD_WP);
624 tmp->vm_next = tmp->vm_prev = NULL; 628 tmp->vm_next = tmp->vm_prev = NULL;
625 tmp->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
626 file = tmp->vm_file; 629 file = tmp->vm_file;
627 if (file) { 630 if (file) {
628 struct inode *inode = file_inode(file); 631 struct inode *inode = file_inode(file);
@@ -678,6 +681,7 @@ out:
678 up_write(&mm->mmap_sem); 681 up_write(&mm->mmap_sem);
679 flush_tlb_mm(oldmm); 682 flush_tlb_mm(oldmm);
680 up_write(&oldmm->mmap_sem); 683 up_write(&oldmm->mmap_sem);
684 dup_userfaultfd_complete(&uf);
681fail_uprobe_end: 685fail_uprobe_end:
682 uprobe_end_dup_mmap(); 686 uprobe_end_dup_mmap();
683 return retval; 687 return retval;