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

Re: [PATCH 2/3] xen/domain: Introduce domain_teardown()



Hi Andrew,

On 21/12/2020 18:14, Andrew Cooper wrote:
There is no common equivelent of domain_reliquish_resources(), which has

s/equivelent/equivalent/

caused various pieces of common cleanup to live in inappropriate
places.

Perhaps most obviously, evtchn_destroy() is called for every continuation of
domain_reliquish_resources(), which can easily be thousands of times.

s/reliquish/relinquish/


Create domain_teardown() to be a new top level facility, and call it from the
appropriate positions in domain_kill() and domain_create()'s error path.

No change in behaviour yet.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Wei Liu <wl@xxxxxxx>
CC: Stefano Stabellini <sstabellini@xxxxxxxxxx>
CC: Julien Grall <julien@xxxxxxx>
CC: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
---
  xen/common/domain.c     | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
  xen/include/xen/sched.h |  8 +++++++
  2 files changed, 67 insertions(+)

diff --git a/xen/common/domain.c b/xen/common/domain.c
index ce3667f1b4..ef1987335b 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -273,6 +273,59 @@ static int __init parse_extra_guest_irqs(const char *s)
  custom_param("extra_guest_irqs", parse_extra_guest_irqs);
/*
+ * Release resources held by a domain.  There may or may not be live
+ * references to the domain, and it may or may not be fully constructed.
+ *
+ * d->is_dying differing between DOMDYING_dying and DOMDYING_dead can be used
+ * to determine if live references to the domain exist, and also whether
+ * continuations are permitted.
+ *
+ * If d->is_dying is DOMDYING_dead, this must not return non-zero.
+ */
+static int domain_teardown(struct domain *d)
+{
+    BUG_ON(!d->is_dying);
+
+    /*
+     * This hypercall can take minutes of wallclock time to complete.  This
+     * logic implements a co-routine, stashing state in struct domain across
+     * hypercall continuation boundaries.
+     */
+    switch ( d->teardown.val )
+    {
+        /*
+         * Record the current progress.  Subsequent hypercall continuations
+         * will logically restart work from this point.
+         *
+         * PROGRESS() markers must not be in the middle of loops.  The loop
+         * variable isn't preserved across a continuation.
+         *
+         * To avoid redundant work, there should be a marker before each
+         * function which may return -ERESTART.
+         */
+#define PROGRESS(x)                             \
+        d->teardown.val = PROG_ ## x;           \
+        /* Fallthrough */                       \
+    case PROG_ ## x
+
+        enum {
+            PROG_done = 1,
+        };
+
+    case 0:
+    PROGRESS(done):
+        break;
+
+#undef PROGRESS
+
+    default:
+        BUG();
+    }
+
+    return 0;
+}
+
+/*
   * Destroy a domain once all references to it have been dropped.  Used either
   * from the RCU path, or from the domain_create() error path before the domain
   * is inserted into the domlist.
@@ -553,6 +606,9 @@ struct domain *domain_create(domid_t domid,
      if ( init_status & INIT_watchdog )
          watchdog_domain_destroy(d);
+ /* Must not hit a continuation in this context. */
+    ASSERT(domain_teardown(d) == 0);
The ASSERT() will become a NOP in production build, so domain_teardown_down() will not be called.

However, I think it would be better if we pass an extra argument to indicated wheter the code is allowed to preempt. This would make the preemption check more obvious in evtchn_destroy() compare to the current d->is_dying != DOMDYING_dead.

+
      _domain_destroy(d);
return ERR_PTR(err);
@@ -733,6 +789,9 @@ int domain_kill(struct domain *d)
          domain_set_outstanding_pages(d, 0);
          /* fallthrough */
      case DOMDYING_dying:
+        rc = domain_teardown(d);
+        if ( rc )
+            break;
          rc = evtchn_destroy(d);
          if ( rc )
              break;
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index faf5fda36f..3f35c537b8 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -525,6 +525,14 @@ struct domain
      /* Argo interdomain communication support */
      struct argo_domain *argo;
  #endif
+
+    /*
+     * Continuation information for domain_teardown().  All fields entirely
+     * private.
+     */
+    struct {
+        unsigned int val;
+    } teardown;
  };
static inline struct page_list_head *page_to_list(


Cheers,

--
Julien Grall



 


Rackspace

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