ia64/xen-unstable

changeset 7307:bea563754fe6

When a domain is introduced to xenstored, check whether this has already
happened, and only return EINVAL if the event channel details have changed.
This allows Xend to introduce domains when it starts without having to be
concerned about whether xenstored has restarted at the same time. This
behaviour used to be subsumed by the bind_interdomain semantics for existing
channels, but in the simplification of that interface, the check must now move
to userspace.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Mon Oct 10 19:04:03 2005 +0100 (2005-10-10)
parents 7a48bfd1aba6
children 0f33cbec4e36
files tools/xenstore/xenstored_domain.c
line diff
     1.1 --- a/tools/xenstore/xenstored_domain.c	Mon Oct 10 18:59:57 2005 +0100
     1.2 +++ b/tools/xenstore/xenstored_domain.c	Mon Oct 10 19:04:03 2005 +0100
     1.3 @@ -53,6 +53,14 @@ struct domain
     1.4  	/* Event channel port */
     1.5  	u16 port;
     1.6  
     1.7 +	/* The remote end of the event channel, used only to validate
     1.8 +	   repeated domain introductions. */
     1.9 +	u16 remote_port;
    1.10 +
    1.11 +	/* The mfn associated with the event channel, used only to validate
    1.12 +	   repeated domain introductions. */
    1.13 +	unsigned long mfn;
    1.14 +
    1.15  	/* Domain path in store. */
    1.16  	char *path;
    1.17  
    1.18 @@ -322,14 +330,35 @@ static struct domain *new_domain(void *c
    1.19  	domain->port = rc;
    1.20  	domain->conn = new_connection(writechn, readchn);
    1.21  	domain->conn->domain = domain;
    1.22 +
    1.23 +	domain->remote_port = port;
    1.24 +	domain->mfn = mfn;
    1.25 +
    1.26  	return domain;
    1.27  }
    1.28  
    1.29 +
    1.30 +static struct domain *find_domain_by_domid(domid_t domid)
    1.31 +{
    1.32 +	struct domain *i;
    1.33 +
    1.34 +	list_for_each_entry(i, &domains, list) {
    1.35 +		if (i->domid == domid)
    1.36 +			return i;
    1.37 +	}
    1.38 +	return NULL;
    1.39 +}
    1.40 +
    1.41 +
    1.42  /* domid, mfn, evtchn, path */
    1.43  void do_introduce(struct connection *conn, struct buffered_data *in)
    1.44  {
    1.45  	struct domain *domain;
    1.46  	char *vec[4];
    1.47 +	domid_t domid;
    1.48 +	unsigned long mfn;
    1.49 +	u16 port;
    1.50 +	const char *path;
    1.51  
    1.52  	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
    1.53  		send_error(conn, EINVAL);
    1.54 @@ -341,38 +370,46 @@ void do_introduce(struct connection *con
    1.55  		return;
    1.56  	}
    1.57  
    1.58 +	domid = atoi(vec[0]);
    1.59 +	mfn = atol(vec[1]);
    1.60 +	port = atoi(vec[2]);
    1.61 +	path = vec[3];
    1.62 +
    1.63  	/* Sanity check args. */
    1.64 -	if ((atoi(vec[2]) <= 0) || !is_valid_nodename(vec[3])) {
    1.65 +	if ((port <= 0) || !is_valid_nodename(path)) {
    1.66  		send_error(conn, EINVAL);
    1.67  		return;
    1.68  	}
    1.69 -	/* Hang domain off "in" until we're finished. */
    1.70 -	domain = new_domain(in, atoi(vec[0]), atol(vec[1]), atol(vec[2]),
    1.71 -			    vec[3]);
    1.72 -	if (!domain) {
    1.73 -		send_error(conn, errno);
    1.74 -		return;
    1.75 -	}
    1.76  
    1.77 -	/* Now domain belongs to its connection. */
    1.78 -	talloc_steal(domain->conn, domain);
    1.79 +	domain = find_domain_by_domid(domid);
    1.80 +
    1.81 +	if (domain == NULL) {
    1.82 +		/* Hang domain off "in" until we're finished. */
    1.83 +		domain = new_domain(in, domid, mfn, port, path);
    1.84 +		if (!domain) {
    1.85 +			send_error(conn, errno);
    1.86 +			return;
    1.87 +		}
    1.88 +
    1.89 +		/* Now domain belongs to its connection. */
    1.90 +		talloc_steal(domain->conn, domain);
    1.91  
    1.92 -	fire_watches(conn, "@introduceDomain", false);
    1.93 +		fire_watches(conn, "@introduceDomain", false);
    1.94 +	}
    1.95 +	else {
    1.96 +		/* Check that the given details match the ones we have
    1.97 +		   previously recorded. */
    1.98 +		if (port != domain->remote_port ||
    1.99 +		    mfn != domain->mfn ||
   1.100 +		    strcmp(path, domain->path) != 0) {
   1.101 +			send_error(conn, EINVAL);
   1.102 +			return;
   1.103 +		}
   1.104 +	}
   1.105  
   1.106  	send_ack(conn, XS_INTRODUCE);
   1.107  }
   1.108  
   1.109 -static struct domain *find_domain_by_domid(domid_t domid)
   1.110 -{
   1.111 -	struct domain *i;
   1.112 -
   1.113 -	list_for_each_entry(i, &domains, list) {
   1.114 -		if (i->domid == domid)
   1.115 -			return i;
   1.116 -	}
   1.117 -	return NULL;
   1.118 -}
   1.119 -
   1.120  /* domid */
   1.121  void do_release(struct connection *conn, const char *domid_str)
   1.122  {