[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/2] x86/mem_sharing: Add extra variable to track fork progress



When VM forking is initiated a VM is not supposed to try to perform mem_sharing
yet as the fork process hasn't completed all required steps. However, the vCPU
bring-up paths trigger guest memory accesses that can lead to such premature
sharing ops. However, the gating check to see whether a VM is a fork is set
already (ie. the domain has a parent).

In this patch we introduce a separate variable to store the information that
forking has been initiated so that the non-restartable part of the forking op
is not repeated and we avoid the premature sharing ops from triggering.

Signed-off-by: Tamas K Lengyel <tamas@xxxxxxxxxxxxx>
---
 xen/arch/x86/include/asm/hvm/domain.h |  8 ++++++++
 xen/arch/x86/mm/mem_sharing.c         | 10 +++++++---
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/include/asm/hvm/domain.h 
b/xen/arch/x86/include/asm/hvm/domain.h
index 698455444e..76a08b55f9 100644
--- a/xen/arch/x86/include/asm/hvm/domain.h
+++ b/xen/arch/x86/include/asm/hvm/domain.h
@@ -33,6 +33,14 @@ struct mem_sharing_domain
 {
     bool enabled, block_interrupts;
 
+    /*
+     * We need to avoid trying to nominate pages for forking until the
+     * fork operation is completely finished. As parts of fork creation
+     * is restartable we mark here if the process started to skip the
+     * non-restartable portion.
+     */
+    bool fork_started;
+
     /*
      * When releasing shared gfn's in a preemptible manner, recall where
      * to resume the search.
diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
index 649d93dc54..b55c5bccdd 100644
--- a/xen/arch/x86/mm/mem_sharing.c
+++ b/xen/arch/x86/mm/mem_sharing.c
@@ -1888,11 +1888,12 @@ static int copy_settings(struct domain *cd, struct 
domain *d)
 static int fork(struct domain *cd, struct domain *d)
 {
     int rc = -EBUSY;
+    struct mem_sharing_domain *msd = &cd->arch.hvm.mem_sharing;
 
     if ( !cd->controller_pause_count )
         return rc;
 
-    if ( !cd->parent )
+    if ( !msd->fork_started )
     {
         if ( !get_domain(d) )
         {
@@ -1905,7 +1906,7 @@ static int fork(struct domain *cd, struct domain *d)
         *cd->arch.cpuid = *d->arch.cpuid;
         *cd->arch.msr = *d->arch.msr;
         cd->vmtrace_size = d->vmtrace_size;
-        cd->parent = d;
+        msd->fork_started = 1;
     }
 
     /* This is preemptible so it's the first to get done */
@@ -1918,8 +1919,11 @@ static int fork(struct domain *cd, struct domain *d)
     rc = copy_settings(cd, d);
 
  done:
-    if ( rc && rc != -ERESTART )
+    if ( !rc )
+        cd->parent = d;
+    else if ( rc != -ERESTART )
     {
+        msd->fork_started = 0;
         cd->parent = NULL;
         domain_unpause(d);
         put_domain(d);
-- 
2.34.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.