mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
Fire watches once immediately upon registration.
It matches the model of programming used to avoid races with watches, and also makes re-establishing watches on daemon restart easier. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
This commit is contained in:
1 parent
e7dcd2ce65
commit
e83a8e7c2b
10 files changed
+28
-18
No files matched your search
@@ -228,6 +228,7 @@ static int blkback_probe(struct xenbus_device *dev,
|
||||
be->dev = dev;
|
||||
be->backend_watch.node = dev->nodename;
|
||||
be->backend_watch.callback = backend_changed;
|
||||
/* Will implicitly call backend_changed once. */
|
||||
err = register_xenbus_watch(&be->backend_watch);
|
||||
if (err) {
|
||||
be->backend_watch.node = NULL;
|
||||
@@ -249,8 +250,6 @@ static int blkback_probe(struct xenbus_device *dev,
|
||||
}
|
||||
|
||||
dev->data = be;
|
||||
|
||||
backend_changed(&be->backend_watch, dev->nodename);
|
||||
return 0;
|
||||
|
||||
free_be:
|
||||
|
||||
@@ -172,6 +172,7 @@ static int blkback_probe(struct xenbus_device *dev,
|
||||
be->dev = dev;
|
||||
be->backend_watch.node = dev->nodename;
|
||||
be->backend_watch.callback = backend_changed;
|
||||
/* Registration implicitly fires backend_changed once */
|
||||
err = register_xenbus_watch(&be->backend_watch);
|
||||
if (err) {
|
||||
be->backend_watch.node = NULL;
|
||||
@@ -193,8 +194,6 @@ static int blkback_probe(struct xenbus_device *dev,
|
||||
}
|
||||
|
||||
dev->data = be;
|
||||
|
||||
backend_changed(&be->backend_watch, dev->nodename);
|
||||
return 0;
|
||||
|
||||
free_be:
|
||||
|
||||
@@ -242,6 +242,7 @@ static int netback_probe(struct xenbus_device *dev,
|
||||
be->dev = dev;
|
||||
be->backend_watch.node = dev->nodename;
|
||||
be->backend_watch.callback = backend_changed;
|
||||
/* Registration implicitly calls backend_changed. */
|
||||
err = register_xenbus_watch(&be->backend_watch);
|
||||
if (err) {
|
||||
be->backend_watch.node = NULL;
|
||||
@@ -263,8 +264,6 @@ static int netback_probe(struct xenbus_device *dev,
|
||||
}
|
||||
|
||||
dev->data = be;
|
||||
|
||||
backend_changed(&be->backend_watch, dev->nodename);
|
||||
return 0;
|
||||
|
||||
free_be:
|
||||
|
||||
@@ -1284,10 +1284,6 @@ static int netfront_probe(struct xenbus_device *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Call once in case entries already there. */
|
||||
watch_for_status(&info->watch, info->watch.node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -213,6 +213,7 @@ static int tpmback_probe(struct xenbus_device *dev,
|
||||
|
||||
be->dev = dev;
|
||||
be->backend_watch.node = dev->nodename;
|
||||
/* Implicitly calls backend_changed() once. */
|
||||
be->backend_watch.callback = backend_changed;
|
||||
be->instance = -1;
|
||||
err = register_xenbus_watch(&be->backend_watch);
|
||||
@@ -236,8 +237,6 @@ static int tpmback_probe(struct xenbus_device *dev,
|
||||
}
|
||||
|
||||
dev->data = be;
|
||||
|
||||
backend_changed(&be->backend_watch, dev->nodename);
|
||||
return err;
|
||||
|
||||
free_be:
|
||||
|
||||
@@ -411,7 +411,6 @@ static int tpmfront_probe(struct xenbus_device *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
watch_for_status(&info->watch, info->watch.node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,10 +168,12 @@ expect 1: waitwatch failed: Connection timed out
|
||||
# Watch event must have happened before we registered interest.
|
||||
1 watch / token
|
||||
2 write /test/subnode contents2
|
||||
1 watch / token2 0
|
||||
1 watchnoack / token2 0
|
||||
expect 1:/test/subnode:token
|
||||
1 waitwatch
|
||||
1 ackwatch token
|
||||
expect 1:/:token2
|
||||
1 waitwatch
|
||||
expect 1: waitwatch failed: Connection timed out
|
||||
1 waitwatch
|
||||
1 close
|
||||
|
||||
@@ -23,7 +23,8 @@ expect *Permission denied
|
||||
getperm /dir/file
|
||||
expect *Permission denied
|
||||
setperm /dir/file 0 NONE
|
||||
watch /dir/file token
|
||||
# We get no watch event when there's no permission. It's a corner case.
|
||||
watchnoack /dir/file token
|
||||
1 write /dir/file contents
|
||||
1 rm /dir/file
|
||||
expect waitwatch failed: Connection timed out
|
||||
@@ -63,7 +64,7 @@ expect *Permission denied
|
||||
getperm /dir/file
|
||||
expect *Permission denied
|
||||
setperm /dir/file 0 NONE
|
||||
watch /dir/file token
|
||||
watchnoack /dir/file token
|
||||
1 write /dir/file contents
|
||||
1 rm /dir/file
|
||||
expect waitwatch failed: Connection timed out
|
||||
|
||||
@@ -236,6 +236,9 @@ void do_watch(struct connection *conn, struct buffered_data *in)
|
||||
trace_create(watch, "watch");
|
||||
talloc_set_destructor(watch, destroy_watch);
|
||||
send_ack(conn, XS_WATCH);
|
||||
|
||||
/* We fire once up front: simplifies clients and restart. */
|
||||
add_event(conn, watch, watch->node);
|
||||
}
|
||||
|
||||
void do_watch_ack(struct connection *conn, const char *token)
|
||||
|
||||
@@ -200,6 +200,7 @@ static void __attribute__((noreturn)) usage(void)
|
||||
" setperm <path> <id> <flags> ...\n"
|
||||
" shutdown\n"
|
||||
" watch <path> <token>\n"
|
||||
" watchnoack <path> <token>\n"
|
||||
" waitwatch\n"
|
||||
" ackwatch <token>\n"
|
||||
" unwatch <path> <token>\n"
|
||||
@@ -480,10 +481,20 @@ static void do_shutdown(unsigned int handle)
|
||||
failed(handle);
|
||||
}
|
||||
|
||||
static void do_watch(unsigned int handle, const char *node, const char *token)
|
||||
static void do_watch(unsigned int handle, const char *node, const char *token,
|
||||
bool swallow_event)
|
||||
{
|
||||
if (!xs_watch(handles[handle], node, token))
|
||||
failed(handle);
|
||||
|
||||
/* Convenient for testing... */
|
||||
if (swallow_event) {
|
||||
char **vec = xs_read_watch(handles[handle]);
|
||||
if (!vec || !streq(vec[0], node) || !streq(vec[1], token))
|
||||
failed(handle);
|
||||
if (!xs_acknowledge_watch(handles[handle], token))
|
||||
failed(handle);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_timeout(void)
|
||||
@@ -767,7 +778,9 @@ static void do_command(unsigned int default_handle, char *line)
|
||||
else if (streq(command, "shutdown"))
|
||||
do_shutdown(handle);
|
||||
else if (streq(command, "watch"))
|
||||
do_watch(handle, arg(line, 1), arg(line, 2));
|
||||
do_watch(handle, arg(line, 1), arg(line, 2), true);
|
||||
else if (streq(command, "watchnoack"))
|
||||
do_watch(handle, arg(line, 1), arg(line, 2), false);
|
||||
else if (streq(command, "waitwatch"))
|
||||
do_waitwatch(handle);
|
||||
else if (streq(command, "ackwatch"))
|
||||
|
||||