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

[PATCH RFC 4/4] tools/xenstore: use new stable interface instead of libxenctrl



Xenstore is using libxenctrl only for obtaining state information
about domains.

Use the new stable interface XEN_CONTROL_OP_get_state_changed_domain
instead.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
 tools/xenstore/Makefile            |   3 +-
 tools/xenstore/xenstored_control.c |  14 +-
 tools/xenstore/xenstored_domain.c  | 219 ++++++++++++++++-------------
 3 files changed, 130 insertions(+), 106 deletions(-)

diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index 292b478fa1..b78e29470b 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -11,6 +11,7 @@ CFLAGS += -include $(XEN_ROOT)/tools/config.h
 CFLAGS += -I./include
 CFLAGS += $(CFLAGS_libxenevtchn)
 CFLAGS += $(CFLAGS_libxenctrl)
+CFLAGS += $(CFLAGS_libxencall)
 CFLAGS += $(CFLAGS_libxenguest)
 CFLAGS += $(CFLAGS_libxentoolcore)
 CFLAGS += -DXEN_LIB_STORED="\"$(XEN_LIB_STORED)\""
@@ -70,7 +71,7 @@ endif
 $(XENSTORED_OBJS): CFLAGS += $(CFLAGS_libxengnttab)
 
 xenstored: $(XENSTORED_OBJS)
-       $(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) 
$(LDLIBS_libxenctrl) $(LDLIBS_xenstored) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
+       $(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) 
$(LDLIBS_libxencall) $(LDLIBS_xenstored) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
 
 xenstored.a: $(XENSTORED_OBJS)
        $(AR) cr $@ $^
diff --git a/tools/xenstore/xenstored_control.c 
b/tools/xenstore/xenstored_control.c
index 7b4300ef77..d767aea0f9 100644
--- a/tools/xenstore/xenstored_control.c
+++ b/tools/xenstore/xenstored_control.c
@@ -594,6 +594,13 @@ void lu_read_state(void)
        void *ctx = talloc_new(NULL); /* Work context for subfunctions. */
        struct xs_state_preamble *pre;
 
+       /*
+        * We may have missed the VIRQ_DOM_EXC notification and a domain may
+        * have died while we were live-updating. So check all the domains are
+        * still alive. This will pre-initialize all domain structures.
+        */
+       check_domains();
+
        syslog(LOG_INFO, "live-update: read state\n");
        lu_get_dump_state(&state);
        if (state.size == 0)
@@ -634,13 +641,6 @@ void lu_read_state(void)
        lu_close_dump_state(&state);
 
        talloc_free(ctx);
-
-       /*
-        * We may have missed the VIRQ_DOM_EXC notification and a domain may
-        * have died while we were live-updating. So check all the domains are
-        * still alive.
-        */
-       check_domains();
 }
 
 static const char *lu_activate_binary(const void *ctx)
diff --git a/tools/xenstore/xenstored_domain.c 
b/tools/xenstore/xenstored_domain.c
index 47e9107c14..2801e4b24f 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -31,11 +31,12 @@
 #include "xenstored_transaction.h"
 #include "xenstored_watch.h"
 
+#include <xencall.h>
 #include <xenevtchn.h>
-#include <xenctrl.h>
+#include <xen/control.h>
 #include <xen/grant_table.h>
 
-static xc_interface **xc_handle;
+static xencall_handle **xc_handle;
 xengnttab_handle **xgt_handle;
 static evtchn_port_t virq_port;
 
@@ -50,6 +51,7 @@ struct domain
 
        /* The id of this domain */
        unsigned int domid;
+       uint64_t unique_id;
 
        /* Event channel port */
        evtchn_port_t port;
@@ -238,54 +240,114 @@ static int destroy_domain(void *_domain)
        return 0;
 }
 
-static bool get_domain_info(unsigned int domid, xc_dominfo_t *dominfo)
+static bool get_domain_info(struct xen_control_changed_domain *dominfo)
 {
-       return xc_domain_getinfo(*xc_handle, domid, 1, dominfo) == 1 &&
-              dominfo->domid == domid;
+       struct xen_control_changed_domain *buf;
+       int ret;
+
+       buf = xencall_alloc_buffer(*xc_handle, sizeof(*buf));
+       if (!buf)
+               return false;
+       ret = xencall2(*xc_handle, __HYPERVISOR_control_op,
+                      XEN_CONTROL_OP_get_state_changed_domain,
+                      (unsigned long)buf);
+       *dominfo = *buf;
+       xencall_free_buffer(*xc_handle, buf);
+
+       return ret == 0;
 }
 
