[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] /proc/xen/xenbus supports watch?
On Wed, 2005-09-14 at 10:21 +1000, Rusty Russell wrote: > So when someone opens the xenbus dev, we introduce a new page to the > domain and the xenstored uses that for comms. When closed, the page is > released. This actually simplifies the xenbus_dev driver a lot: now > it's just a dumb pass-through since we don't have to worry about the > userspace program blowing chunks all over the kernel's comms mechanism. > > I'll hack something up and see what you think... OK, realized there's a problem with suspend/resume. Within the kernel, we prevent suspend/resume by simply holding the xenstore_lock, so it can't happen during normal operations, or transactions. So let's leave this for now. It is fairly similar to the problem of xenstored restarts, which I'm trying to merge, so I suggest we revisit after that... Patch for reading only (I subbed in NULL for the default store page for the moment, since I know there's another patch out there which touches this). diff -r 0d8c0db04258 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Tue Sep 13 21:52:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Wed Sep 14 19:16:48 2005 @@ -46,14 +46,18 @@ DECLARE_WAIT_QUEUE_HEAD(xb_waitq); -static inline struct ringbuf_head *outbuf(void) -{ - return mfn_to_virt(xen_start_info->store_mfn); -} - -static inline struct ringbuf_head *inbuf(void) -{ - return mfn_to_virt(xen_start_info->store_mfn) + PAGE_SIZE/2; +static inline struct ringbuf_head *outbuf(void *page) +{ + if (!page) + return mfn_to_virt(xen_start_info->store_mfn); + return page; +} + +static inline struct ringbuf_head *inbuf(void *page) +{ + if (!page) + return mfn_to_virt(xen_start_info->store_mfn) + PAGE_SIZE/2; + return page + PAGE_SIZE/2; } static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs) @@ -117,10 +121,10 @@ return avail != 0; } -int xb_write(const void *data, unsigned len) +int xb_write(const void *data, unsigned len, void *page) { struct ringbuf_head h; - struct ringbuf_head *out = outbuf(); + struct ringbuf_head *out = outbuf(page); do { void *dst; @@ -151,19 +155,19 @@ return 0; } -int xs_input_avail(void) +int xs_input_avail(void *page) { unsigned int avail; - struct ringbuf_head *in = inbuf(); + struct ringbuf_head *in = inbuf(page); get_input_chunk(in, in->buf, &avail); return avail != 0; } -int xb_read(void *data, unsigned len) +int xb_read(void *data, unsigned len, void *page) { struct ringbuf_head h; - struct ringbuf_head *in = inbuf(); + struct ringbuf_head *in = inbuf(page); int was_full; while (len != 0) { @@ -200,34 +204,25 @@ return 0; } -/* Set up interrupt handler off store event channel. */ -int xb_init_comms(void) +/* Set up interrupt handler off store event channel, and clear page. */ +int xb_init_comms(unsigned int evtchn, void *page) { int err; - if (!xen_start_info->store_evtchn) - return 0; - - err = bind_evtchn_to_irqhandler( - xen_start_info->store_evtchn, wake_waiting, - 0, "xenbus", &xb_waitq); + err = bind_evtchn_to_irqhandler(evtchn, wake_waiting, + 0, "xenbus", &xb_waitq); if (err) { printk(KERN_ERR "XENBUS request irq failed %i\n", err); - unbind_evtchn_from_irq(xen_start_info->store_evtchn); return err; } /* FIXME zero out page -- domain builder should probably do this*/ - memset(mfn_to_virt(xen_start_info->store_mfn), 0, PAGE_SIZE); - + memset(inbuf(page), 0, PAGE_SIZE/2); + memset(outbuf(page), 0, PAGE_SIZE/2); return 0; } -void xb_suspend_comms(void) -{ - - if (!xen_start_info->store_evtchn) - return; - - unbind_evtchn_from_irqhandler(xen_start_info->store_evtchn, &xb_waitq); -} +void xb_stop_comms(unsigned int evtchn) +{ + unbind_evtchn_from_irqhandler(evtchn, &xb_waitq); +} diff -r 0d8c0db04258 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h Tue Sep 13 21:52:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h Wed Sep 14 19:16:48 2005 @@ -29,13 +29,13 @@ #define _XENBUS_COMMS_H int xs_init(void); -int xb_init_comms(void); -void xb_suspend_comms(void); +int xb_init_comms(unsigned int evtchn, void *page); +void xb_stop_comms(unsigned int evtchn); -/* Low level routines. */ -int xb_write(const void *data, unsigned len); -int xb_read(void *data, unsigned len); -int xs_input_avail(void); +/* Low level routines: page is NULL for default store page */ +int xb_write(const void *data, unsigned len, void *page); +int xb_read(void *data, unsigned len, void *page); +int xs_input_avail(void *page); extern wait_queue_head_t xb_waitq; #endif /* _XENBUS_COMMS_H */ diff -r 0d8c0db04258 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Tue Sep 13 21:52:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Wed Sep 14 19:16:48 2005 @@ -36,6 +36,7 @@ #include <linux/notifier.h> #include <linux/wait.h> #include <linux/fs.h> +#include <linux/spinlock.h> #include "xenbus_comms.h" @@ -45,90 +46,47 @@ #include <asm-xen/linux-public/xenstored.h> struct xenbus_dev_data { - /* Are there bytes left to be read in this message? */ - int bytes_left; - /* Are we still waiting for the reply to a message we wrote? */ - int awaiting_reply; - /* Buffer for outgoing messages. */ - unsigned int len; - union { - struct xsd_sockmsg msg; - char buffer[PAGE_SIZE]; - } u; + unsigned int evtchn; + char *page; + char bouncebuf[PAGE_SIZE]; }; static struct proc_dir_entry *xenbus_dev_intf; -/* Reply can be long (dir, getperm): don't buffer, just examine - * headers so we can discard rest if they die. */ static ssize_t xenbus_dev_read(struct file *filp, char __user *ubuf, size_t len, loff_t *ppos) { struct xenbus_dev_data *data = filp->private_data; - struct xsd_sockmsg msg; - int err; + int ret; - /* Refill empty buffer? */ - if (data->bytes_left == 0) { - if (len < sizeof(msg)) - return -EINVAL; - - err = xb_read(&msg, sizeof(msg)); - if (err) - return err; - data->bytes_left = msg.len; - if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0) - return -EFAULT; - /* We can receive spurious XS_WATCH_EVENT messages. */ - if (msg.type != XS_WATCH_EVENT) - data->awaiting_reply = 0; - return sizeof(msg); - } - - /* Don't read over next header, or over temporary buffer. */ - if (len > sizeof(data->u.buffer)) - len = sizeof(data->u.buffer); - if (len > data->bytes_left) - len = data->bytes_left; - - err = xb_read(data->u.buffer, len); - if (err) - return err; - - data->bytes_left -= len; - if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0) - return -EFAULT; - return len; + if (len > sizeof(data->bouncebuf)) + len = sizeof(data->bouncebuf); + ret = xb_read(data->bouncebuf, len, data->page); + if (ret && copy_to_user(ubuf, data->bouncebuf, len) != 0) + ret = -EFAULT; + return ret; } -/* We do v. basic sanity checking so they don't screw up kernel later. */ static ssize_t xenbus_dev_write(struct file *filp, const char __user *ubuf, size_t len, loff_t *ppos) { struct xenbus_dev_data *data = filp->private_data; - int err; + int ret; - /* We gather data in buffer until we're ready to send it. */ - if (len > data->len + sizeof(data->u)) - return -EINVAL; - if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0) + if (len > sizeof(data->bouncebuf)) + len = sizeof(data->bouncebuf); + if (copy_from_user(data->bouncebuf, ubuf, len) != 0) return -EFAULT; - data->len += len; - if (data->len >= sizeof(data->u.msg) + data->u.msg.len) { - err = xb_write(data->u.buffer, data->len); - if (err) - return err; - data->len = 0; - data->awaiting_reply = 1; - } - return len; + return xb_write(data->boundbuf, len); } static int xenbus_dev_open(struct inode *inode, struct file *filp) { - struct xenbus_dev_data *u; + struct xenbus_dev_data *data; + int err; + evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound }; if (xen_start_info->store_evtchn == 0) return -ENOENT; @@ -136,34 +94,71 @@ /* Don't try seeking. */ nonseekable_open(inode, filp); - u = kmalloc(sizeof(*u), GFP_KERNEL); - if (u == NULL) - return -ENOMEM; + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto out; + } + data->page = (void *)__get_free_page(GFP_KERNEL); + if (!data->page) { + err = -ENOMEM; + goto free_data; + } + op.u.alloc_unbound.dom = 0; + err = HYPERVISOR_event_channel_op(&op); + if (err) + goto free_page; + data->evtchn = op.u.alloc_unbound.port; + err = xb_init_comms(data->evtchn, data->page); + if (err) + goto release_evtchn; - memset(u, 0, sizeof(*u)); + down(&xenbus_lock); + err = xenbus_introduce(virt_to_mfn(data->page), data->evtchn); + up(&xenbus_lock); + if (err) + goto release_comms; filp->private_data = u; + return 0; - down(&xenbus_lock); +release_comms: + xb_stop_comms(data->evtchn); +release_evtchn: + op.cmd = EVTCHNOP_close; + op.u.close.dom = DOMID_SELF; + op.u.close.port = data->evtchn; + if (HYPERVISOR_event_channel_op(&op) != 0) + printk(KERN_WARNING "xenbus_dev: channel close failed\n"); +free_page: + free_page((unsigned long)data->page); +free_data: + kfree(data); +out: + return err; +} - return 0; -} +static void xenbus_dev_stop(struct xenbus_dev_data *data) +{ + static int xenbus_dev_release(struct inode *inode, struct file *filp) { struct xenbus_dev_data *data = filp->private_data; + evtchn_op_t op = { .cmd = EVTCHNOP_close }; - /* Discard any unread replies. */ - while (data->bytes_left || data->awaiting_reply) - xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL); - - /* Harmless if no transaction in progress. */ - xenbus_transaction_end(1); - + down(&xenbus_lock); + if (xenbus_release(virt_to_mfn(data->page)) != 0) + printk(KERN_WARNING "xenbus_dev: release failed\n"); up(&xenbus_lock); + xb_stop_comms(data->evtchn); + op.u.close.dom = DOMID_SELF; + op.u.close.port = data->evtchn; + if (HYPERVISOR_event_channel_op(&op) != 0) + printk(KERN_WARNING "xenbus_dev: channel close failed\n"); + free_page((unsigned long)data->page); kfree(data); - return 0; } diff -r 0d8c0db04258 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Sep 13 21:52:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Wed Sep 14 19:16:48 2005 @@ -607,12 +607,12 @@ down(&xenbus_lock); bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); - xb_suspend_comms(); + xb_stop_comms(xen_start_info->store_evtchn); } void xenbus_resume(void) { - xb_init_comms(); + xb_init_comms(xen_start_info->store_evtchn, NULL); reregister_xenbus_watches(); bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev); diff -r 0d8c0db04258 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Tue Sep 13 21:52:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Wed Sep 14 19:16:48 2005 @@ -426,6 +426,44 @@ } EXPORT_SYMBOL(xenbus_gather); +int xenbus_introduce(unsigned long mfn, unsigned int evtchn) +{ + char domid_str[21]; + char mfn_str[21]; + char eventchn_str[21]; + struct kvec iov[4]; + + sprintf(domid_str, "%u", DOMID_SELF); + sprintf(mfn_str, "%lu", mfn); + sprintf(eventchn_str, "%u", eventchn); + + 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; + iov[2].iov_base = eventchn_str; + iov[2].iov_len = strlen(eventchn_str) + 1; + iov[3].iov_base = ""; + iov[3].iov_len = 1; + + return xs_error(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL)); +} + +int xenbus_release(unsigned long mfn); +{ + struct iovec iov[2]; + char domid_str[21], mfn_str[21]; + + sprintf(domid_str, "%u", DOMID_SELF); + 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_error(xs_talkv(h, XS_RELEASE, iov, ARRAY_SIZE(iov), NULL)); +} + static int xs_watch(const char *path, const char *token) { struct kvec iov[2]; @@ -569,7 +607,7 @@ int err; struct task_struct *watcher; - err = xb_init_comms(); + err = xb_init_comms(xen_start_info->store_evtchn, NULL); if (err) return err; diff -r 0d8c0db04258 linux-2.6-xen-sparse/include/asm-xen/xenbus.h --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Tue Sep 13 21:52:24 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Wed Sep 14 19:16:48 2005 @@ -90,6 +90,8 @@ int xenbus_rm(const char *dir, const char *node); int xenbus_transaction_start(const char *subtree); int xenbus_transaction_end(int abort); +int xenbus_introduce(unsigned long mfn, unsigned int evtchn); +int xenbus_release(unsigned long mfn); /* Single read and scanf: returns -errno or num scanned if > 0. */ int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...) diff -r 0d8c0db04258 tools/python/xen/lowlevel/xs/xs.c --- a/tools/python/xen/lowlevel/xs/xs.c Tue Sep 13 21:52:24 2005 +++ b/tools/python/xen/lowlevel/xs/xs.c Wed Sep 14 19:16:48 2005 @@ -708,7 +708,7 @@ } #define xspy_release_domain_doc "\n" \ - "Tell xenstore to release its channel to a domain.\n" \ + "Tell xenstore to release its channel(s) to a domain.\n" \ "Unless this is done the domain will not be released.\n" \ " dom [int]: domain id\n" \ "\n" \ @@ -733,7 +733,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 0d8c0db04258 tools/xenstore/testsuite/09domain.test --- a/tools/xenstore/testsuite/09domain.test Tue Sep 13 21:52:24 2005 +++ b/tools/xenstore/testsuite/09domain.test Wed Sep 14 19:16:48 2005 @@ -10,10 +10,16 @@ close # Release that domain. -release 1 +release 1 100 close # Introduce and release by same connection. expect handle is 2 introduce 1 100 7 /my/home -release 1 +release 1 100 + +# Introduce another connection from a domain connection +expect handle is 3 +# FIXME: We can't actually handle multiple domain connections in xs_test. +introduce 1 101 7 /my/home +release 1 0 diff -r 0d8c0db04258 tools/xenstore/testsuite/11domain-watch.test --- a/tools/xenstore/testsuite/11domain-watch.test Tue Sep 13 21:52:24 2005 +++ b/tools/xenstore/testsuite/11domain-watch.test Wed Sep 14 19:16:48 2005 @@ -12,7 +12,7 @@ 1 waitwatch 1 ackwatch token 1 unwatch /test token -release 1 +release 1 0 1 close # ignore watches while doing commands, should work. @@ -26,7 +26,7 @@ expect 1:/dir/test:token 1 waitwatch 1 ackwatch token -release 1 +release 1 0 1 close # unwatch @@ -39,7 +39,7 @@ expect 1:/dir/test2:token2 1 waitwatch 1 unwatch /dir token2 -release 1 +release 1 0 1 close # unwatch while watch pending. @@ -48,5 +48,5 @@ 1 watch /dir token1 write /dir/test2 create contents 1 unwatch /dir token1 -release 1 +release 1 0 1 close diff -r 0d8c0db04258 tools/xenstore/xenstored_core.c --- a/tools/xenstore/xenstored_core.c Tue Sep 13 21:52:24 2005 +++ b/tools/xenstore/xenstored_core.c Wed Sep 14 19:16:48 2005 @@ -1285,7 +1285,7 @@ break; case XS_RELEASE: - do_release(conn, onearg(in)); + do_release(conn, in); break; case XS_GET_DOMAIN_PATH: diff -r 0d8c0db04258 tools/xenstore/xenstored_domain.c --- a/tools/xenstore/xenstored_domain.c Tue Sep 13 21:52:24 2005 +++ b/tools/xenstore/xenstored_domain.c Wed Sep 14 19:16:48 2005 @@ -51,6 +51,9 @@ /* Event channel port */ u16 port; + /* Shared page frame */ + unsigned long mfn; + /* Domain path in store. */ char *path; @@ -273,6 +276,7 @@ domain = talloc(context, struct domain); domain->port = 0; domain->domid = domid; + domain->mfn = mfn; domain->path = talloc_strdup(domain, path); domain->page = xc_map_foreign_range(*xc_handle, domain->domid, getpagesize(), @@ -302,6 +306,10 @@ void do_introduce(struct connection *conn, struct buffered_data *in) { struct domain *domain; + domid_t domid; + unsigned long mfn; + unsigned int evtchn; + char *path; char *vec[4]; if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) { @@ -309,7 +317,20 @@ return; } - if (conn->id != 0) { + domid = atoi(vec[0]); + mfn = atol(vec[1]); + evtchn = atoi(vec[2]); + path = vec[3]; + + /* Domains can introduce more pages: share same path. */ + if (conn->domain) { + if (domid != DOMID_SELF) { + send_error(conn, EACCES); + return; + } + domid = conn->domain->domid; + path = conn->domain->path; + } else if (conn->id != 0) { send_error(conn, EACCES); return; } @@ -320,13 +341,12 @@ } /* Sanity check args. */ - if ((atoi(vec[2]) <= 0) || !is_valid_nodename(vec[3])) { + if (mfn == 0 || !is_valid_nodename(path)) { send_error(conn, EINVAL); 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, mfn, evtchn, path); if (!domain) { send_error(conn, errno); return; @@ -340,54 +360,69 @@ 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) - return i; + if (i->domid == domid) { + if (!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; + char *vec[2]; + + if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) { send_error(conn, EINVAL); return; } - - domid = atoi(domid_str); + domid = atol(vec[0]); + mfn = atol(vec[1]); + if (!domid) { send_error(conn, EINVAL); return; } - if (conn->id != 0) { + if (!conn->can_write) { + send_error(conn, EROFS); + return; + } + + /* Domains can release own pages, but not all of them. */ + if (conn->domain) { + if (domid != DOMID_SELF || !mfn) { + send_error(conn, EACCES); + return; + } + domid = conn->domain->domid; + } else if (conn->id != 0) { send_error(conn, EACCES); return; } - domain = find_domain_by_domid(domid); - if (!domain) { - send_error(conn, ENOENT); - return; - } - - if (!domain->conn) { - send_error(conn, EINVAL); - return; - } - - talloc_free(domain->conn); - - fire_watches(NULL, "@releaseDomain", false); - + if (mfn) { + domain = find_domain(domid, mfn); + if (!domain) { + send_error(conn, ENOENT); + return; + } + talloc_free(domain->conn); + } else { + while ((domain = find_domain(domid, 0)) != NULL) + talloc_free(domain->conn); + + fire_watches(NULL, "@releaseDomain", false); + } send_ack(conn, XS_RELEASE); } @@ -405,7 +440,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 0d8c0db04258 tools/xenstore/xenstored_domain.h --- a/tools/xenstore/xenstored_domain.h Tue Sep 13 21:52:24 2005 +++ b/tools/xenstore/xenstored_domain.h Wed Sep 14 19:16:48 2005 @@ -26,7 +26,7 @@ void do_introduce(struct connection *conn, struct buffered_data *in); /* domid */ -void do_release(struct connection *conn, const char *domid_str); +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 0d8c0db04258 tools/xenstore/xs.c --- a/tools/xenstore/xs.c Tue Sep 13 21:52:24 2005 +++ b/tools/xenstore/xs.c Wed Sep 14 19:16:48 2005 @@ -565,13 +565,19 @@ return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL)); } -bool xs_release_domain(struct xs_handle *h, domid_t domid) -{ - char domid_str[MAX_STRLEN(domid)]; +bool xs_release_domain(struct xs_handle *h, domid_t domid, unsigned long mfn) +{ + struct iovec iov[2]; + char domid_str[MAX_STRLEN(domid)], mfn_str[MAX_STRLEN(mfn)]; 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 0d8c0db04258 tools/xenstore/xs.h --- a/tools/xenstore/xs.h Tue Sep 13 21:52:24 2005 +++ b/tools/xenstore/xs.h Wed Sep 14 19:16:48 2005 @@ -125,14 +125,16 @@ /* Introduce a new domain. * This tells the store daemon about a shared memory page, event channel * and store path associated with a domain: the domain uses these to communicate. + * The domain can use this to add its own extra pages. */ bool xs_introduce_domain(struct xs_handle *h, domid_t domid, unsigned long mfn, unsigned int eventchn, const char *path); /* Release a domain. * Tells the store domain to release the memory page to the domain. + * mfn == 0 means to release all pages. */ -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. */ diff -r 0d8c0db04258 tools/xenstore/xs_test.c --- a/tools/xenstore/xs_test.c Tue Sep 13 21:52:24 2005 +++ b/tools/xenstore/xs_test.c Wed Sep 14 19:16:48 2005 @@ -207,6 +207,7 @@ " start <node>\n" " abort\n" " introduce <domid> <mfn> <eventchn> <path>\n" + " release <domid> <mfn>\n" " commit\n" " sleep <milliseconds>\n" " expect <pattern>\n" @@ -630,9 +631,9 @@ daemon_pid = *(int *)((void *)out + 32); } -static void do_release(unsigned int handle, const char *domid) -{ - if (!xs_release_domain(handles[handle], atoi(domid))) +static void do_release(unsigned int handle, const char *domid, const char *mfn) +{ + if (!xs_release_domain(handles[handle], atoi(domid), atol(mfn))) failed(handle); } @@ -809,7 +810,7 @@ do_introduce(handle, arg(line, 1), arg(line, 2), arg(line, 3), arg(line, 4)); else if (streq(command, "release")) - do_release(handle, arg(line, 1)); + do_release(handle, arg(line, 1), arg(line, 2)); else if (streq(command, "dump")) dump(handle); else if (streq(command, "sleep")) { -- A bad analogy is like a leaky screwdriver -- Richard Braakman _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |