WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 3/3] [linux-2.6.18-xen.hg] delay xenbus init if xenbu

To: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 3/3] [linux-2.6.18-xen.hg] delay xenbus init if xenbus master is a separate domain
From: Alex Zeffertt <alex.zeffertt@xxxxxxxxxxxxx>
Date: Mon, 23 Mar 2009 15:20:12 +0000
Delivery-date: Mon, 23 Mar 2009 08:22:42 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 2.0.0.19 (X11/20090105)

This patch modifies xenbus to lazily initialize. This is necessary when
xenstored is running in a seperate minios domain, since it can't connect as a
slave just yet.

Ian Campbell has looked at an earlier version of this patch, and seems
to generally approve.

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.

TODO: The types in the IOCTL might not be correct.

Signed-off-by: Diego Ongaro <diego.ongaro@xxxxxxxxxx>
Signed-off-by: Alex Zeffertt <alex.zeffertt@xxxxxxxxxxxxx>
---

diff -r e68a58170585 drivers/xen/core/xen_sysfs.c
--- a/drivers/xen/core/xen_sysfs.c      Mon Mar 16 17:02:03 2009 +0000
+++ b/drivers/xen/core/xen_sysfs.c      Thu Mar 19 10:46:26 2009 +0000
@@ -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 @@
 {
        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 e68a58170585 drivers/xen/xenbus/xenbus_comms.c
--- a/drivers/xen/xenbus/xenbus_comms.c Mon Mar 16 17:02:03 2009 +0000
+++ b/drivers/xen/xenbus/xenbus_comms.c Thu Mar 19 10:46:26 2009 +0000
@@ -50,18 +50,39 @@
 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;
-               schedule_work(&probe_work);
+       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 e68a58170585 drivers/xen/xenbus/xenbus_comms.h
--- a/drivers/xen/xenbus/xenbus_comms.h Mon Mar 16 17:02:03 2009 +0000
+++ b/drivers/xen/xenbus/xenbus_comms.h Thu Mar 19 10:46:26 2009 +0000
@@ -43,4 +43,20 @@
 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 e68a58170585 drivers/xen/xenbus/xenbus_dev.c
--- a/drivers/xen/xenbus/xenbus_dev.c   Mon Mar 16 17:02:03 2009 +0000
+++ b/drivers/xen/xenbus/xenbus_dev.c   Thu Mar 19 10:46:26 2009 +0000
@@ -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 @@
        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 @@
        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;
@@ -391,10 +399,63 @@
 {
        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 = {
@@ -403,6 +464,7 @@
        .open = xenbus_dev_open,
        .release = xenbus_dev_release,
        .poll = xenbus_dev_poll,
+       .unlocked_ioctl = xenbus_dev_ioctl
 };
 
 int xenbus_dev_init(void)
diff -r e68a58170585 drivers/xen/xenbus/xenbus_probe.c
--- a/drivers/xen/xenbus/xenbus_probe.c Mon Mar 16 17:02:03 2009 +0000
+++ b/drivers/xen/xenbus/xenbus_probe.c Thu Mar 19 10:46:26 2009 +0000
@@ -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 @@
 
        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);
 
 /* 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 @@
 
 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 *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 @@
        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 @@
 #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 @@
                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 e68a58170585 drivers/xen/xenbus/xenbus_xs.c
--- a/drivers/xen/xenbus/xenbus_xs.c    Mon Mar 16 17:02:03 2009 +0000
+++ b/drivers/xen/xenbus/xenbus_xs.c    Thu Mar 19 10:46:26 2009 +0000
@@ -872,7 +872,6 @@
 
 int xs_init(void)
 {
-       int err;
        struct task_struct *task;
 
        INIT_LIST_HEAD(&xs_state.reply_list);
@@ -883,11 +882,6 @@
        mutex_init(&xs_state.response_mutex);
        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))
diff -r e68a58170585 include/xen/public/xenbus.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/include/xen/public/xenbus.h       Thu Mar 19 10:46:26 2009 +0000
@@ -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-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 3/3] [linux-2.6.18-xen.hg] delay xenbus init if xenbus master is a separate domain, Alex Zeffertt <=