-void check_domains(void)
+static struct domain *find_domain_struct(unsigned int domid)
+{
+       struct domain *i;
+
+       list_for_each_entry(i, &domains, list) {
+               if (i->domid == domid)
+                       return i;
+       }
+       return NULL;
+}
+
+static struct domain *alloc_domain(unsigned int domid)
 {
-       xc_dominfo_t dominfo;
        struct domain *domain;
+
+       domain = talloc_zero(talloc_autofree_context(), struct domain);
+       if (!domain) {
+               errno = ENOMEM;
+               return NULL;
+       }
+
+       domain->domid = domid;
+       domain->generation = generation;
+       domain->introduced = false;
+
+       talloc_set_destructor(domain, destroy_domain);
+
+       list_add(&domain->list, &domains);
+
+       return domain;
+}
+
+static void domain_drop(struct domain *domain)
+{
        struct connection *conn;
+
+       /* domain is a talloc child of domain->conn. */
+       conn = domain->conn;
+       domain->conn = NULL;
+       talloc_unlink(talloc_autofree_context(), conn);
+}
+
+void check_domains(void)
+{
+       struct xen_control_changed_domain dominfo;
+       struct domain *domain;
        int notify = 0;
-       bool dom_valid;
 
- again:
-       list_for_each_entry(domain, &domains, list) {
-               dom_valid = get_domain_info(domain->domid, &dominfo);
-               if (!domain->introduced) {
-                       if (!dom_valid) {
+       while (get_domain_info(&dominfo)) {
+               domain = find_domain_struct(dominfo.domid);
+
+               if (!dominfo.state) {
+                       if (domain && !domain->introduced)
                                talloc_free(domain);
-                               goto again;
-                       }
                        continue;
                }
-               if (dom_valid) {
-                       if ((dominfo.crashed || dominfo.shutdown)
-                           && !domain->shutdown) {
-                               domain->shutdown = true;
-                               notify = 1;
-                       }
-                       /*
-                        * On Restore, we may have been unable to remap the
-                        * interface and the port. As we don't know whether
-                        * this was because of a dying domain, we need to
-                        * check if the interface and port are still valid.
-                        */
-                       if (!dominfo.dying && domain->port &&
-                           domain->interface)
+
+               if (domain && domain->unique_id &&
+                   domain->unique_id != dominfo.unique_id) {
+                       if (domain->conn)
+                               domain_drop(domain);
+                       else
+                               talloc_free(domain);
+                       domain = NULL;
+               }
+
+               if (!domain) {
+                       domain = alloc_domain(dominfo.domid);
+                       if (!domain)
                                continue;
+                       domain->unique_id = dominfo.unique_id;
                }
-               if (domain->conn) {
-                       /* domain is a talloc child of domain->conn. */
-                       conn = domain->conn;
-                       domain->conn = NULL;
-                       talloc_unlink(talloc_autofree_context(), conn);
-                       notify = 0; /* destroy_domain() fires the watch */
-                       goto again;
+
+               if ((dominfo.state & XEN_CONTROL_CHANGEDDOM_STATE_SHUTDOWN) &&
+                   !domain->shutdown) {
+                       domain->shutdown = true;
+                       notify = 1;
                }
+
+               /*
+                * On Restore, we may have been unable to remap the
+                * interface and the port. As we don't know whether
+                * this was because of a dying domain, we need to
+                * check if the interface and port are still valid.
+                */
+               if (!(dominfo.state & XEN_CONTROL_CHANGEDDOM_STATE_DYING) &&
+                   domain->port && domain->interface)
+                       continue;
+
+               if (domain->conn)
+                       domain_drop(domain);
        }
 
        if (notify)
@@ -323,46 +385,6 @@ static char *talloc_domain_path(void *context, unsigned 
int domid)
        return talloc_asprintf(context, "/local/domain/%u", domid);
 }
 
-static struct domain *find_domain_struct(unsigned int domid)
-{
-       struct domain *i;
-
-       list_for_each_entry(i, &domains, list) {
-               if (i->domid == domid)
-                       return i;
-       }
-       return NULL;
-}
-
-static struct domain *alloc_domain(const void *context, unsigned int domid)
-{
-       struct domain *domain;
-
-       domain = talloc(context, struct domain);
-       if (!domain) {
-               errno = ENOMEM;
-               return NULL;
-       }
-
-       domain->domid = domid;
-       domain->generation = generation;
-       domain->introduced = false;
-
-       talloc_set_destructor(domain, destroy_domain);
-
-       list_add(&domain->list, &domains);
-
-       return domain;
-}
-
-static struct domain *find_or_alloc_domain(const void *ctx, unsigned int domid)
-{
-       struct domain *domain;
-
-       domain = find_domain_struct(domid);
-       return domain ? : alloc_domain(ctx, domid);
-}
-
 static int new_domain(struct domain *domain, int port, bool restore)
 {
        int rc;
@@ -443,9 +465,13 @@ static struct domain *introduce_domain(const void *ctx,
        struct xenstore_domain_interface *interface;
        bool is_master_domain = (domid == xenbus_master_domid());
 
-       domain = find_or_alloc_domain(ctx, domid);
-       if (!domain)
+       check_domains();
+
+       domain = find_domain_struct(domid);
+       if (!domain) {
+               errno = ENOENT;
                return NULL;
+       }
 
        if (!domain->introduced) {
                interface = is_master_domain ? xenbus_map()
@@ -650,7 +676,7 @@ int do_reset_watches(struct connection *conn, struct 
buffered_data *in)
 
 static int close_xc_handle(void *_handle)
 {
-       xc_interface_close(*(xc_interface**)_handle);
+       xencall_close(*(xencall_handle **)_handle);
        return 0;
 }
 
@@ -741,11 +767,11 @@ void domain_init(int evtfd)
 {
        int rc;
 
-       xc_handle = talloc(talloc_autofree_context(), xc_interface*);
+       xc_handle = talloc(talloc_autofree_context(), xencall_handle *);
        if (!xc_handle)
                barf_perror("Failed to allocate domain handle");
 
-       *xc_handle = xc_interface_open(0,0,0);
+       *xc_handle = xencall_open(NULL, 0);
        if (!*xc_handle)
                barf_perror("Failed to open connection to hypervisor");
 
@@ -821,7 +847,6 @@ void domain_entry_inc(struct connection *conn, struct node 
*node)
  * count (used for testing whether a node permission is older than a domain).
  *
  * Return values:
- * -1: error
  *  0: domain has higher generation count (it is younger than a node with the
  *     given count), or domain isn't existing any longer
  *  1: domain is older than the node
@@ -829,7 +854,6 @@ void domain_entry_inc(struct connection *conn, struct node 
*node)
 static int chk_domain_generation(unsigned int domid, uint64_t gen)
 {
        struct domain *d;
-       xc_dominfo_t dominfo;
 
        if (!xc_handle && domid == 0)
                return 1;
@@ -838,11 +862,9 @@ static int chk_domain_generation(unsigned int domid, 
uint64_t gen)
        if (d)
                return (d->generation <= gen) ? 1 : 0;
 
-       if (!get_domain_info(domid, &dominfo))
-               return 0;
-
-       d = alloc_domain(NULL, domid);
-       return d ? 1 : -1;
+       check_domains();
+       d = find_domain_struct(domid);
+       return (d && d->generation <= gen) ? 1 : 0;
 }
 
 /*
@@ -855,8 +877,6 @@ int domain_adjust_node_perms(struct node *node)
        int ret;
 
        ret = chk_domain_generation(node->perms.p[0].id, node->generation);
-       if (ret < 0)
-               return errno;
 
        /* If the owner doesn't exist any longer give it to priv domain. */
        if (!ret)
@@ -867,8 +887,6 @@ int domain_adjust_node_perms(struct node *node)
                        continue;
                ret = chk_domain_generation(node->perms.p[i].id,
                                            node->generation);
-               if (ret < 0)
-                       return errno;
                if (!ret)
                        node->perms.p[i].perms |= XS_PERM_IGNORE;
        }
@@ -1300,16 +1318,21 @@ void read_state_connection(const void *ctx, const void 
*state)
        } else {
                domain = introduce_domain(ctx, sc->spec.ring.domid,
                                          sc->spec.ring.evtchn, true);
-               if (!domain)
+               if (!domain) {
+                       /* Domain vanished during LM? */
+                       if (errno = ENOENT)
+                               return;
                        barf("domain allocation error");
+               }
 
                if (sc->spec.ring.tdomid != DOMID_INVALID) {
-                       tdomain = find_or_alloc_domain(ctx,
-                                                      sc->spec.ring.tdomid);
-                       if (!tdomain)
+                       tdomain = find_domain_struct(sc->spec.ring.tdomid);
+                       if (!tdomain && errno != ENOENT)
                                barf("target domain allocation error");
-                       talloc_reference(domain->conn, tdomain->conn);
-                       domain->conn->target = tdomain->conn;
+                       if (tdomain) {
+                               talloc_reference(domain->conn, tdomain->conn);
+                               domain->conn->target = tdomain->conn;
+                       }
                }
                conn = domain->conn;
        }
-- 
2.26.2




 


Rackspace

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