ia64/xen-unstable

changeset 5870:99366b44c421

Test and fix acknowedge_watch from returning EINVAL.
Also ensure that daemon re-xmits event if they ack wrong thing
(otherwise confused clients get stuck, as we will send no more
data while awaiting ack).
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:09:43 2005 +0000 (2005-07-26)
parents f9a3f32a129b
children 997b2b07b96d
files tools/xenstore/testsuite/13watch-ack.sh tools/xenstore/xenstored_core.c tools/xenstore/xenstored_core.h tools/xenstore/xenstored_watch.c
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/xenstore/testsuite/13watch-ack.sh	Tue Jul 26 15:09:43 2005 +0000
     1.3 @@ -0,0 +1,22 @@
     1.4 +#! /bin/sh
     1.5 +
     1.6 +# This demonstrates a bug where an xs_acknowledge_watch returns
     1.7 +# EINVAL, because the daemon doesn't track what watch event it sent
     1.8 +# and relies on it being the "first" watch which has an event.
     1.9 +# Watches firing after the first event is sent out will change this.
    1.10 +
    1.11 +# Create three things to watch.
    1.12 +echo mkdir /test | ./xs_test
    1.13 +echo mkdir /test/1 | ./xs_test
    1.14 +echo mkdir /test/2 | ./xs_test
    1.15 +echo mkdir /test/3 | ./xs_test
    1.16 +
    1.17 +# Watch all three, fire event on 2, read watch, fire event on 1 and 3, ack 2.
    1.18 +[ "`echo '1 watch /test/1 token1 0
    1.19 +1 watch /test/2 token2 0
    1.20 +1 watch /test/3 token3 0
    1.21 +2 write /test/2 create contents2
    1.22 +1 waitwatch
    1.23 +2 write /test/1 create contents1
    1.24 +2 write /test/3 create contents3
    1.25 +1 ackwatch token2' | ./xs_test 2>&1`" = "1:/test/2:token2" ]
     2.1 --- a/tools/xenstore/xenstored_core.c	Tue Jul 26 15:08:22 2005 +0000
     2.2 +++ b/tools/xenstore/xenstored_core.c	Tue Jul 26 15:09:43 2005 +0000
     2.3 @@ -1166,7 +1166,7 @@ static void consider_message(struct conn
     2.4  	/* We might get a command while waiting for an ack: this means
     2.5  	 * the other end discarded it: we will re-transmit. */
     2.6  	if (type != XS_WATCH_ACK)
     2.7 -		conn->waiting_for_ack = false;
     2.8 +		conn->waiting_for_ack = NULL;
     2.9  
    2.10  	/* Careful: process_message may free connection.  We detach
    2.11  	 * "in" beforehand and allocate the new buffer to avoid
     3.1 --- a/tools/xenstore/xenstored_core.h	Tue Jul 26 15:08:22 2005 +0000
     3.2 +++ b/tools/xenstore/xenstored_core.h	Tue Jul 26 15:09:43 2005 +0000
     3.3 @@ -64,7 +64,7 @@ struct connection
     3.4  	bool can_write;
     3.5  
     3.6  	/* Are we waiting for a watch event ack? */
     3.7 -	bool waiting_for_ack;
     3.8 +	struct watch *waiting_for_ack;
     3.9  
    3.10  	/* Buffered incoming data. */
    3.11  	struct buffered_data *in;
     4.1 --- a/tools/xenstore/xenstored_watch.c	Tue Jul 26 15:08:22 2005 +0000
     4.2 +++ b/tools/xenstore/xenstored_watch.c	Tue Jul 26 15:09:43 2005 +0000
     4.3 @@ -102,7 +102,7 @@ void queue_next_event(struct connection 
     4.4  	if (conn->waiting_reply) {
     4.5  		conn->out = conn->waiting_reply;
     4.6  		conn->waiting_reply = NULL;
     4.7 -		conn->waiting_for_ack = false;
     4.8 +		conn->waiting_for_ack = NULL;
     4.9  		return;
    4.10  	}
    4.11  
    4.12 @@ -115,7 +115,7 @@ void queue_next_event(struct connection 
    4.13  		return;
    4.14  
    4.15  	/* If we decide to cancel, we will reset this. */
    4.16 -	conn->waiting_for_ack = true;
    4.17 +	conn->waiting_for_ack = event->watches[0];
    4.18  
    4.19  	/* If we deleted /foo and they're watching /foo/bar, that's what we
    4.20  	 * tell them has changed. */
    4.21 @@ -348,12 +348,17 @@ bool do_watch_ack(struct connection *con
    4.22  	if (!conn->waiting_for_ack)
    4.23  		return send_error(conn, ENOENT);
    4.24  
    4.25 -	event = get_first_event(conn);
    4.26 -	if (!streq(event->watches[0]->token, token))
    4.27 +	event = list_top(&conn->waiting_for_ack->events,
    4.28 +			 struct watch_event, list);
    4.29 +	assert(event->watches[0] == conn->waiting_for_ack);
    4.30 +	if (!streq(conn->waiting_for_ack->token, token)) {
    4.31 +		/* They're confused: this will cause us to send event again */
    4.32 +		conn->waiting_for_ack = NULL;
    4.33  		return send_error(conn, EINVAL);
    4.34 +	}
    4.35  
    4.36  	move_event_onwards(event);
    4.37 -	conn->waiting_for_ack = false;
    4.38 +	conn->waiting_for_ack = NULL;
    4.39  	return send_ack(conn, XS_WATCH_ACK);
    4.40  }
    4.41