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

[Xen-devel] [PATCH RFCv3 3/8] xen: introduce XEN_DOMCTL_set_recipient



New operation sets the 'recipient' domain which will recieve all
memory pages from a particular domain when these pages are freed.

Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx>
---
 xen/common/domain.c         |  3 +++
 xen/common/domctl.c         | 27 +++++++++++++++++++++++++++
 xen/common/page_alloc.c     | 26 ++++++++++++++++++++++----
 xen/include/public/domctl.h | 19 +++++++++++++++++++
 xen/include/xen/sched.h     |  1 +
 5 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/xen/common/domain.c b/xen/common/domain.c
index 62514b0..6bceb64 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -822,6 +822,9 @@ static void complete_domain_destroy(struct rcu_head *head)
     if ( d->target != NULL )
         put_domain(d->target);
 
+    if ( d->recipient != NULL )
+        put_domain(d->recipient);
+
     evtchn_destroy_final(d);
 
     radix_tree_destroy(&d->pirq_tree, free_pirq_struct);
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 1ad0729..38cd10a 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -1152,6 +1152,33 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) 
u_domctl)
     }
     break;
 
+    case XEN_DOMCTL_set_recipient:
+    {
+        struct domain *recipient_dom;
+
+        if ( op->u.recipient.recipient == DOMID_INVALID )
+        {
+            if ( d->recipient )
+            {
+                put_domain(d->recipient);
+            }
+            d->recipient = NULL;
+            break;
+        }
+
+        recipient_dom = get_domain_by_id(op->u.recipient.recipient);
+        if ( recipient_dom == NULL )
+        {
+            ret = -ESRCH;
+            break;
+        }
+        else
+        {
+            d->recipient = recipient_dom;
+        }
+    }
+    break;
+
     default:
         ret = arch_do_domctl(op, d, u_domctl);
         break;
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 7b4092d..abb2ef3 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -1707,6 +1707,7 @@ void free_domheap_pages(struct page_info *pg, unsigned 
int order)
 {
     struct domain *d = page_get_owner(pg);
     unsigned int i;
+    unsigned long mfn, gmfn;
     bool_t drop_dom_ref;
 
     ASSERT(!in_irq());
@@ -1764,11 +1765,28 @@ void free_domheap_pages(struct page_info *pg, unsigned 
int order)
             scrub = 1;
         }
 
-        if ( unlikely(scrub) )
-            for ( i = 0; i < (1 << order); i++ )
-                scrub_one_page(&pg[i]);
+        if ( !d || !d->recipient || d->recipient->is_dying )
+        {
+            if ( unlikely(scrub) )
+                for ( i = 0; i < (1 << order); i++ )
+                    scrub_one_page(&pg[i]);
 
-        free_heap_pages(pg, order);
+            free_heap_pages(pg, order);
+        }
+        else
+        {
+            mfn = page_to_mfn(pg);
+            gmfn = mfn_to_gmfn(d, mfn);
+
+            page_set_owner(pg, NULL);
+            assign_pages(d->recipient, pg, order, 0);
+
+            if ( guest_physmap_add_page(d->recipient, gmfn, mfn, order) )
+            {
+                gdprintk(XENLOG_INFO, "Failed to add page to domain's physmap"
+                         " mfn: %lx\n", mfn);
+            }
+        }
     }
 
     if ( drop_dom_ref )
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index cfa39b3..7fcb6db 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -965,6 +965,23 @@ struct xen_domctl_vnuma {
 typedef struct xen_domctl_vnuma xen_domctl_vnuma_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_vnuma_t);
 
+/*
+ * XEN_DOMCTL_set_recipient - sets the 'recipient' domain which will recieve
+ * all the domain's memory after its death or when and memory page from
+ * domain's heap is being freed. Pages from xen heap belonging to the domain
+ * are not copied. An additional reference link to the destination domain is
+ * being taken to prevent it from dying.
+ * When DOMID_INVALID is supplied as a recipient the source domain returns to
+ * its original state when memory pages are freed normally, reference link to
+ * the destination domain is being dropped.
+ */
+struct xen_domctl_set_recipient {
+    domid_t recipient;
+};
+typedef struct xen_domctl_set_recipient xen_domctl_set_recipient_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_recipient_t);
+
+
 struct xen_domctl {
     uint32_t cmd;
 #define XEN_DOMCTL_createdomain                   1
@@ -1038,6 +1055,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_get_vcpu_msrs                 72
 #define XEN_DOMCTL_set_vcpu_msrs                 73
 #define XEN_DOMCTL_setvnumainfo                  74
+#define XEN_DOMCTL_set_recipient                 75
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -1099,6 +1117,7 @@ struct xen_domctl {
         struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
         struct xen_domctl_gdbsx_domstatus   gdbsx_domstatus;
         struct xen_domctl_vnuma             vnuma;
+        struct xen_domctl_set_recipient     recipient;
         uint8_t                             pad[128];
     } u;
 };
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index c5157e6..d00d655 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -366,6 +366,7 @@ struct domain
     bool_t           is_privileged;
     /* Which guest this guest has privileges on */
     struct domain   *target;
+    struct domain   *recipient;
     /* Is this guest being debugged by dom0? */
     bool_t           debugger_attached;
     /* Is this guest dying (i.e., a zombie)? */
-- 
1.9.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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