|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |