From: Rusty Russell <rusty@rustcorp.com.au>
To: Keir Fraser <Keir.Fraser@cl.cam.ac.uk>
Cc: xen-devel List <xen-devel@lists.xensource.com>,
Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
Subject: Re: /proc/xen/xenbus supports watch?
Date: Tue, 27 Sep 2005 16:48:10 +1000 [thread overview]
Message-ID: <1127803690.7703.81.camel@localhost.localdomain> (raw)
In-Reply-To: <9d854deef18181141747d60fc1310462@cl.cam.ac.uk>
On Mon, 2005-09-26 at 20:30 +0100, Keir Fraser wrote:
> On 26 Sep 2005, at 19:51, Christian Limpach wrote:
>
> >>> Since we
> >>> need to add some kind of transaction identifier to the interface
> >>> to support this, we should make this change now.
> >>
> >> Or, alternately, since we don't need it, we shouldn't.
> >
> > I think we need them since it's the simplest solution to the whole
> > multi-page/multi-connection issue for a saner xenbus_dev
> > implementation:
> > - lock only held around xs_talkv
> > - transaction ids
> > - single point for demultiplexing watch events
>
> This is precisely how I expected that xenbus was going to be structured
> in the first place. It seems the simplest, most natural implementation
> and happens to avoid a lot of potential unnecessary blocking and
> serialisation. And not even at much cost in xenstored (how hard can the
> demultiplex be?).
Well, here's the simple patch that modifies introductions to allow the
domain to introduce new pages, and another one that tests it. I'm away
for the next week and a half on other stuff, then I'm in Cambridge.
Modifying the xenbus dev to use this should be fairly easy, if you
choose to go this route.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
diff -r 0e368f851f6a tools/python/xen/lowlevel/xs/xs.c
--- a/tools/python/xen/lowlevel/xs/xs.c Tue Sep 27 00:55:56 2005
+++ b/tools/python/xen/lowlevel/xs/xs.c Tue Sep 27 16:36:19 2005
@@ -728,7 +728,7 @@
&dom))
goto exit;
Py_BEGIN_ALLOW_THREADS
- xsval = xs_release_domain(xh, dom);
+ xsval = xs_release_domain(xh, dom, 0);
Py_END_ALLOW_THREADS
if (!xsval) {
PyErr_SetFromErrno(PyExc_RuntimeError);
diff -r 0e368f851f6a tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c Tue Sep 27 00:55:56 2005
+++ b/tools/xenstore/xenstored_core.c Tue Sep 27 16:36:19 2005
@@ -1136,7 +1136,7 @@
break;
case XS_RELEASE:
- do_release(conn, onearg(in));
+ do_release(conn, in);
break;
case XS_GET_DOMAIN_PATH:
diff -r 0e368f851f6a tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Tue Sep 27 00:55:56 2005
+++ b/tools/xenstore/xenstored_domain.c Tue Sep 27 16:36:19 2005
@@ -50,6 +50,9 @@
/* Event channel port */
u16 port;
+
+ /* Page number. */
+ unsigned long mfn;
/* Domain path in store. */
char *path;
@@ -282,6 +285,7 @@
domain->port = 0;
domain->shutdown = 0;
domain->domid = domid;
+ domain->mfn = mfn;
domain->path = talloc_strdup(domain, path);
domain->page = xc_map_foreign_range(*xc_handle, domain->domid,
getpagesize(),
@@ -312,15 +316,28 @@
{
struct domain *domain;
char *vec[4];
+ domid_t domid;
if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
send_error(conn, EINVAL);
return;
}
- if (conn->id != 0 || !conn->can_write) {
+ domid = atoi(vec[0]);
+ if (!conn->can_write || (conn->id != 0 && domid != DOMID_SELF)) {
send_error(conn, EACCES);
return;
+ }
+
+ /* Domains can introduce more comms pages to store. FIXME: limit. */
+ if (domid == DOMID_SELF) {
+ if (!conn->domain) {
+ send_error(conn, EINVAL);
+ return;
+ }
+ /* Same domid and path. */
+ domid = conn->domain->domid;
+ vec[3] = conn->domain->path;
}
/* Sanity check args. */
@@ -329,8 +346,7 @@
return;
}
/* Hang domain off "in" until we're finished. */
- domain = new_domain(in, atoi(vec[0]), atol(vec[1]), atol(vec[2]),
- vec[3]);
+ domain = new_domain(in, domid, atol(vec[1]), atol(vec[2]), vec[3]);
if (!domain) {
send_error(conn, errno);
return;
@@ -339,58 +355,69 @@
/* Now domain belongs to its connection. */
talloc_steal(domain->conn, domain);
- fire_watches(conn, "@introduceDomain", false);
+ if (domid != DOMID_SELF)
+ fire_watches(conn, "@introduceDomain", false);
send_ack(conn, XS_INTRODUCE);
}
-static struct domain *find_domain_by_domid(domid_t domid)
+static struct domain *find_domain(domid_t domid, unsigned long mfn)
{
struct domain *i;
list_for_each_entry(i, &domains, list) {
- if (i->domid == domid)
+ if (i->domid == domid && (!mfn || i->mfn == mfn))
return i;
}
return NULL;
}
-/* domid */
-void do_release(struct connection *conn, const char *domid_str)
+/* domid, mfn */
+void do_release(struct connection *conn, struct buffered_data *in)
{
struct domain *domain;
domid_t domid;
-
- if (!domid_str) {
+ unsigned long mfn;
+ bool released = false;
+ char *vec[2];
+
+ if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
send_error(conn, EINVAL);
return;
}
-
- domid = atoi(domid_str);
+ domid = atoi(vec[0]);
+ mfn = atol(vec[1]);
if (!domid) {
send_error(conn, EINVAL);
return;
}
- if (conn->id != 0) {
- send_error(conn, EACCES);
- return;
- }
-
- domain = find_domain_by_domid(domid);
- if (!domain) {
+ if (domid == DOMID_SELF) {
+ if (!conn->domain || mfn == 0) {
+ send_error(conn, EINVAL);
+ return;
+ }
+ domid = conn->domain->domid;
+ } else {
+ if (conn->id != 0) {
+ send_error(conn, EACCES);
+ return;
+ }
+ }
+
+ /* Can release multiple if mfn == 0 */
+ while ((domain = find_domain(domid, mfn)) != NULL) {
+ talloc_free(domain->conn);
+ released = true;
+ }
+
+ if (!released) {
send_error(conn, ENOENT);
return;
}
- if (!domain->conn) {
- send_error(conn, EINVAL);
- return;
- }
-
- talloc_free(domain->conn);
-
- fire_watches(conn, "@releaseDomain", false);
+ if (domid != DOMID_SELF)
+ fire_watches(conn, "@releaseDomain", false);
send_ack(conn, XS_RELEASE);
}
@@ -409,7 +436,7 @@
if (domid == DOMID_SELF)
domain = conn->domain;
else
- domain = find_domain_by_domid(domid);
+ domain = find_domain(domid, 0);
if (!domain)
send_error(conn, ENOENT);
diff -r 0e368f851f6a tools/xenstore/xenstored_domain.h
--- a/tools/xenstore/xenstored_domain.h Tue Sep 27 00:55:56 2005
+++ b/tools/xenstore/xenstored_domain.h Tue Sep 27 16:36:19 2005
@@ -25,8 +25,8 @@
/* domid, mfn, eventchn, path */
void do_introduce(struct connection *conn, struct buffered_data *in);
-/* domid */
-void do_release(struct connection *conn, const char *domid_str);
+/* domid, mfn */
+void do_release(struct connection *conn, struct buffered_data *in);
/* domid */
void do_get_domain_path(struct connection *conn, const char *domid_str);
diff -r 0e368f851f6a tools/xenstore/xs.c
--- a/tools/xenstore/xs.c Tue Sep 27 00:55:56 2005
+++ b/tools/xenstore/xs.c Tue Sep 27 16:36:19 2005
@@ -676,13 +676,21 @@
return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL));
}
-bool xs_release_domain(struct xs_handle *h, domid_t domid)
+bool xs_release_domain(struct xs_handle *h, domid_t domid, unsigned long mfn)
{
char domid_str[MAX_STRLEN(domid)];
+ char mfn_str[MAX_STRLEN(mfn)];
+ struct iovec iov[2];
sprintf(domid_str, "%u", domid);
-
- return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL));
+ sprintf(mfn_str, "%lu", mfn);
+
+ iov[0].iov_base = domid_str;
+ iov[0].iov_len = strlen(domid_str) + 1;
+ iov[1].iov_base = mfn_str;
+ iov[1].iov_len = strlen(mfn_str) + 1;
+
+ return xs_bool(xs_talkv(h, XS_RELEASE, iov, ARRAY_SIZE(iov), NULL));
}
char *xs_get_domain_path(struct xs_handle *h, domid_t domid)
diff -r 0e368f851f6a tools/xenstore/xs.h
--- a/tools/xenstore/xs.h Tue Sep 27 00:55:56 2005
+++ b/tools/xenstore/xs.h Tue Sep 27 16:36:19 2005
@@ -130,8 +130,9 @@
/* Release a domain.
* Tells the store domain to release the memory page to the domain.
+ * mfn is 0 to release all of them.
*/
-bool xs_release_domain(struct xs_handle *h, domid_t domid);
+bool xs_release_domain(struct xs_handle *h, domid_t domid, unsigned long mfn);
/* Query the home path of a domain.
*/
Test code for previous patch.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
diff -r 0e368f851f6a tools/xenstore/fake_libxc.c
--- a/tools/xenstore/fake_libxc.c Tue Sep 27 00:55:56 2005
+++ b/tools/xenstore/fake_libxc.c Tue Sep 27 16:36:19 2005
@@ -44,42 +44,38 @@
return 0;
}
-void *xc_map_foreign_range(int xc_handle, u32 dom __attribute__((unused)),
+void *xc_map_foreign_range(int xc_handle __attribute__((unused)),
+ u32 dom __attribute__((unused)),
int size, int prot,
unsigned long mfn __attribute__((unused)))
{
void *ret;
+ int *extra;
+ int fd;
- ret = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
+ fd = open("/tmp/xcmap", O_RDWR);
+ if (fd < 0)
+ return NULL;
+
+ /* We actually get extra page, for comms with xs_test. */
+ ret = mmap(NULL, size + getpagesize(), prot, MAP_SHARED, fd, 0);
if (ret == MAP_FAILED)
return NULL;
- /* xs_test tells us pid and port by putting it in buffer, we reply. */
- xs_test_pid = *(int *)(ret + 32);
- port = *(int *)(ret + 36);
- *(int *)(ret + 32) = getpid();
+ extra = ret + size;
+ xs_test_pid = extra[0];
+ port = extra[1];
+ extra[2] = getpid();
return ret;
}
int xc_interface_open(void)
{
- int fd;
- char page[getpagesize()];
-
- fd = open("/tmp/xcmap", O_RDWR|O_CREAT|O_TRUNC, 0600);
- if (fd < 0)
- return fd;
-
- memset(page, 0, sizeof(page));
- if (!xs_write_all(fd, page, sizeof(page)))
- barf_perror("Failed to write /tmp/xcmap page");
-
- return fd;
+ return 1;
}
-int xc_interface_close(int xc_handle)
+int xc_interface_close(int xc_handle __attribute__((unused)))
{
- close(xc_handle);
return 0;
}
diff -r 0e368f851f6a tools/xenstore/testsuite/09domain.test
--- a/tools/xenstore/testsuite/09domain.test Tue Sep 27 00:55:56 2005
+++ b/tools/xenstore/testsuite/09domain.test Tue Sep 27 16:36:19 2005
@@ -17,3 +17,24 @@
expect handle is 2
introduce 1 100 7 /my/home
release 1
+
+# Introduce sub-connection
+write /my/home/entry contents
+close
+expect handle is 3
+introduce 1 100 7 /my/home
+expect handle is 4
+3 introduce-self 120 7 /my/home
+
+# Check home is correct
+expect 4:contents
+4 read entry
+
+# Release 4 from 3
+3 release-self 120
+
+# Introduce a new one and release both at once.
+expect handle is 5
+3 introduce-self 120 7 /my/home
+
+release 1
diff -r 0e368f851f6a tools/xenstore/xs_test.c
--- a/tools/xenstore/xs_test.c Tue Sep 27 00:55:56 2005
+++ b/tools/xenstore/xs_test.c Tue Sep 27 16:36:19 2005
@@ -59,6 +59,7 @@
static struct ringbuf_head *out, *in;
static unsigned int ringbuf_datasize;
+static int event_channel;
static int daemon_pid;
/* FIXME: Mark connection as broken (close it?) when this happens. */
@@ -208,6 +209,9 @@
" start <node>\n"
" abort\n"
" introduce <domid> <mfn> <eventchn> <path>\n"
+ " introduce-self <mfn> <eventchn> <path>\n"
+ " release <domid>\n"
+ " release-self <mfn>\n"
" commit\n"
" sleep <milliseconds>\n"
" expect <pattern>\n"
@@ -575,16 +579,22 @@
}
static void do_introduce(unsigned int handle,
- const char *domid,
+ int domid,
const char *mfn,
const char *eventchn,
const char *path)
{
unsigned int i;
- int fd;
+ int fd, *extra;
+ char pages[getpagesize()*2];
+
+ fd = open("/tmp/xcmap", O_RDWR|O_CREAT, 0600);
+ memset(pages, 0, sizeof(pages));
+ write(fd, pages, sizeof(pages));
/* This mechanism is v. slow w. valgrind running. */
- timeout_ms = 5000;
+ if (timeout_ms)
+ timeout_ms = 5000;
/* We poll, so ignore signal */
signal(SIGUSR2, SIG_IGN);
@@ -592,22 +602,24 @@
if (!handles[i])
break;
- fd = open("/tmp/xcmap", O_RDWR);
/* Set in and out pointers. */
- out = mmap(NULL, getpagesize(), PROT_WRITE|PROT_READ, MAP_SHARED,fd,0);
+ out = mmap(NULL, sizeof(pages), PROT_WRITE|PROT_READ, MAP_SHARED,fd,0);
if (out == MAP_FAILED)
barf_perror("Failed to map /tmp/xcmap page");
in = (void *)out + getpagesize() / 2;
close(fd);
+ event_channel = atoi(eventchn);
+
/* Tell them the event channel and our PID. */
- *(int *)((void *)out + 32) = getpid();
- *(u16 *)((void *)out + 36) = atoi(eventchn);
-
- if (!xs_introduce_domain(handles[handle], atoi(domid),
+ extra = (void *)out + getpagesize();
+ extra[0] = getpid();
+ extra[1] = event_channel;
+
+ if (!xs_introduce_domain(handles[handle], domid,
atol(mfn), atoi(eventchn), path)) {
failed(handle);
- munmap(out, getpagesize());
+ munmap(out, getpagesize()*2);
return;
}
output("handle is %i\n", i);
@@ -622,12 +634,18 @@
handles[i]->committing = false;
/* Read in daemon pid. */
- daemon_pid = *(int *)((void *)out + 32);
+ daemon_pid = extra[2];
}
static void do_release(unsigned int handle, const char *domid)
{
- if (!xs_release_domain(handles[handle], atoi(domid)))
+ if (!xs_release_domain(handles[handle], atoi(domid), 0))
+ failed(handle);
+}
+
+static void do_release_self(unsigned int handle, const char *mfn)
+{
+ if (!xs_release_domain(handles[handle], DOMID_SELF, atol(mfn)))
failed(handle);
}
@@ -802,10 +820,15 @@
else if (streq(command, "abort"))
do_end(handle, true);
else if (streq(command, "introduce"))
- do_introduce(handle, arg(line, 1), arg(line, 2),
+ do_introduce(handle, atoi(arg(line, 1)), arg(line, 2),
arg(line, 3), arg(line, 4));
+ else if (streq(command, "introduce-self"))
+ do_introduce(handle, DOMID_SELF,
+ arg(line, 1), arg(line, 2), arg(line, 3));
else if (streq(command, "release"))
do_release(handle, arg(line, 1));
+ else if (streq(command, "release-self"))
+ do_release_self(handle, arg(line, 1));
else if (streq(command, "dump"))
dump(handle);
else if (streq(command, "sleep")) {
--
A bad analogy is like a leaky screwdriver -- Richard Braakman
next prev parent reply other threads:[~2005-09-27 6:48 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-09-08 8:02 /proc/xen/xenbus supports watch? NAHieu
2005-09-08 10:38 ` Christian Limpach
2005-09-09 0:43 ` Rusty Russell
2005-09-13 9:42 ` Christian Limpach
2005-09-14 0:21 ` Rusty Russell
2005-09-14 8:24 ` Christian Limpach
2005-09-14 9:18 ` Rusty Russell
2005-09-14 12:55 ` Christian Limpach
2005-09-15 1:39 ` Rusty Russell
2005-09-15 10:53 ` Keir Fraser
2005-09-17 8:26 ` Rusty Russell
2005-09-17 8:33 ` Keir Fraser
2005-09-19 0:11 ` Rusty Russell
2005-09-19 8:54 ` Keir Fraser
2005-09-20 11:01 ` Rusty Russell
2005-09-21 9:35 ` Keir Fraser
2005-09-22 2:07 ` Rusty Russell
2005-09-22 9:36 ` Keir Fraser
2005-09-22 22:54 ` Rusty Russell
2005-09-23 9:17 ` Keir Fraser
2005-09-25 3:29 ` Rusty Russell
2005-09-25 11:02 ` Keir Fraser
2005-09-25 11:33 ` Keir Fraser
2005-09-25 18:55 ` Christian Limpach
2005-09-26 6:36 ` Rusty Russell
2005-09-26 7:33 ` Keir Fraser
2005-09-26 18:51 ` Christian Limpach
2005-09-26 19:30 ` Keir Fraser
2005-09-27 6:48 ` Rusty Russell [this message]
2005-09-27 7:15 ` Rusty Russell
2005-09-27 23:31 ` David Hopwood
2005-09-25 23:06 ` Rusty Russell
2005-09-21 9:39 ` Keir Fraser
2005-09-21 11:42 ` harry
2005-09-22 2:22 ` Rusty Russell
2005-09-22 9:35 ` Keir Fraser
2005-09-22 23:51 ` Rusty Russell
2005-09-23 1:01 ` Andrew Warfield
2005-09-25 0:57 ` Rusty Russell
2005-09-25 11:09 ` Keir Fraser
2005-09-25 22:52 ` Rusty Russell
2005-09-23 9:24 ` Keir Fraser
2005-09-25 1:09 ` Rusty Russell
2005-09-17 17:40 ` Christian Limpach
2005-09-19 0:19 ` Rusty Russell
2005-09-15 11:02 ` Christian Limpach
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1127803690.7703.81.camel@localhost.localdomain \
--to=rusty@rustcorp.com.au \
--cc=Christian.Limpach@cl.cam.ac.uk \
--cc=Keir.Fraser@cl.cam.ac.uk \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.