# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID d6d77aa96aa1465d287069e809b489a569a9b3fb
# Parent 275e28658c66b4327cded36dd86a20e81399efa0
Make xenstored listen to domain exception virqs.
The virq triggers a scan for domains which have gone away, and then
removes those domains.
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
diff -r 275e28658c66 -r d6d77aa96aa1 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c Tue Sep 6 13:43:28 2005
+++ b/tools/xenstore/xenstored_core.c Tue Sep 6 16:59:14 2005
@@ -49,6 +49,9 @@
#include "xenstored_watch.h"
#include "xenstored_transaction.h"
#include "xenstored_domain.h"
+#include "xenctrl.h"
+#include "xen/io/domain_controller.h"
+#include "xcs_proto.h"
static bool verbose;
LIST_HEAD(connections);
@@ -322,7 +325,7 @@
}
static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock,
- int event_fd)
+ int event_fd, int xcs_fd)
{
struct connection *i;
int max;
@@ -337,6 +340,9 @@
FD_SET(event_fd, inset);
if (event_fd > max)
max = event_fd;
+ FD_SET(xcs_fd, inset);
+ if (xcs_fd > max)
+ max = xcs_fd;
list_for_each_entry(i, &connections, list) {
if (i->domain)
continue;
@@ -1636,6 +1642,125 @@
umask(0);
}
+static int open_domain_socket(const char *path)
+{
+ struct sockaddr_un addr;
+ int sock;
+ size_t addr_len;
+
+ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
+ goto out;
+ }
+
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, path);
+ addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
+
+ if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
+ goto out_close_sock;
+ }
+
+ return sock;
+
+ out_close_sock:
+ close(sock);
+ out:
+ return -1;
+}
+
+bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
+{
+ size_t offset = 0;
+ ssize_t len;
+
+ while (offset < size) {
+ if (do_read) {
+ len = read(fd, data + offset, size - offset);
+ } else {
+ len = write(fd, data + offset, size - offset);
+ }
+
+ if (len < 1) {
+ if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
+ continue;
+ } else {
+ return false;
+ }
+ } else {
+ offset += len;
+ }
+ }
+
+ return true;
+}
+
+#define read_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, true)
+#define write_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, false)
+
+/* synchronized send/recv strictly for setting up xcs */
+/* always use asychronize callbacks any other time */
+static bool xcs_send_recv(int fd, xcs_msg_t *msg)
+{
+ bool ret = false;
+
+ if (!write_sync(fd, msg, sizeof(*msg))) {
+ eprintf("Write failed at %s:%s():L%d? Possible bug.",
+ __FILE__, __FUNCTION__, __LINE__);
+ goto out;
+ }
+
+ if (!read_sync(fd, msg, sizeof(*msg))) {
+ eprintf("Read failed at %s:%s():L%d? Possible bug.",
+ __FILE__, __FUNCTION__, __LINE__);
+ goto out;
+ }
+
+ ret = true;
+
+ out:
+ return ret;
+}
+
+static void handle_xcs(int xcs_fd)
+{
+ xcs_msg_t msg;
+
+ if (!read_sync(xcs_fd, &msg, sizeof(msg)))
+ barf_perror("read from xcs failed!");
+
+ domain_cleanup();
+}
+
+static int xcs_init(void)
+{
+ int ctrl_fd, data_fd;
+ xcs_msg_t msg;
+
+ ctrl_fd = open_domain_socket(XCS_SUN_PATH);
+ if (ctrl_fd == -1)
+ barf_perror("Failed to contact xcs. Is it running?");
+
+ data_fd = open_domain_socket(XCS_SUN_PATH);
+ if (data_fd == -1)
+ barf_perror("Failed to contact xcs. Is it running?");
+
+ memset(&msg, 0, sizeof(msg));
+ msg.type = XCS_CONNECT_CTRL;
+ if (!xcs_send_recv(ctrl_fd, &msg) || msg.result != XCS_RSLT_OK)
+ barf_perror("xcs control connect failed.");
+
+ msg.type = XCS_CONNECT_DATA;
+ if (!xcs_send_recv(data_fd, &msg) || msg.result != XCS_RSLT_OK)
+ barf_perror("xcs data connect failed.");
+
+ msg.type = XCS_VIRQ_BIND;
+ msg.u.virq.virq = VIRQ_DOM_EXC;
+ if (!xcs_send_recv(ctrl_fd, &msg) || msg.result != XCS_RSLT_OK)
+ barf_perror("xcs virq bind failed.");
+
+ return data_fd;
+}
+
static struct option options[] = {
{ "pid-file", 1, NULL, 'F' },
@@ -1647,7 +1772,7 @@
int main(int argc, char *argv[])
{
- int opt, *sock, *ro_sock, event_fd, max;
+ int opt, *sock, *ro_sock, event_fd, xcs_fd, max;
struct sockaddr_un addr;
fd_set inset, outset;
bool dofork = true;
@@ -1731,6 +1856,9 @@
/* Listen to hypervisor. */
event_fd = domain_init();
+ /* Listen to hypervisor - more. */
+ xcs_fd = xcs_init();
+
/* Restore existing connections. */
restore_existing_connections();
@@ -1751,7 +1879,8 @@
#endif
/* Get ready to listen to the tools. */
- max = initialize_set(&inset, &outset, *sock, *ro_sock, event_fd);
+ max = initialize_set(&inset, &outset, *sock, *ro_sock, event_fd,
+ xcs_fd);
/* Main loop. */
/* FIXME: Rewrite so noone can starve. */
@@ -1781,6 +1910,9 @@
if (FD_ISSET(event_fd, &inset))
handle_event(event_fd);
+
+ if (FD_ISSET(xcs_fd, &inset))
+ handle_xcs(xcs_fd);
list_for_each_entry(i, &connections, list) {
if (i->domain)
@@ -1824,6 +1956,7 @@
/* If transactions ended, we might be able to do more work. */
unblock_connections();
- max = initialize_set(&inset, &outset, *sock,*ro_sock,event_fd);
- }
-}
+ max = initialize_set(&inset, &outset, *sock, *ro_sock,
+ event_fd, xcs_fd);
+ }
+}
diff -r 275e28658c66 -r d6d77aa96aa1 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Tue Sep 6 13:43:28 2005
+++ b/tools/xenstore/xenstored_domain.c Tue Sep 6 16:59:14 2005
@@ -363,6 +363,21 @@
send_ack(conn, XS_RELEASE);
}
+void domain_cleanup(void)
+{
+ xc_dominfo_t dominfo;
+ struct domain *domain, *tmp;
+
+ list_for_each_entry_safe(domain, tmp, &domains, list) {
+ if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
+ &dominfo) == 1 &&
+ dominfo.domid == domain->domid &&
+ !dominfo.dying && !dominfo.crashed && !dominfo.shutdown)
+ continue;
+ talloc_free(domain->conn);
+ }
+}
+
void do_get_domain_path(struct connection *conn, const char *domid_str)
{
struct domain *domain;
diff -r 275e28658c66 -r d6d77aa96aa1 tools/xenstore/xenstored_domain.h
--- a/tools/xenstore/xenstored_domain.h Tue Sep 6 13:43:28 2005
+++ b/tools/xenstore/xenstored_domain.h Tue Sep 6 16:59:14 2005
@@ -28,6 +28,10 @@
/* domid */
void do_release(struct connection *conn, const char *domid_str);
+/* Enumerate domains and release connections for non-existant or dying
+ * domains. */
+void domain_cleanup(void);
+
/* domid */
void do_get_domain_path(struct connection *conn, const char *domid_str);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|