ia64/xen-unstable

changeset 6656:d6d77aa96aa1

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@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 06 16:59:14 2005 +0000 (2005-09-06)
parents 275e28658c66
children d4d69c509371
files tools/xenstore/xenstored_core.c tools/xenstore/xenstored_domain.c tools/xenstore/xenstored_domain.h
line diff
     1.1 --- a/tools/xenstore/xenstored_core.c	Tue Sep 06 13:43:28 2005 +0000
     1.2 +++ b/tools/xenstore/xenstored_core.c	Tue Sep 06 16:59:14 2005 +0000
     1.3 @@ -49,6 +49,9 @@
     1.4  #include "xenstored_watch.h"
     1.5  #include "xenstored_transaction.h"
     1.6  #include "xenstored_domain.h"
     1.7 +#include "xenctrl.h"
     1.8 +#include "xen/io/domain_controller.h"
     1.9 +#include "xcs_proto.h"
    1.10  
    1.11  static bool verbose;
    1.12  LIST_HEAD(connections);
    1.13 @@ -322,7 +325,7 @@ static int destroy_conn(void *_conn)
    1.14  }
    1.15  
    1.16  static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock,
    1.17 -			  int event_fd)
    1.18 +			  int event_fd, int xcs_fd)
    1.19  {
    1.20  	struct connection *i;
    1.21  	int max;
    1.22 @@ -337,6 +340,9 @@ static int initialize_set(fd_set *inset,
    1.23  	FD_SET(event_fd, inset);
    1.24  	if (event_fd > max)
    1.25  		max = event_fd;
    1.26 +	FD_SET(xcs_fd, inset);
    1.27 +	if (xcs_fd > max)
    1.28 +		max = xcs_fd;
    1.29  	list_for_each_entry(i, &connections, list) {
    1.30  		if (i->domain)
    1.31  			continue;
    1.32 @@ -1636,6 +1642,125 @@ static void daemonize(void)
    1.33  	umask(0);
    1.34  }
    1.35  
    1.36 +static int open_domain_socket(const char *path)
    1.37 +{
    1.38 +	struct sockaddr_un addr;
    1.39 +	int sock;
    1.40 +	size_t addr_len;
    1.41 +
    1.42 +	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
    1.43 +		goto out;
    1.44 +	}
    1.45 +
    1.46 +	addr.sun_family = AF_UNIX;
    1.47 +	strcpy(addr.sun_path, path);
    1.48 +	addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
    1.49 +
    1.50 +	if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
    1.51 +		goto out_close_sock;
    1.52 +	}
    1.53 +
    1.54 +	return sock;
    1.55 +
    1.56 + out_close_sock:
    1.57 +	close(sock);
    1.58 + out:
    1.59 +	return -1;
    1.60 +}
    1.61 +
    1.62 +bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
    1.63 +{
    1.64 +	size_t offset = 0;
    1.65 +	ssize_t len;
    1.66 +
    1.67 +	while (offset < size) {
    1.68 +		if (do_read) {
    1.69 +			len = read(fd, data + offset, size - offset);
    1.70 +		} else {
    1.71 +			len = write(fd, data + offset, size - offset);
    1.72 +		}
    1.73 +
    1.74 +		if (len < 1) {
    1.75 +			if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
    1.76 +				continue;
    1.77 +			} else {
    1.78 +				return false;
    1.79 +			}
    1.80 +		} else {
    1.81 +			offset += len;
    1.82 +		}
    1.83 +	}
    1.84 +
    1.85 +	return true;
    1.86 +}
    1.87 +
    1.88 +#define read_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, true)
    1.89 +#define write_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, false)
    1.90 +
    1.91 +/* synchronized send/recv strictly for setting up xcs */
    1.92 +/* always use asychronize callbacks any other time */
    1.93 +static bool xcs_send_recv(int fd, xcs_msg_t *msg)
    1.94 +{
    1.95 +	bool ret = false;
    1.96 +
    1.97 +	if (!write_sync(fd, msg, sizeof(*msg))) {
    1.98 +		eprintf("Write failed at %s:%s():L%d?  Possible bug.",
    1.99 +			__FILE__, __FUNCTION__, __LINE__);
   1.100 +		goto out;
   1.101 +	}
   1.102 +
   1.103 +	if (!read_sync(fd, msg, sizeof(*msg))) {
   1.104 +		eprintf("Read failed at %s:%s():L%d?  Possible bug.",
   1.105 +			__FILE__, __FUNCTION__, __LINE__);
   1.106 +		goto out;
   1.107 +	}
   1.108 +
   1.109 +	ret = true;
   1.110 +
   1.111 + out:
   1.112 +	return ret;
   1.113 +}
   1.114 +
   1.115 +static void handle_xcs(int xcs_fd)
   1.116 +{
   1.117 +	xcs_msg_t msg;
   1.118 +
   1.119 +	if (!read_sync(xcs_fd, &msg, sizeof(msg)))
   1.120 +		barf_perror("read from xcs failed!");
   1.121 +
   1.122 +	domain_cleanup();
   1.123 +}
   1.124 +
   1.125 +static int xcs_init(void)
   1.126 +{
   1.127 +	int ctrl_fd, data_fd;
   1.128 +	xcs_msg_t msg;
   1.129 +
   1.130 +	ctrl_fd = open_domain_socket(XCS_SUN_PATH);
   1.131 +	if (ctrl_fd == -1)
   1.132 +		barf_perror("Failed to contact xcs.  Is it running?");
   1.133 +
   1.134 +	data_fd = open_domain_socket(XCS_SUN_PATH);
   1.135 +	if (data_fd == -1)
   1.136 +		barf_perror("Failed to contact xcs.  Is it running?");
   1.137 +	
   1.138 +	memset(&msg, 0, sizeof(msg));
   1.139 +	msg.type = XCS_CONNECT_CTRL;
   1.140 +	if (!xcs_send_recv(ctrl_fd, &msg) || msg.result != XCS_RSLT_OK)
   1.141 +		barf_perror("xcs control connect failed.");
   1.142 +
   1.143 +	msg.type = XCS_CONNECT_DATA;
   1.144 +	if (!xcs_send_recv(data_fd, &msg) || msg.result != XCS_RSLT_OK)
   1.145 +		barf_perror("xcs data connect failed.");
   1.146 +
   1.147 +	msg.type = XCS_VIRQ_BIND;
   1.148 +	msg.u.virq.virq = VIRQ_DOM_EXC;
   1.149 +	if (!xcs_send_recv(ctrl_fd, &msg) || msg.result != XCS_RSLT_OK)
   1.150 +		barf_perror("xcs virq bind failed.");
   1.151 +
   1.152 +	return data_fd;
   1.153 +}
   1.154 +
   1.155  
   1.156  static struct option options[] = {
   1.157  	{ "pid-file", 1, NULL, 'F' },
   1.158 @@ -1647,7 +1772,7 @@ static struct option options[] = {
   1.159  
   1.160  int main(int argc, char *argv[])
   1.161  {
   1.162 -	int opt, *sock, *ro_sock, event_fd, max;
   1.163 +	int opt, *sock, *ro_sock, event_fd, xcs_fd, max;
   1.164  	struct sockaddr_un addr;
   1.165  	fd_set inset, outset;
   1.166  	bool dofork = true;
   1.167 @@ -1731,6 +1856,9 @@ int main(int argc, char *argv[])
   1.168  	/* Listen to hypervisor. */
   1.169  	event_fd = domain_init();
   1.170  
   1.171 +	/* Listen to hypervisor - more. */
   1.172 +	xcs_fd = xcs_init();
   1.173 +
   1.174  	/* Restore existing connections. */
   1.175  	restore_existing_connections();
   1.176  
   1.177 @@ -1751,7 +1879,8 @@ int main(int argc, char *argv[])
   1.178  #endif
   1.179  
   1.180  	/* Get ready to listen to the tools. */
   1.181 -	max = initialize_set(&inset, &outset, *sock, *ro_sock, event_fd);
   1.182 +	max = initialize_set(&inset, &outset, *sock, *ro_sock, event_fd,
   1.183 +			     xcs_fd);
   1.184  
   1.185  	/* Main loop. */
   1.186  	/* FIXME: Rewrite so noone can starve. */
   1.187 @@ -1782,6 +1911,9 @@ int main(int argc, char *argv[])
   1.188  		if (FD_ISSET(event_fd, &inset))
   1.189  			handle_event(event_fd);
   1.190  
   1.191 +		if (FD_ISSET(xcs_fd, &inset))
   1.192 +			handle_xcs(xcs_fd);
   1.193 +
   1.194  		list_for_each_entry(i, &connections, list) {
   1.195  			if (i->domain)
   1.196  				continue;
   1.197 @@ -1824,6 +1956,7 @@ int main(int argc, char *argv[])
   1.198  		/* If transactions ended, we might be able to do more work. */
   1.199  		unblock_connections();
   1.200  
   1.201 -		max = initialize_set(&inset, &outset, *sock,*ro_sock,event_fd);
   1.202 +		max = initialize_set(&inset, &outset, *sock, *ro_sock,
   1.203 +				     event_fd, xcs_fd);
   1.204  	}
   1.205  }
     2.1 --- a/tools/xenstore/xenstored_domain.c	Tue Sep 06 13:43:28 2005 +0000
     2.2 +++ b/tools/xenstore/xenstored_domain.c	Tue Sep 06 16:59:14 2005 +0000
     2.3 @@ -363,6 +363,21 @@ void do_release(struct connection *conn,
     2.4  	send_ack(conn, XS_RELEASE);
     2.5  }
     2.6  
     2.7 +void domain_cleanup(void)
     2.8 +{
     2.9 +	xc_dominfo_t dominfo;
    2.10 +	struct domain *domain, *tmp;
    2.11 +
    2.12 +	list_for_each_entry_safe(domain, tmp, &domains, list) {
    2.13 +		if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
    2.14 +				      &dominfo) == 1 &&
    2.15 +		    dominfo.domid == domain->domid &&
    2.16 +		    !dominfo.dying && !dominfo.crashed && !dominfo.shutdown)
    2.17 +			continue;
    2.18 +		talloc_free(domain->conn);
    2.19 +	}
    2.20 +}
    2.21 +
    2.22  void do_get_domain_path(struct connection *conn, const char *domid_str)
    2.23  {
    2.24  	struct domain *domain;
     3.1 --- a/tools/xenstore/xenstored_domain.h	Tue Sep 06 13:43:28 2005 +0000
     3.2 +++ b/tools/xenstore/xenstored_domain.h	Tue Sep 06 16:59:14 2005 +0000
     3.3 @@ -28,6 +28,10 @@ void do_introduce(struct connection *con
     3.4  /* domid */
     3.5  void do_release(struct connection *conn, const char *domid_str);
     3.6  
     3.7 +/* Enumerate domains and release connections for non-existant or dying
     3.8 + * domains. */
     3.9 +void domain_cleanup(void);
    3.10 +
    3.11  /* domid */
    3.12  void do_get_domain_path(struct connection *conn, const char *domid_str);
    3.13