[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] xenbus: Allow lazy init in case xenstored runs in a separate minios domain.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1242740750 -3600 # Node ID bd7e30b58d125a64fc8388022a24f598068b95ec # Parent e17af34d4d90b034f229ebe6e504270200bf50e4 xenbus: Allow lazy init in case xenstored runs in a separate minios domain. Here's an explanation of the states: It starts out in XENBUS_XSD_UNCOMMITTED. As the master xenbus (the one local to xenstored), it will receive an mmap from xenstore, putting it in XENBUS_XSD_LOCAL_INIT. This enables the wake_waiting IRQ, which will put it in XENBUS_XSD_LOCAL_READY. Alternatively, as a slave xenbus, it will receive an ioctl from the xenstore domain builder, putting it in XENBUS_XSD_FOREIGN_INIT. This enables the wake_waiting IRQ, which will put it in XENBUS_XSD_FOREIGN_READY. DomU's are immediately initialized to XENBUS_XSD_FOREIGN_READY. Signed-off-by: Diego Ongaro <diego.ongaro@xxxxxxxxxx> Signed-off-by: Alex Zeffertt <alex.zeffertt@xxxxxxxxxxxxx> --- drivers/xen/core/xen_sysfs.c | 6 +- drivers/xen/xenbus/xenbus_comms.c | 31 +++++++++-- drivers/xen/xenbus/xenbus_comms.h | 16 ++++++ drivers/xen/xenbus/xenbus_dev.c | 62 +++++++++++++++++++++++ drivers/xen/xenbus/xenbus_probe.c | 100 +++++++++++++++++++++++++++++++++++--- drivers/xen/xenbus/xenbus_xs.c | 6 -- include/xen/public/xenbus.h | 56 +++++++++++++++++++++ 7 files changed, 256 insertions(+), 21 deletions(-) diff -r e17af34d4d90 -r bd7e30b58d12 drivers/xen/core/xen_sysfs.c --- a/drivers/xen/core/xen_sysfs.c Tue May 19 14:42:04 2009 +0100 +++ b/drivers/xen/core/xen_sysfs.c Tue May 19 14:45:50 2009 +0100 @@ -16,6 +16,7 @@ #include <xen/hypervisor_sysfs.h> #include <xen/xenbus.h> #include <xen/interface/kexec.h> +#include "../xenbus/xenbus_comms.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mike D. Day <ncmike@xxxxxxxxxx>"); @@ -105,9 +106,8 @@ static ssize_t uuid_show(struct hyp_sysf { char *vm, *val; int ret; - extern int xenstored_ready; - - if (!xenstored_ready) + + if (!is_xenstored_ready()) return -EBUSY; vm = xenbus_read(XBT_NIL, "vm", "", NULL); diff -r e17af34d4d90 -r bd7e30b58d12 drivers/xen/xenbus/xenbus_comms.c --- a/drivers/xen/xenbus/xenbus_comms.c Tue May 19 14:42:04 2009 +0100 +++ b/drivers/xen/xenbus/xenbus_comms.c Tue May 19 14:45:50 2009 +0100 @@ -50,18 +50,39 @@ static int xenbus_irq; static int xenbus_irq; extern void xenbus_probe(void *); -extern int xenstored_ready; static DECLARE_WORK(probe_work, xenbus_probe, NULL); static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs) { - if (unlikely(xenstored_ready == 0)) { - xenstored_ready = 1; + int old, new; + + old = atomic_read(&xenbus_xsd_state); + switch (old) { + case XENBUS_XSD_UNCOMMITTED: + BUG(); + return IRQ_HANDLED; + + case XENBUS_XSD_FOREIGN_INIT: + new = XENBUS_XSD_FOREIGN_READY; + break; + + case XENBUS_XSD_LOCAL_INIT: + new = XENBUS_XSD_LOCAL_READY; + break; + + case XENBUS_XSD_FOREIGN_READY: + case XENBUS_XSD_LOCAL_READY: + default: + goto wake; + } + + old = atomic_cmpxchg(&xenbus_xsd_state, old, new); + if (old != new) schedule_work(&probe_work); - } - + +wake: wake_up(&xb_waitq); return IRQ_HANDLED; } diff -r e17af34d4d90 -r bd7e30b58d12 drivers/xen/xenbus/xenbus_comms.h --- a/drivers/xen/xenbus/xenbus_comms.h Tue May 19 14:42:04 2009 +0100 +++ b/drivers/xen/xenbus/xenbus_comms.h Tue May 19 14:45:50 2009 +0100 @@ -43,4 +43,20 @@ extern struct xenstore_domain_interface extern struct xenstore_domain_interface *xen_store_interface; extern int xen_store_evtchn; +/* For xenbus internal use. */ +enum { + XENBUS_XSD_UNCOMMITTED = 0, + XENBUS_XSD_FOREIGN_INIT, + XENBUS_XSD_FOREIGN_READY, + XENBUS_XSD_LOCAL_INIT, + XENBUS_XSD_LOCAL_READY, +}; +extern atomic_t xenbus_xsd_state; + +static inline int is_xenstored_ready(void) +{ + int s = atomic_read(&xenbus_xsd_state); + return s == XENBUS_XSD_FOREIGN_READY || s == XENBUS_XSD_LOCAL_READY; +} + #endif /* _XENBUS_COMMS_H */ diff -r e17af34d4d90 -r bd7e30b58d12 drivers/xen/xenbus/xenbus_dev.c --- a/drivers/xen/xenbus/xenbus_dev.c Tue May 19 14:42:04 2009 +0100 +++ b/drivers/xen/xenbus/xenbus_dev.c Tue May 19 14:45:50 2009 +0100 @@ -53,6 +53,8 @@ #include <xen/platform-compat.h> #endif +#include <xen/public/xenbus.h> + struct xenbus_dev_transaction { struct list_head list; struct xenbus_transaction handle; @@ -95,6 +97,9 @@ static ssize_t xenbus_dev_read(struct fi struct xenbus_dev_data *u = filp->private_data; struct read_buffer *rb; int i, ret; + + if (!is_xenstored_ready()) + return -ENODEV; mutex_lock(&u->reply_mutex); while (list_empty(&u->read_buffers)) { @@ -205,6 +210,9 @@ static ssize_t xenbus_dev_write(struct f char *path, *token; struct watch_adapter *watch, *tmp_watch; int err, rc = len; + + if (!is_xenstored_ready()) + return -ENODEV; if ((len + u->len) > sizeof(u->u.buffer)) { rc = -EINVAL; @@ -370,10 +378,63 @@ static unsigned int xenbus_dev_poll(stru { struct xenbus_dev_data *u = file->private_data; + if (!is_xenstored_ready()) + return -ENODEV; + poll_wait(file, &u->read_waitq, wait); if (!list_empty(&u->read_buffers)) return POLLIN | POLLRDNORM; return 0; +} + +static long xenbus_dev_ioctl(struct file *file, + unsigned int cmd, unsigned long data) +{ + extern int xenbus_conn(domid_t remote_dom, int *grant_ref, + evtchn_port_t *local_port); + void __user *udata = (void __user *) data; + int ret = -ENOTTY; + + if (!is_initial_xendomain()) + return -ENODEV; + + + switch (cmd) { + case IOCTL_XENBUS_ALLOC: { + xenbus_alloc_t xa; + int old; + + old = atomic_cmpxchg(&xenbus_xsd_state, + XENBUS_XSD_UNCOMMITTED, + XENBUS_XSD_FOREIGN_INIT); + if (old != XENBUS_XSD_UNCOMMITTED) + return -EBUSY; + + if (copy_from_user(&xa, udata, sizeof(xa))) { + ret = -EFAULT; + atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED); + break; + } + + ret = xenbus_conn(xa.dom, &xa.grant_ref, &xa.port); + if (ret != 0) { + atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED); + break; + } + + if (copy_to_user(udata, &xa, sizeof(xa))) { + ret = -EFAULT; + atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED); + break; + } + } + break; + + default: + break; + } + + return ret; } static const struct file_operations xenbus_dev_file_ops = { @@ -382,6 +443,7 @@ static const struct file_operations xenb .open = xenbus_dev_open, .release = xenbus_dev_release, .poll = xenbus_dev_poll, + .unlocked_ioctl = xenbus_dev_ioctl }; int xenbus_dev_init(void) diff -r e17af34d4d90 -r bd7e30b58d12 drivers/xen/xenbus/xenbus_probe.c --- a/drivers/xen/xenbus/xenbus_probe.c Tue May 19 14:42:04 2009 +0100 +++ b/drivers/xen/xenbus/xenbus_probe.c Tue May 19 14:45:50 2009 +0100 @@ -44,6 +44,7 @@ #include <linux/notifier.h> #include <linux/mutex.h> #include <linux/module.h> +#include <xen/gnttab.h> #include <asm/io.h> #include <asm/page.h> @@ -347,7 +348,12 @@ static void xenbus_dev_shutdown(struct d DPRINTK("%s", dev->nodename); +/* Commented out since xenstored stubdom is now minios based not linux based +#define XENSTORE_DOMAIN_SHARES_THIS_KERNEL +*/ +#ifndef XENSTORE_DOMAIN_SHARES_THIS_KERNEL if (is_initial_xendomain()) +#endif return; get_device(&dev->dev); @@ -820,14 +826,13 @@ EXPORT_SYMBOL_GPL(xenbus_suspend_cancel) EXPORT_SYMBOL_GPL(xenbus_suspend_cancel); /* A flag to determine if xenstored is 'ready' (i.e. has started) */ -int xenstored_ready = 0; - +atomic_t xenbus_xsd_state = ATOMIC_INIT(XENBUS_XSD_UNCOMMITTED); int register_xenstore_notifier(struct notifier_block *nb) { int ret = 0; - if (xenstored_ready > 0) + if (is_xenstored_ready()) ret = nb->notifier_call(nb, 0, NULL); else blocking_notifier_chain_register(&xenstore_chain, nb); @@ -845,7 +850,7 @@ EXPORT_SYMBOL_GPL(unregister_xenstore_no void xenbus_probe(void *unused) { - BUG_ON((xenstored_ready <= 0)); + BUG_ON(!is_xenstored_ready()); /* Enumerate devices in xenstore and watch for changes. */ xenbus_probe_devices(&xenbus_frontend); @@ -865,6 +870,28 @@ static int xsd_kva_mmap(struct file *fil static int xsd_kva_mmap(struct file *file, struct vm_area_struct *vma) { size_t size = vma->vm_end - vma->vm_start; + int old; + int rc; + + old = atomic_cmpxchg(&xenbus_xsd_state, + XENBUS_XSD_UNCOMMITTED, + XENBUS_XSD_LOCAL_INIT); + switch (old) { + case XENBUS_XSD_UNCOMMITTED: + rc = xb_init_comms(); + if (rc != 0) + return rc; + break; + + case XENBUS_XSD_FOREIGN_INIT: + case XENBUS_XSD_FOREIGN_READY: + return -EBUSY; + + case XENBUS_XSD_LOCAL_INIT: + case XENBUS_XSD_LOCAL_READY: + default: + break; + } if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0)) return -EINVAL; @@ -896,6 +923,62 @@ static int xsd_port_read(char *page, cha return len; } #endif + +static int xb_free_port(evtchn_port_t port) +{ + struct evtchn_close close; + close.port = port; + return HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); +} + +int xenbus_conn(domid_t remote_dom, unsigned long *grant_ref, evtchn_port_t *local_port) +{ + struct evtchn_alloc_unbound alloc_unbound; + int rc, rc2; + + BUG_ON(atomic_read(&xenbus_xsd_state) != XENBUS_XSD_FOREIGN_INIT); + BUG_ON(!is_initial_xendomain()); + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST) + remove_xen_proc_entry("xsd_kva"); + remove_xen_proc_entry("xsd_port"); +#endif + + rc = xb_free_port(xen_store_evtchn); + if (rc != 0) + goto fail0; + + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = remote_dom; + rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, + &alloc_unbound); + if (rc != 0) + goto fail0; + *local_port = xen_store_evtchn = alloc_unbound.port; + + /* keep the old page (xen_store_mfn, xen_store_interface) */ + rc = gnttab_grant_foreign_access(remote_dom, xen_store_mfn, + GTF_permit_access); + if (rc < 0) + goto fail1; + *grant_ref = rc; + + rc = xb_init_comms(); + if (rc != 0) + goto fail1; + + return 0; + +fail1: + rc2 = xb_free_port(xen_store_evtchn); + if (rc2 != 0) + printk(KERN_WARNING + "XENBUS: Error freeing xenstore event channel: %d\n", + rc2); +fail0: + xen_store_evtchn = -1; + return rc; +} static int xenbus_probe_init(void) { @@ -958,7 +1041,7 @@ static int xenbus_probe_init(void) #endif xen_store_interface = mfn_to_virt(xen_store_mfn); } else { - xenstored_ready = 1; + atomic_set(&xenbus_xsd_state, XENBUS_XSD_FOREIGN_READY); #ifdef CONFIG_XEN xen_store_evtchn = xen_start_info->store_evtchn; xen_store_mfn = xen_start_info->store_mfn; @@ -969,8 +1052,11 @@ static int xenbus_probe_init(void) xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); #endif - } - + /* Initialize the shared memory rings to talk to xenstored */ + err = xb_init_comms(); + if (err) + goto err; + } xenbus_dev_init(); diff -r e17af34d4d90 -r bd7e30b58d12 drivers/xen/xenbus/xenbus_xs.c --- a/drivers/xen/xenbus/xenbus_xs.c Tue May 19 14:42:04 2009 +0100 +++ b/drivers/xen/xenbus/xenbus_xs.c Tue May 19 14:45:50 2009 +0100 @@ -872,7 +872,6 @@ static int xenbus_thread(void *unused) int xs_init(void) { - int err; struct task_struct *task; INIT_LIST_HEAD(&xs_state.reply_list); @@ -884,11 +883,6 @@ int xs_init(void) init_rwsem(&xs_state.transaction_mutex); init_rwsem(&xs_state.watch_mutex); - /* Initialize the shared memory rings to talk to xenstored */ - err = xb_init_comms(); - if (err) - return err; - task = kthread_run(xenwatch_thread, NULL, "xenwatch"); if (IS_ERR(task)) return PTR_ERR(task); diff -r e17af34d4d90 -r bd7e30b58d12 include/xen/public/xenbus.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/xen/public/xenbus.h Tue May 19 14:45:50 2009 +0100 @@ -0,0 +1,56 @@ +/****************************************************************************** + * xenbus.h + * + * Interface to /proc/xen/xenbus. + * + * Copyright (c) 2008, Diego Ongaro <diego.ongaro@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __LINUX_PUBLIC_XENBUS_H__ +#define __LINUX_PUBLIC_XENBUS_H__ + +#include <linux/types.h> + +#ifndef __user +#define __user +#endif + +typedef struct xenbus_alloc { + domid_t dom; + __u32 port; + __u32 grant_ref; +} xenbus_alloc_t; + +/* + * @cmd: IOCTL_XENBUS_ALLOC + * @arg: &xenbus_alloc_t + * Return: 0, or -1 for error + */ +#define IOCTL_XENBUS_ALLOC \ + _IOC(_IOC_NONE, 'X', 0, sizeof(xenbus_alloc_t)) + +#endif /* __LINUX_PUBLIC_XENBUS_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |