ia64/xen-unstable

changeset 5871:997b2b07b96d

Change from bool indicating blocked to an enum: when watches go
synchronous this makes it easier (because then we have two reasons
to block)
Instead of using return value, use explicit state member inside
struct connection.
Signed-off-by: Rusty Russel <rusty@rustcorp.com.au>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Jul 26 15:13:56 2005 +0000 (2005-07-26)
parents 99366b44c421
children 4e833037159d
files tools/xenstore/xenstored_core.c tools/xenstore/xenstored_core.h tools/xenstore/xenstored_domain.c tools/xenstore/xenstored_domain.h tools/xenstore/xenstored_transaction.c tools/xenstore/xenstored_transaction.h tools/xenstore/xenstored_watch.c tools/xenstore/xenstored_watch.h
line diff
     1.1 --- a/tools/xenstore/xenstored_core.c	Tue Jul 26 15:09:43 2005 +0000
     1.2 +++ b/tools/xenstore/xenstored_core.c	Tue Jul 26 15:13:56 2005 +0000
     1.3 @@ -318,7 +318,7 @@ static int initialize_set(fd_set *inset,
     1.4  	list_for_each_entry(i, &connections, list) {
     1.5  		if (i->domain)
     1.6  			continue;
     1.7 -		if (!i->blocked)
     1.8 +		if (i->state == OK)
     1.9  			FD_SET(i->fd, inset);
    1.10  		if (i->out)
    1.11  			FD_SET(i->fd, outset);
    1.12 @@ -454,8 +454,7 @@ unsigned int get_strings(struct buffered
    1.13  	return i;
    1.14  }
    1.15  
    1.16 -/* Returns "false", meaning "connection is not blocked". */
    1.17 -bool send_reply(struct connection *conn, enum xsd_sockmsg_type type,
    1.18 +void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
    1.19  		const void *data, unsigned int len)
    1.20  {
    1.21  	struct buffered_data *bdata;
    1.22 @@ -476,16 +475,15 @@ bool send_reply(struct connection *conn,
    1.23  		conn->waiting_reply = bdata;
    1.24  	} else
    1.25  		conn->out = bdata;
    1.26 -	return false;
    1.27  }
    1.28  
    1.29  /* Some routines (write, mkdir, etc) just need a non-error return */
    1.30 -bool send_ack(struct connection *conn, enum xsd_sockmsg_type type)
    1.31 +void send_ack(struct connection *conn, enum xsd_sockmsg_type type)
    1.32  {
    1.33 -	return send_reply(conn, type, "OK", sizeof("OK"));
    1.34 +	send_reply(conn, type, "OK", sizeof("OK"));
    1.35  }
    1.36  
    1.37 -bool send_error(struct connection *conn, int error)
    1.38 +void send_error(struct connection *conn, int error)
    1.39  {
    1.40  	unsigned int i;
    1.41  
    1.42 @@ -494,7 +492,7 @@ bool send_error(struct connection *conn,
    1.43  			corrupt(conn, "Unknown error %i (%s)", error,
    1.44  				strerror(error));
    1.45  
    1.46 -	return send_reply(conn, XS_ERROR, xsd_errors[i].errstring,
    1.47 +	send_reply(conn, XS_ERROR, xsd_errors[i].errstring,
    1.48  			  strlen(xsd_errors[i].errstring) + 1);
    1.49  }
    1.50  
    1.51 @@ -780,7 +778,7 @@ bool check_node_perms(struct connection 
    1.52  	return false;
    1.53  }
    1.54  
    1.55 -static bool send_directory(struct connection *conn, const char *node)
    1.56 +static void send_directory(struct connection *conn, const char *node)
    1.57  {
    1.58  	char *path, *reply = talloc_strdup(node, "");
    1.59  	unsigned int reply_len = 0;
    1.60 @@ -788,13 +786,17 @@ static bool send_directory(struct connec
    1.61  	struct dirent *dirent;
    1.62  
    1.63  	node = canonicalize(conn, node);
    1.64 -	if (!check_node_perms(conn, node, XS_PERM_READ))
    1.65 -		return send_error(conn, errno);
    1.66 +	if (!check_node_perms(conn, node, XS_PERM_READ)) {
    1.67 +		send_error(conn, errno);
    1.68 +		return;
    1.69 +	}
    1.70  
    1.71  	path = node_dir(conn->transaction, node);
    1.72  	dir = talloc_opendir(path);
    1.73 -	if (!dir)
    1.74 -		return send_error(conn, errno);
    1.75 +	if (!dir) {
    1.76 +		send_error(conn, errno);
    1.77 +		return;
    1.78 +	}
    1.79  
    1.80  	while ((dirent = readdir(*dir)) != NULL) {
    1.81  		int len = strlen(dirent->d_name) + 1;
    1.82 @@ -807,32 +809,35 @@ static bool send_directory(struct connec
    1.83  		reply_len += len;
    1.84  	}
    1.85  
    1.86 -	return send_reply(conn, XS_DIRECTORY, reply, reply_len);
    1.87 +	send_reply(conn, XS_DIRECTORY, reply, reply_len);
    1.88  }
    1.89  
    1.90 -static bool do_read(struct connection *conn, const char *node)
    1.91 +static void do_read(struct connection *conn, const char *node)
    1.92  {
    1.93  	char *value;
    1.94  	unsigned int size;
    1.95  	int *fd;
    1.96  
    1.97  	node = canonicalize(conn, node);
    1.98 -	if (!check_node_perms(conn, node, XS_PERM_READ))
    1.99 -		return send_error(conn, errno);
   1.100 +	if (!check_node_perms(conn, node, XS_PERM_READ)) {
   1.101 +		send_error(conn, errno);
   1.102 +		return;
   1.103 +	}
   1.104  
   1.105  	fd = talloc_open(node_datafile(conn->transaction, node), O_RDONLY, 0);
   1.106  	if (!fd) {
   1.107  		/* Data file doesn't exist?  We call that a directory */
   1.108  		if (errno == ENOENT)
   1.109  			errno = EISDIR;
   1.110 -		return send_error(conn, errno);
   1.111 +		send_error(conn, errno);
   1.112 +		return;
   1.113  	}
   1.114  
   1.115  	value = read_all(fd, &size);
   1.116  	if (!value)
   1.117 -		return send_error(conn, errno);
   1.118 -
   1.119 -	return send_reply(conn, XS_READ, value, size);
   1.120 +		send_error(conn, errno);
   1.121 +	else
   1.122 +		send_reply(conn, XS_READ, value, size);
   1.123  }
   1.124  
   1.125  /* Create a new directory.  Optionally put data in it (if data != NULL) */
   1.126 @@ -876,7 +881,7 @@ static bool new_directory(struct connect
   1.127  }
   1.128  
   1.129  /* path, flags, data... */
   1.130 -static bool do_write(struct connection *conn, struct buffered_data *in)
   1.131 +static void do_write(struct connection *conn, struct buffered_data *in)
   1.132  {
   1.133  	unsigned int offset, datalen;
   1.134  	char *vec[2];
   1.135 @@ -885,16 +890,20 @@ static bool do_write(struct connection *
   1.136  	struct stat st;
   1.137  
   1.138  	/* Extra "strings" can be created by binary data. */
   1.139 -	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec))
   1.140 -		return send_error(conn, EINVAL);
   1.141 +	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
   1.142 +		send_error(conn, EINVAL);
   1.143 +		return;
   1.144 +	}
   1.145  
   1.146  	node = canonicalize(conn, vec[0]);
   1.147  	if (/*suppress error on write outside transaction*/ 0 &&
   1.148 -            !within_transaction(conn->transaction, node))
   1.149 -		return send_error(conn, EROFS);
   1.150 +	    !within_transaction(conn->transaction, node)) {
   1.151 +		send_error(conn, EROFS);
   1.152 +		return;
   1.153 +	}
   1.154  
   1.155  	if (transaction_block(conn, node))
   1.156 -		return true;
   1.157 +		return;
   1.158  
   1.159  	offset = strlen(vec[0]) + strlen(vec[1]) + 2;
   1.160  	datalen = in->used - offset;
   1.161 @@ -905,32 +914,46 @@ static bool do_write(struct connection *
   1.162  		mode = XS_PERM_WRITE|XS_PERM_CREATE;
   1.163  	else if (streq(vec[1], XS_WRITE_CREATE_EXCL))
   1.164  		mode = XS_PERM_WRITE|XS_PERM_CREATE;
   1.165 -	else
   1.166 -		return send_error(conn, EINVAL);
   1.167 +	else {
   1.168 +		send_error(conn, EINVAL);
   1.169 +		return;
   1.170 +	}
   1.171  
   1.172 -	if (!check_node_perms(conn, node, mode))
   1.173 -		return send_error(conn, errno);
   1.174 +	if (!check_node_perms(conn, node, mode)) {
   1.175 +		send_error(conn, errno);
   1.176 +		return;
   1.177 +	}
   1.178  
   1.179  	if (lstat(node_dir(conn->transaction, node), &st) != 0) {
   1.180  		/* Does not exist... */
   1.181 -		if (errno != ENOENT)
   1.182 -			return send_error(conn, errno);
   1.183 +		if (errno != ENOENT) {
   1.184 +			send_error(conn, errno);
   1.185 +			return;
   1.186 +		}
   1.187  
   1.188  		/* Not going to create it? */
   1.189 -		if (!(mode & XS_PERM_CREATE))
   1.190 -			return send_error(conn, ENOENT);
   1.191 +		if (!(mode & XS_PERM_CREATE)) {
   1.192 +			send_error(conn, ENOENT);
   1.193 +			return;
   1.194 +		}
   1.195  
   1.196 -		if (!new_directory(conn, node, in->buffer + offset, datalen))
   1.197 -			return send_error(conn, errno);
   1.198 +		if (!new_directory(conn, node, in->buffer + offset, datalen)) {
   1.199 +			send_error(conn, errno);
   1.200 +			return;
   1.201 +		}
   1.202  	} else {
   1.203  		/* Exists... */
   1.204 -		if (streq(vec[1], XS_WRITE_CREATE_EXCL))
   1.205 -			return send_error(conn, EEXIST);
   1.206 +		if (streq(vec[1], XS_WRITE_CREATE_EXCL)) {
   1.207 +			send_error(conn, EEXIST);
   1.208 +			return;
   1.209 +		}
   1.210  
   1.211  		tmppath = tempfile(node_datafile(conn->transaction, node),
   1.212  				   in->buffer + offset, datalen);
   1.213 -		if (!tmppath)
   1.214 -			return send_error(conn, errno);
   1.215 +		if (!tmppath) {
   1.216 +			send_error(conn, errno);
   1.217 +			return;
   1.218 +		}
   1.219  
   1.220  		commit_tempfile(tmppath);
   1.221  	}
   1.222 @@ -938,163 +961,196 @@ static bool do_write(struct connection *
   1.223  	add_change_node(conn->transaction, node, false);
   1.224  	send_ack(conn, XS_WRITE);
   1.225  	fire_watches(conn->transaction, node, false);
   1.226 -	return false;
   1.227  }
   1.228  
   1.229 -static bool do_mkdir(struct connection *conn, const char *node)
   1.230 +static void do_mkdir(struct connection *conn, const char *node)
   1.231  {
   1.232  	node = canonicalize(conn, node);
   1.233 -	if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_CREATE))
   1.234 -		return send_error(conn, errno);
   1.235 +	if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_CREATE)) {
   1.236 +		send_error(conn, errno);
   1.237 +		return;
   1.238 +	}
   1.239  
   1.240 -	if (!within_transaction(conn->transaction, node))
   1.241 -		return send_error(conn, EROFS);
   1.242 +	if (!within_transaction(conn->transaction, node)) {
   1.243 +		send_error(conn, EROFS);
   1.244 +		return;
   1.245 +	}
   1.246  
   1.247  	if (transaction_block(conn, node))
   1.248 -		return true;
   1.249 +		return;
   1.250  
   1.251 -	if (!new_directory(conn, node, NULL, 0))
   1.252 -		return send_error(conn, errno);
   1.253 +	if (!new_directory(conn, node, NULL, 0)) {
   1.254 +		send_error(conn, errno);
   1.255 +		return;
   1.256 +	}
   1.257  
   1.258  	add_change_node(conn->transaction, node, false);
   1.259  	send_ack(conn, XS_MKDIR);
   1.260  	fire_watches(conn->transaction, node, false);
   1.261 -	return false;
   1.262  }
   1.263  
   1.264 -static bool do_rm(struct connection *conn, const char *node)
   1.265 +static void do_rm(struct connection *conn, const char *node)
   1.266  {
   1.267  	char *tmppath, *path;
   1.268  
   1.269  	node = canonicalize(conn, node);
   1.270 -	if (!check_node_perms(conn, node, XS_PERM_WRITE))
   1.271 -		return send_error(conn, errno);
   1.272 +	if (!check_node_perms(conn, node, XS_PERM_WRITE)) {
   1.273 +		send_error(conn, errno);
   1.274 +		return;
   1.275 +	}
   1.276  
   1.277 -	if (!within_transaction(conn->transaction, node))
   1.278 -		return send_error(conn, EROFS);
   1.279 +	if (!within_transaction(conn->transaction, node)) {
   1.280 +		send_error(conn, EROFS);
   1.281 +		return;
   1.282 +	}
   1.283  
   1.284  	if (transaction_block(conn, node))
   1.285 -		return true;
   1.286 +		return;
   1.287  
   1.288 -	if (streq(node, "/"))
   1.289 -		return send_error(conn, EINVAL);
   1.290 +	if (streq(node, "/")) {
   1.291 +		send_error(conn, EINVAL);
   1.292 +		return;
   1.293 +	}
   1.294  
   1.295  	/* We move the directory to temporary name, destructor cleans up. */
   1.296  	path = node_dir(conn->transaction, node);
   1.297  	tmppath = talloc_asprintf(node, "%s.tmp", path);
   1.298  	talloc_set_destructor(tmppath, destroy_path);
   1.299  
   1.300 -	if (rename(path, tmppath) != 0)
   1.301 -		return send_error(conn, errno);
   1.302 +	if (rename(path, tmppath) != 0) {
   1.303 +		send_error(conn, errno);
   1.304 +		return;
   1.305 +	}
   1.306  
   1.307  	add_change_node(conn->transaction, node, true);
   1.308  	send_ack(conn, XS_RM);
   1.309  	fire_watches(conn->transaction, node, true);
   1.310 -	return false;
   1.311  }
   1.312  
   1.313 -static bool do_get_perms(struct connection *conn, const char *node)
   1.314 +static void do_get_perms(struct connection *conn, const char *node)
   1.315  {
   1.316  	struct xs_permissions *perms;
   1.317  	char *strings;
   1.318  	unsigned int len, num;
   1.319  
   1.320  	node = canonicalize(conn, node);
   1.321 -	if (!check_node_perms(conn, node, XS_PERM_READ))
   1.322 -		return send_error(conn, errno);
   1.323 +	if (!check_node_perms(conn, node, XS_PERM_READ)) {
   1.324 +		send_error(conn, errno);
   1.325 +		return;
   1.326 +	}
   1.327  
   1.328  	perms = get_perms(conn->transaction, node, &num);
   1.329 -	if (!perms)
   1.330 -		return send_error(conn, errno);
   1.331 +	if (!perms) {
   1.332 +		send_error(conn, errno);
   1.333 +		return;
   1.334 +	}
   1.335  
   1.336  	strings = perms_to_strings(node, perms, num, &len);
   1.337  	if (!strings)
   1.338 -		return send_error(conn, errno);
   1.339 -
   1.340 -	return send_reply(conn, XS_GET_PERMS, strings, len);
   1.341 +		send_error(conn, errno);
   1.342 +	else
   1.343 +		send_reply(conn, XS_GET_PERMS, strings, len);
   1.344  }
   1.345  
   1.346 -static bool do_set_perms(struct connection *conn, struct buffered_data *in)
   1.347 +static void do_set_perms(struct connection *conn, struct buffered_data *in)
   1.348  {
   1.349  	unsigned int num;
   1.350  	char *node;
   1.351  	struct xs_permissions *perms;
   1.352  
   1.353  	num = xs_count_strings(in->buffer, in->used);
   1.354 -	if (num < 2)
   1.355 -		return send_error(conn, EINVAL);
   1.356 +	if (num < 2) {
   1.357 +		send_error(conn, EINVAL);
   1.358 +		return;
   1.359 +	}
   1.360  
   1.361  	/* First arg is node name. */
   1.362  	node = canonicalize(conn, in->buffer);
   1.363  	in->buffer += strlen(in->buffer) + 1;
   1.364  	num--;
   1.365  
   1.366 -	if (!within_transaction(conn->transaction, node))
   1.367 -		return send_error(conn, EROFS);
   1.368 +	if (!within_transaction(conn->transaction, node)) {
   1.369 +		send_error(conn, EROFS);
   1.370 +		return;
   1.371 +	}
   1.372  
   1.373  	if (transaction_block(conn, node))
   1.374 -		return true;
   1.375 +		return;
   1.376  
   1.377  	/* We must own node to do this (tools can do this too). */
   1.378 -	if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_OWNER))
   1.379 -		return send_error(conn, errno);
   1.380 +	if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_OWNER)) {
   1.381 +		send_error(conn, errno);
   1.382 +		return;
   1.383 +	}
   1.384  
   1.385  	perms = talloc_array(node, struct xs_permissions, num);
   1.386 -	if (!xs_strings_to_perms(perms, num, in->buffer))
   1.387 -		return send_error(conn, errno);
   1.388 +	if (!xs_strings_to_perms(perms, num, in->buffer)) {
   1.389 +		send_error(conn, errno);
   1.390 +		return;
   1.391 +	}
   1.392  
   1.393 -	if (!set_perms(conn->transaction, node, perms, num))
   1.394 -		return send_error(conn, errno);
   1.395 +	if (!set_perms(conn->transaction, node, perms, num)) {
   1.396 +		send_error(conn, errno);
   1.397 +		return;
   1.398 +	}
   1.399 +
   1.400  	add_change_node(conn->transaction, node, false);
   1.401  	send_ack(conn, XS_SET_PERMS);
   1.402  	fire_watches(conn->transaction, node, false);
   1.403 -	return false;
   1.404  }
   1.405  
   1.406  /* Process "in" for conn: "in" will vanish after this conversation, so
   1.407   * we can talloc off it for temporary variables.  May free "conn".
   1.408 - * Returns true if can't complete due to block.
   1.409   */
   1.410 -static bool process_message(struct connection *conn, struct buffered_data *in)
   1.411 +static void process_message(struct connection *conn, struct buffered_data *in)
   1.412  {
   1.413  	switch (in->hdr.msg.type) {
   1.414  	case XS_DIRECTORY:
   1.415 -		return send_directory(conn, onearg(in));
   1.416 +		send_directory(conn, onearg(in));
   1.417 +		break;
   1.418  
   1.419  	case XS_READ:
   1.420 -		return do_read(conn, onearg(in));
   1.421 +		do_read(conn, onearg(in));
   1.422 +		break;
   1.423  
   1.424  	case XS_WRITE:
   1.425 -		return do_write(conn, in);
   1.426 +		do_write(conn, in);
   1.427 +		break;
   1.428  
   1.429  	case XS_MKDIR:
   1.430 -		return do_mkdir(conn, onearg(in));
   1.431 +		do_mkdir(conn, onearg(in));
   1.432 +		break;
   1.433  
   1.434  	case XS_RM:
   1.435 -		return do_rm(conn, onearg(in));
   1.436 +		do_rm(conn, onearg(in));
   1.437 +		break;
   1.438  
   1.439  	case XS_GET_PERMS:
   1.440 -		return do_get_perms(conn, onearg(in));
   1.441 +		do_get_perms(conn, onearg(in));
   1.442 +		break;
   1.443  
   1.444  	case XS_SET_PERMS:
   1.445 -		return do_set_perms(conn, in);
   1.446 +		do_set_perms(conn, in);
   1.447 +		break;
   1.448  
   1.449  	case XS_SHUTDOWN:
   1.450  		/* FIXME: Implement gentle shutdown too. */
   1.451  		/* Only tools can do this. */
   1.452 -		if (conn->id != 0)
   1.453 -			return send_error(conn, EACCES);
   1.454 -		if (!conn->can_write)
   1.455 -			return send_error(conn, EROFS);
   1.456 +		if (conn->id != 0) {
   1.457 +			send_error(conn, EACCES);
   1.458 +			break;
   1.459 +		}
   1.460 +		if (!conn->can_write) {
   1.461 +			send_error(conn, EROFS);
   1.462 +			break;
   1.463 +		}
   1.464  		send_ack(conn, XS_SHUTDOWN);
   1.465  		/* Everything hangs off auto-free context, freed at exit. */
   1.466  		exit(0);
   1.467  
   1.468  	case XS_DEBUG:
   1.469 -		if (streq(in->buffer, "print")) {
   1.470 +		if (streq(in->buffer, "print"))
   1.471  			xprintf("debug: %s", in->buffer + get_string(in, 0));
   1.472 -			return false;
   1.473 -		}
   1.474  #ifdef TESTING
   1.475  		/* For testing, we allow them to set id. */
   1.476  		if (streq(in->buffer, "setid")) {
   1.477 @@ -1107,37 +1163,44 @@ static bool process_message(struct conne
   1.478  			failtest = true;
   1.479  		}
   1.480  #endif /* TESTING */
   1.481 -		return false;
   1.482 +		break;
   1.483  
   1.484  	case XS_WATCH:
   1.485 -		return do_watch(conn, in);
   1.486 +		do_watch(conn, in);
   1.487 +		break;
   1.488  
   1.489  	case XS_WATCH_ACK:
   1.490 -		return do_watch_ack(conn, onearg(in));
   1.491 +		do_watch_ack(conn, onearg(in));
   1.492 +		break;
   1.493  
   1.494  	case XS_UNWATCH:
   1.495 -		return do_unwatch(conn, in);
   1.496 +		do_unwatch(conn, in);
   1.497 +		break;
   1.498  
   1.499  	case XS_TRANSACTION_START:
   1.500 -		return do_transaction_start(conn, onearg(in));
   1.501 +		do_transaction_start(conn, onearg(in));
   1.502 +		break;
   1.503  
   1.504  	case XS_TRANSACTION_END:
   1.505 -		return do_transaction_end(conn, onearg(in));
   1.506 +		do_transaction_end(conn, onearg(in));
   1.507 +		break;
   1.508  
   1.509  	case XS_INTRODUCE:
   1.510 -		return do_introduce(conn, in);
   1.511 +		do_introduce(conn, in);
   1.512 +		break;
   1.513  
   1.514  	case XS_RELEASE:
   1.515 -		return do_release(conn, onearg(in));
   1.516 +		do_release(conn, onearg(in));
   1.517 +		break;
   1.518  
   1.519  	case XS_GETDOMAINPATH:
   1.520 -		return do_get_domain_path(conn, onearg(in));
   1.521 +		do_get_domain_path(conn, onearg(in));
   1.522 +		break;
   1.523  
   1.524  	case XS_WATCH_EVENT:
   1.525  	default:
   1.526  		eprintf("Client unknown operation %i", in->hdr.msg.type);
   1.527  		send_error(conn, ENOSYS);
   1.528 -		return false;
   1.529  	}
   1.530  }
   1.531  
   1.532 @@ -1152,6 +1215,8 @@ static void consider_message(struct conn
   1.533  	enum xsd_sockmsg_type type = conn->in->hdr.msg.type;
   1.534  	jmp_buf talloc_fail;
   1.535  
   1.536 +	assert(conn->state == OK);
   1.537 +
   1.538  	/* For simplicity, we kill the connection on OOM. */
   1.539  	talloc_set_fail_handler(out_of_mem, &talloc_fail);
   1.540  	if (setjmp(talloc_fail)) {
   1.541 @@ -1174,7 +1239,9 @@ static void consider_message(struct conn
   1.542  	 */
   1.543  	in = talloc_steal(talloc_autofree_context(), conn->in);
   1.544  	conn->in = new_buffer(conn);
   1.545 -	if (process_message(conn, in)) {
   1.546 +	process_message(conn, in);
   1.547 +
   1.548 +	if (conn->state == BLOCKED) {
   1.549  		/* Blocked by transaction: queue for re-xmit. */
   1.550  		talloc_free(conn->in);
   1.551  		conn->in = in;
   1.552 @@ -1197,7 +1264,7 @@ void handle_input(struct connection *con
   1.553  	int bytes;
   1.554  	struct buffered_data *in;
   1.555  
   1.556 -	assert(!conn->blocked);
   1.557 +	assert(conn->state == OK);
   1.558  	in = conn->in;
   1.559  
   1.560  	/* Not finished header yet? */
   1.561 @@ -1254,12 +1321,13 @@ static void unblock_connections(void)
   1.562  	struct connection *i, *tmp;
   1.563  
   1.564  	list_for_each_entry_safe(i, tmp, &connections, list) {
   1.565 -		if (!i->blocked)
   1.566 +		if (i->state == OK)
   1.567  			continue;
   1.568  
   1.569 -		if (!transaction_covering_node(i->blocked)) {
   1.570 -			talloc_free(i->blocked);
   1.571 -			i->blocked = NULL;
   1.572 +		if (!transaction_covering_node(i->blocked_by)) {
   1.573 +			talloc_free(i->blocked_by);
   1.574 +			i->blocked_by = NULL;
   1.575 +			i->state = OK;
   1.576  			consider_message(i);
   1.577  		}
   1.578  	}
   1.579 @@ -1281,7 +1349,8 @@ struct connection *new_connection(connwr
   1.580  	if (!new)
   1.581  		return NULL;
   1.582  
   1.583 -	new->blocked = false;
   1.584 +	new->state = OK;
   1.585 +	new->blocked_by = NULL;
   1.586  	new->out = new->waiting_reply = NULL;
   1.587  	new->fd = -1;
   1.588  	new->id = 0;
   1.589 @@ -1358,10 +1427,14 @@ void dump_connection(void)
   1.590  
   1.591  	list_for_each_entry(i, &connections, list) {
   1.592  		printf("Connection %p:\n", i);
   1.593 +		printf("    state = %s\n",
   1.594 +		       i->state == OK ? "OK"
   1.595 +		       : i->state == BLOCKED ? "BLOCKED"
   1.596 +		       : "INVALID");
   1.597  		if (i->id)
   1.598  			printf("    id = %i\n", i->id);
   1.599 -		if (i->blocked)
   1.600 -			printf("    blocked on = %s\n", i->blocked);
   1.601 +		if (i->blocked_by)
   1.602 +			printf("    blocked on = %s\n", i->blocked_by);
   1.603  		if (i->waiting_for_ack)
   1.604  			printf("    waiting_for_ack TRUE\n");
   1.605  		if (!i->in->inhdr || i->in->used)
   1.606 @@ -1418,7 +1491,6 @@ static void setup_structure(void)
   1.607  	permfile = talloc_strdup(root, "/tool/xenstored");
   1.608  	if (!set_perms(NULL, permfile, &perms, 1))
   1.609  		barf_perror("Could not create permissions on %s", permfile);
   1.610 -
   1.611  	talloc_free(root);
   1.612  	if (mkdir(xs_daemon_transactions(), 0750) != 0)
   1.613  		barf_perror("Could not create transaction dir %s",
     2.1 --- a/tools/xenstore/xenstored_core.h	Tue Jul 26 15:09:43 2005 +0000
     2.2 +++ b/tools/xenstore/xenstored_core.h	Tue Jul 26 15:13:56 2005 +0000
     2.3 @@ -47,6 +47,14 @@ struct connection;
     2.4  typedef int connwritefn_t(struct connection *, const void *, unsigned int);
     2.5  typedef int connreadfn_t(struct connection *, void *, unsigned int);
     2.6  
     2.7 +enum state
     2.8 +{
     2.9 +	/* Blocked by transaction. */
    2.10 +	BLOCKED,
    2.11 +	/* Completed */
    2.12 +	OK,
    2.13 +};
    2.14 +
    2.15  struct connection
    2.16  {
    2.17  	struct list_head list;
    2.18 @@ -57,8 +65,11 @@ struct connection
    2.19  	/* Who am I?  0 for socket connections. */
    2.20  	domid_t id;
    2.21  
    2.22 -	/* Are we blocked waiting for a transaction to end?  Contains node. */
    2.23 -	char *blocked;
    2.24 +	/* Blocked on transaction? */
    2.25 +	enum state state;
    2.26 +
    2.27 +	/* Node we are waiting for (if state == BLOCKED) */
    2.28 +	char *blocked_by;
    2.29  
    2.30  	/* Is this a read-only connection? */
    2.31  	bool can_write;
    2.32 @@ -100,14 +111,14 @@ bool is_child(const char *child, const c
    2.33  /* Create a new buffer with lifetime of context. */
    2.34  struct buffered_data *new_buffer(void *ctx);
    2.35  
    2.36 -bool send_reply(struct connection *conn, enum xsd_sockmsg_type type,
    2.37 -                const void *data, unsigned int len);
    2.38 +void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
    2.39 +		const void *data, unsigned int len);
    2.40  
    2.41  /* Some routines (write, mkdir, etc) just need a non-error return */
    2.42 -bool send_ack(struct connection *conn, enum xsd_sockmsg_type type);
    2.43 +void send_ack(struct connection *conn, enum xsd_sockmsg_type type);
    2.44  
    2.45  /* Send an error: error is usually "errno". */
    2.46 -bool send_error(struct connection *conn, int error);
    2.47 +void send_error(struct connection *conn, int error);
    2.48  
    2.49  /* Canonicalize this path if possible. */
    2.50  char *canonicalize(struct connection *conn, const char *node);
     3.1 --- a/tools/xenstore/xenstored_domain.c	Tue Jul 26 15:09:43 2005 +0000
     3.2 +++ b/tools/xenstore/xenstored_domain.c	Tue Jul 26 15:13:56 2005 +0000
     3.3 @@ -239,7 +239,8 @@ void handle_event(int event_fd)
     3.4  	 * careful that handle_input/handle_output can destroy conn.
     3.5  	 */
     3.6  	while ((domain = find_domain(port)) != NULL) {
     3.7 -		if (!domain->conn->blocked && buffer_has_input(domain->input))
     3.8 +		if (domain->conn->state == OK
     3.9 +		    && buffer_has_input(domain->input))
    3.10  			handle_input(domain->conn);
    3.11  		else if (domain->conn->out
    3.12  			 && buffer_has_output_room(domain->output))
    3.13 @@ -287,33 +288,42 @@ static struct domain *new_domain(void *c
    3.14  }
    3.15  
    3.16  /* domid, mfn, evtchn, path */
    3.17 -bool do_introduce(struct connection *conn, struct buffered_data *in)
    3.18 +void do_introduce(struct connection *conn, struct buffered_data *in)
    3.19  {
    3.20  	struct domain *domain;
    3.21  	char *vec[4];
    3.22  
    3.23 -	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec))
    3.24 -		return send_error(conn, EINVAL);
    3.25 +	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
    3.26 +		send_error(conn, EINVAL);
    3.27 +		return;
    3.28 +	}
    3.29  
    3.30 -	if (conn->id != 0)
    3.31 -		return send_error(conn, EACCES);
    3.32 +	if (conn->id != 0) {
    3.33 +		send_error(conn, EACCES);
    3.34 +		return;
    3.35 +	}
    3.36  
    3.37 -	if (!conn->can_write)
    3.38 -		return send_error(conn, EROFS);
    3.39 +	if (!conn->can_write) {
    3.40 +		send_error(conn, EROFS);
    3.41 +		return;
    3.42 +	}
    3.43  
    3.44  	/* Sanity check args. */
    3.45 -	if ((atoi(vec[2]) <= 0) || !is_valid_nodename(vec[3]))
    3.46 -		return send_error(conn, EINVAL);
    3.47 +	if ((atoi(vec[2]) <= 0) || !is_valid_nodename(vec[3])) {
    3.48 +		send_error(conn, EINVAL);
    3.49 +		return;
    3.50 +	}
    3.51  	/* Hang domain off "in" until we're finished. */
    3.52  	domain = new_domain(in, atoi(vec[0]), atol(vec[1]), atol(vec[2]),
    3.53  			    vec[3]);
    3.54 -	if (!domain)
    3.55 -		return send_error(conn, errno);
    3.56 +	if (!domain) {
    3.57 +		send_error(conn, errno);
    3.58 +		return;
    3.59 +	}
    3.60  
    3.61  	/* Now domain belongs to its connection. */
    3.62  	talloc_steal(domain->conn, domain);
    3.63 -
    3.64 -	return send_ack(conn, XS_INTRODUCE);
    3.65 +	send_ack(conn, XS_INTRODUCE);
    3.66  }
    3.67  
    3.68  static struct domain *find_domain_by_domid(domid_t domid)
    3.69 @@ -328,39 +338,51 @@ static struct domain *find_domain_by_dom
    3.70  }
    3.71  
    3.72  /* domid */
    3.73 -bool do_release(struct connection *conn, const char *domid_str)
    3.74 +void do_release(struct connection *conn, const char *domid_str)
    3.75  {
    3.76  	struct domain *domain;
    3.77  	domid_t domid;
    3.78  
    3.79 -	if (!domid_str)
    3.80 -		return send_error(conn, EINVAL);
    3.81 +	if (!domid_str) {
    3.82 +		send_error(conn, EINVAL);
    3.83 +		return;
    3.84 +	}
    3.85  
    3.86  	domid = atoi(domid_str);
    3.87 -	if (!domid)
    3.88 -		return send_error(conn, EINVAL);
    3.89 +	if (!domid) {
    3.90 +		send_error(conn, EINVAL);
    3.91 +		return;
    3.92 +	}
    3.93  
    3.94 -	if (conn->id != 0)
    3.95 -		return send_error(conn, EACCES);
    3.96 +	if (conn->id != 0) {
    3.97 +		send_error(conn, EACCES);
    3.98 +		return;
    3.99 +	}
   3.100  
   3.101  	domain = find_domain_by_domid(domid);
   3.102 -	if (!domain)
   3.103 -		return send_error(conn, ENOENT);
   3.104 +	if (!domain) {
   3.105 +		send_error(conn, ENOENT);
   3.106 +		return;
   3.107 +	}
   3.108  
   3.109 -	if (!domain->conn)
   3.110 -		return send_error(conn, EINVAL);
   3.111 +	if (!domain->conn) {
   3.112 +		send_error(conn, EINVAL);
   3.113 +		return;
   3.114 +	}
   3.115  
   3.116  	talloc_free(domain->conn);
   3.117 -	return send_ack(conn, XS_RELEASE);
   3.118 +	send_ack(conn, XS_RELEASE);
   3.119  }
   3.120  
   3.121 -bool do_get_domain_path(struct connection *conn, const char *domid_str)
   3.122 +void do_get_domain_path(struct connection *conn, const char *domid_str)
   3.123  {
   3.124  	struct domain *domain;
   3.125  	domid_t domid;
   3.126  
   3.127 -	if (!domid_str)
   3.128 -		return send_error(conn, EINVAL);
   3.129 +	if (!domid_str) {
   3.130 +		send_error(conn, EINVAL);
   3.131 +		return;
   3.132 +	}
   3.133  
   3.134  	domid = atoi(domid_str);
   3.135  	if (domid == DOMID_SELF)
   3.136 @@ -368,11 +390,11 @@ bool do_get_domain_path(struct connectio
   3.137  	else
   3.138  		domain = find_domain_by_domid(domid);
   3.139  
   3.140 -	if (!domain)
   3.141 -		return send_error(conn, ENOENT);
   3.142 -
   3.143 -	return send_reply(conn, XS_GETDOMAINPATH, domain->path,
   3.144 -			  strlen(domain->path) + 1);
   3.145 +	if (!domain) 
   3.146 +		send_error(conn, ENOENT);
   3.147 +	else
   3.148 +		send_reply(conn, XS_GETDOMAINPATH, domain->path,
   3.149 +			   strlen(domain->path) + 1);
   3.150  }
   3.151  
   3.152  static int close_xc_handle(void *_handle)
     4.1 --- a/tools/xenstore/xenstored_domain.h	Tue Jul 26 15:09:43 2005 +0000
     4.2 +++ b/tools/xenstore/xenstored_domain.h	Tue Jul 26 15:13:56 2005 +0000
     4.3 @@ -23,13 +23,13 @@
     4.4  void handle_event(int event_fd);
     4.5  
     4.6  /* domid, mfn, eventchn, path */
     4.7 -bool do_introduce(struct connection *conn, struct buffered_data *in);
     4.8 +void do_introduce(struct connection *conn, struct buffered_data *in);
     4.9  
    4.10  /* domid */
    4.11 -bool do_release(struct connection *conn, const char *domid_str);
    4.12 +void do_release(struct connection *conn, const char *domid_str);
    4.13  
    4.14  /* domid */
    4.15 -bool do_get_domain_path(struct connection *conn, const char *domid_str);
    4.16 +void do_get_domain_path(struct connection *conn, const char *domid_str);
    4.17  
    4.18  /* Returns the event channel handle */
    4.19  int domain_init(void);
     5.1 --- a/tools/xenstore/xenstored_transaction.c	Tue Jul 26 15:09:43 2005 +0000
     5.2 +++ b/tools/xenstore/xenstored_transaction.c	Tue Jul 26 15:13:56 2005 +0000
     5.3 @@ -114,7 +114,8 @@ bool transaction_block(struct connection
     5.4  	trans = transaction_covering_node(node);
     5.5  	if (trans) {
     5.6  		start_transaction_timeout(trans);
     5.7 -		conn->blocked = talloc_strdup(conn, node);
     5.8 +		conn->state = BLOCKED;
     5.9 +		conn->blocked_by = talloc_strdup(conn, node);
    5.10  		return true;
    5.11  	}
    5.12  	return false;
    5.13 @@ -239,20 +240,24 @@ static bool copy_dir(const char *src, co
    5.14  	return true;
    5.15  }
    5.16  
    5.17 -bool do_transaction_start(struct connection *conn, const char *node)
    5.18 +void do_transaction_start(struct connection *conn, const char *node)
    5.19  {
    5.20  	struct transaction *transaction;
    5.21  	char *dir;
    5.22  
    5.23 -	if (conn->transaction)
    5.24 -		return send_error(conn, EBUSY);
    5.25 +	if (conn->transaction) {
    5.26 +		send_error(conn, EBUSY);
    5.27 +		return;
    5.28 +	}
    5.29  
    5.30  	node = canonicalize(conn, node);
    5.31 -	if (!check_node_perms(conn, node, XS_PERM_READ))
    5.32 -		return send_error(conn, errno);
    5.33 +	if (!check_node_perms(conn, node, XS_PERM_READ)) {
    5.34 +		send_error(conn, errno);
    5.35 +		return;
    5.36 +	}
    5.37  
    5.38  	if (transaction_block(conn, node))
    5.39 -		return true;
    5.40 +		return;
    5.41  
    5.42  	dir = node_dir_outside_transaction(node);
    5.43  
    5.44 @@ -270,12 +275,14 @@ bool do_transaction_start(struct connect
    5.45  	talloc_set_destructor(transaction, destroy_transaction);
    5.46  	trace_create(transaction, "transaction");
    5.47  
    5.48 -	if (!copy_dir(dir, transaction->divert))
    5.49 -		return send_error(conn, errno);
    5.50 +	if (!copy_dir(dir, transaction->divert)) {
    5.51 +		send_error(conn, errno);
    5.52 +		return;
    5.53 +	}
    5.54  
    5.55  	talloc_steal(conn, transaction);
    5.56  	conn->transaction = transaction;
    5.57 -	return send_ack(transaction->conn, XS_TRANSACTION_START);
    5.58 +	send_ack(transaction->conn, XS_TRANSACTION_START);
    5.59  }
    5.60  
    5.61  static bool commit_transaction(struct transaction *trans)
    5.62 @@ -301,13 +308,17 @@ static bool commit_transaction(struct tr
    5.63  	return true;
    5.64  }
    5.65  
    5.66 -bool do_transaction_end(struct connection *conn, const char *arg)
    5.67 +void do_transaction_end(struct connection *conn, const char *arg)
    5.68  {
    5.69 -	if (!arg || (!streq(arg, "T") && !streq(arg, "F")))
    5.70 -		return send_error(conn, EINVAL);
    5.71 +	if (!arg || (!streq(arg, "T") && !streq(arg, "F"))) {
    5.72 +		send_error(conn, EINVAL);
    5.73 +		return;
    5.74 +	}
    5.75  
    5.76 -	if (!conn->transaction)
    5.77 -		return send_error(conn, ENOENT);
    5.78 +	if (!conn->transaction) {
    5.79 +		send_error(conn, ENOENT);
    5.80 +		return;
    5.81 +	}
    5.82  
    5.83  	if (streq(arg, "T")) {
    5.84  		if (conn->transaction->destined_to_fail) {
    5.85 @@ -322,11 +333,11 @@ bool do_transaction_end(struct connectio
    5.86  
    5.87  	talloc_free(conn->transaction);
    5.88  	conn->transaction = NULL;
    5.89 -	return send_ack(conn, XS_TRANSACTION_END);
    5.90 +	send_ack(conn, XS_TRANSACTION_END);
    5.91 +	return;
    5.92  
    5.93  failed:
    5.94  	talloc_free(conn->transaction);
    5.95  	conn->transaction = NULL;
    5.96 -	return false;
    5.97  }
    5.98  
     6.1 --- a/tools/xenstore/xenstored_transaction.h	Tue Jul 26 15:09:43 2005 +0000
     6.2 +++ b/tools/xenstore/xenstored_transaction.h	Tue Jul 26 15:13:56 2005 +0000
     6.3 @@ -22,8 +22,8 @@
     6.4  
     6.5  struct transaction;
     6.6  
     6.7 -bool do_transaction_start(struct connection *conn, const char *node);
     6.8 -bool do_transaction_end(struct connection *conn, const char *arg);
     6.9 +void do_transaction_start(struct connection *conn, const char *node);
    6.10 +void do_transaction_end(struct connection *conn, const char *arg);
    6.11  
    6.12  /* Is node covered by this transaction? */
    6.13  bool within_transaction(struct transaction *trans, const char *node);
     7.1 --- a/tools/xenstore/xenstored_watch.c	Tue Jul 26 15:09:43 2005 +0000
     7.2 +++ b/tools/xenstore/xenstored_watch.c	Tue Jul 26 15:13:56 2005 +0000
     7.3 @@ -310,19 +310,23 @@ void check_watch_ack_timeout(void)
     7.4  	}
     7.5  }
     7.6  
     7.7 -bool do_watch(struct connection *conn, struct buffered_data *in)
     7.8 +void do_watch(struct connection *conn, struct buffered_data *in)
     7.9  {
    7.10  	struct watch *watch;
    7.11  	char *vec[3];
    7.12  	bool relative;
    7.13  
    7.14 -	if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
    7.15 -		return send_error(conn, EINVAL);
    7.16 +	if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec)) {
    7.17 +		send_error(conn, EINVAL);
    7.18 +		return;
    7.19 +	}
    7.20  
    7.21  	relative = !strstarts(vec[0], "/");
    7.22  	vec[0] = canonicalize(conn, vec[0]);
    7.23 -	if (!check_node_perms(conn, vec[0], XS_PERM_READ))
    7.24 -		return send_error(conn, errno);
    7.25 +	if (!check_node_perms(conn, vec[0], XS_PERM_READ)) {
    7.26 +		send_error(conn, errno);
    7.27 +		return;
    7.28 +	}
    7.29  
    7.30  	watch = talloc(conn, struct watch);
    7.31  	watch->node = talloc_strdup(watch, vec[0]);
    7.32 @@ -335,18 +339,22 @@ bool do_watch(struct connection *conn, s
    7.33  	insert_watch(watch);
    7.34  	talloc_set_destructor(watch, destroy_watch);
    7.35  	trace_create(watch, "watch");
    7.36 -	return send_ack(conn, XS_WATCH);
    7.37 +	send_ack(conn, XS_WATCH);
    7.38  }
    7.39  
    7.40 -bool do_watch_ack(struct connection *conn, const char *token)
    7.41 +void do_watch_ack(struct connection *conn, const char *token)
    7.42  {
    7.43  	struct watch_event *event;
    7.44  
    7.45 -	if (!token)
    7.46 -		return send_error(conn, EINVAL);
    7.47 +	if (!token) {
    7.48 +		send_error(conn, EINVAL);
    7.49 +		return;
    7.50 +	}
    7.51  
    7.52 -	if (!conn->waiting_for_ack)
    7.53 -		return send_error(conn, ENOENT);
    7.54 +	if (!conn->waiting_for_ack) {
    7.55 +		send_error(conn, ENOENT);
    7.56 +		return;
    7.57 +	}
    7.58  
    7.59  	event = list_top(&conn->waiting_for_ack->events,
    7.60  			 struct watch_event, list);
    7.61 @@ -354,21 +362,24 @@ bool do_watch_ack(struct connection *con
    7.62  	if (!streq(conn->waiting_for_ack->token, token)) {
    7.63  		/* They're confused: this will cause us to send event again */
    7.64  		conn->waiting_for_ack = NULL;
    7.65 -		return send_error(conn, EINVAL);
    7.66 +		send_error(conn, EINVAL);
    7.67 +		return;
    7.68  	}
    7.69  
    7.70  	move_event_onwards(event);
    7.71  	conn->waiting_for_ack = NULL;
    7.72 -	return send_ack(conn, XS_WATCH_ACK);
    7.73 +	send_ack(conn, XS_WATCH_ACK);
    7.74  }
    7.75  
    7.76 -bool do_unwatch(struct connection *conn, struct buffered_data *in)
    7.77 +void do_unwatch(struct connection *conn, struct buffered_data *in)
    7.78  {
    7.79  	struct watch *watch;
    7.80  	char *node, *vec[2];
    7.81  
    7.82 -	if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
    7.83 -		return send_error(conn, EINVAL);
    7.84 +	if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec)) {
    7.85 +		send_error(conn, EINVAL);
    7.86 +		return;
    7.87 +	}
    7.88  
    7.89  	/* We don't need to worry if we're waiting for an ack for the
    7.90  	 * watch we're deleting: conn->waiting_for_ack was reset by
    7.91 @@ -380,10 +391,11 @@ bool do_unwatch(struct connection *conn,
    7.92  
    7.93  		if (streq(watch->node, node) && streq(watch->token, vec[1])) {
    7.94  			talloc_free(watch);
    7.95 -			return send_ack(conn, XS_UNWATCH);
    7.96 +			send_ack(conn, XS_UNWATCH);
    7.97 +			return;
    7.98  		}
    7.99  	}
   7.100 -	return send_error(conn, ENOENT);
   7.101 +	send_error(conn, ENOENT);
   7.102  }
   7.103  
   7.104  #ifdef TESTING
     8.1 --- a/tools/xenstore/xenstored_watch.h	Tue Jul 26 15:09:43 2005 +0000
     8.2 +++ b/tools/xenstore/xenstored_watch.h	Tue Jul 26 15:13:56 2005 +0000
     8.3 @@ -22,9 +22,9 @@
     8.4  
     8.5  #include "xenstored_core.h"
     8.6  
     8.7 -bool do_watch(struct connection *conn, struct buffered_data *in);
     8.8 -bool do_watch_ack(struct connection *conn, const char *token);
     8.9 -bool do_unwatch(struct connection *conn, struct buffered_data *in);
    8.10 +void do_watch(struct connection *conn, struct buffered_data *in);
    8.11 +void do_watch_ack(struct connection *conn, const char *token);
    8.12 +void do_unwatch(struct connection *conn, struct buffered_data *in);
    8.13  
    8.14  /* Is this a watch event message for this connection? */
    8.15  bool is_watch_event(struct connection *conn, struct buffered_data *out);