[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Switch block device setup/teardown over to xenbus/xenstore.



# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID b399599f2ff83fe438c66f23bb1eb8490f55a0b1
# Parent  2d7a9bae9814bae5151c9a7823fbaf3dfbd37fa2
Switch block device setup/teardown over to xenbus/xenstore.
Remove device probing support over the device channel.
g/c all the control message code.
Simplify and cleanup internal function calling code (explicit arguments
instead of passing structs around).
Also includes:
Changed "readonly" to "read-only". "backend" is still not hyphenated, but
that seems to be fairly common usage.
Block backends use xenbus_dev_error, making debugging nicer.
The block front end is told explicitly what domid to use to talk to the
backend. There's speculation that fake domid-like tokens may be given
for cluster purposes in future, so deriving from the backend dir name is
not guaranteed to work. Backends still derive front-end ids, using a
xenbus helper (xenbus_uuid_to_domid).
Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>

diff -r 2d7a9bae9814 -r b399599f2ff8 
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- /dev/null   Fri Aug 19 10:59:47 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Aug 19 12:13:31 2005
@@ -0,0 +1,309 @@
+/*  Xenbus code for blkif backend
+    Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <stdarg.h>
+#include <linux/module.h>
+#include <asm-xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+       struct xenbus_device *dev;
+
+       /* our communications channel */
+       blkif_t *blkif;
+       struct vbd *vbd;
+
+       long int frontend_id;
+       long int pdev;
+       long int readonly;
+
+       /* watch back end for changes */
+       struct xenbus_watch backend_watch;
+
+       /* watch front end for changes */
+       struct xenbus_watch watch;
+       char *frontpath;
+};
+
+static int blkback_remove(struct xenbus_device *dev)
+{
+       struct backend_info *be = dev->data;
+
+       unregister_xenbus_watch(&be->watch);
+       unregister_xenbus_watch(&be->backend_watch);
+       vbd_free(be->blkif, be->vbd);
+       blkif_put(be->blkif);
+       kfree(be->frontpath);
+       kfree(be);
+       return 0;
+}
+
+/* Front end tells us frame. */
+static void frontend_changed(struct xenbus_watch *watch, const char *node)
+{
+       unsigned long sharedmfn;
+       unsigned int evtchn;
+       int err;
+       struct backend_info *be
+               = container_of(watch, struct backend_info, watch);
+
+       // printk("Got front end event on %s (%s)\n", node, be->frontpath);
+
+       if (vbd_is_active(be->vbd)) {
+               /* If other end is gone, delete ourself. */
+               if (!xenbus_exists(be->frontpath, "")) {
+                       // printk("Removing...\n");
+                       xenbus_rm(be->dev->nodename, "");
+                       device_unregister(&be->dev->dev);
+               }
+               return;
+       }
+
+#ifndef CONFIG_XEN_BLKDEV_GRANT
+       err = xenbus_gather(be->frontpath, "shared-frame", "%lu", &sharedmfn,
+                           "event-channel", "%u", &evtchn, NULL);
+       if (err) {
+               xenbus_dev_error(be->dev, err, 
+                                "reading %s/shared-frame and event-channel",
+                                be->frontpath);
+               return;
+       }
+#else
+       err = xenbus_gather(be->frontpath, "grant-id", "%lu", &sharedmfn,
+                           "event-channel", "%u", &evtchn, NULL);
+       if (err) {
+               xenbus_dev_error(be->dev, err, 
+                                "reading %s/grant-id and event-channel",
+                                be->frontpath);
+               return;
+       }
+#endif
+
+       /* Domains must use same shared frame for all vbds. */
+       if (be->blkif->status == CONNECTED &&
+           (evtchn != be->blkif->remote_evtchn ||
+            sharedmfn != be->blkif->shmem_frame)) {
+               xenbus_dev_error(be->dev, err,
+                                "Shared frame/evtchn %li/%u not same as"
+                                " old %li/%u",
+                                sharedmfn, evtchn,
+                                be->blkif->shmem_frame,
+                                be->blkif->remote_evtchn);
+               return;
+       }
+
+       /* Supply the information about the device the frontend needs */
+       err = xenbus_transaction_start(be->dev->nodename);
+       if (err) {
+               xenbus_dev_error(be->dev, err, "starting transaction");
+               return;
+       }
+
+       err = xenbus_printf(be->dev->nodename, "sectors", "%lu",
+                           vbd_size(be->vbd));
+       if (err) {
+               xenbus_dev_error(be->dev, err, "writing %s/sectors",
+                                be->dev->nodename);
+               goto abort;
+       }
+
+       /* FIXME: use a typename instead */
+       err = xenbus_printf(be->dev->nodename, "info", "%u",
+                           vbd_info(be->vbd));
+       if (err) {
+               xenbus_dev_error(be->dev, err, "writing %s/info",
+                                be->dev->nodename);
+               goto abort;
+       }
+       err = xenbus_printf(be->dev->nodename, "sector-size", "%lu",
+                           vbd_secsize(be->vbd));
+       if (err) {
+               xenbus_dev_error(be->dev, err, "writing %s/sector-size",
+                                be->dev->nodename);
+               goto abort;
+       }
+
+       /* First vbd?  We need to map the shared frame, irq etc. */
+       if (be->blkif->status != CONNECTED) {
+               err = blkif_map(be->blkif, sharedmfn, evtchn);
+               if (err) {
+                       xenbus_dev_error(be->dev, err,
+                                        "mapping shared-frame %lu port %u",
+                                        sharedmfn, evtchn);
+                       goto abort;
+               }
+       }
+
+       /* We're ready, activate. */
+       vbd_activate(be->blkif, be->vbd);
+
+       xenbus_transaction_end(0);
+       xenbus_dev_ok(be->dev);
+
+       return;
+
+abort:
+       xenbus_transaction_end(1);
+}
+
+/* 
+   Setup supplies physical device.  
+   We provide event channel and device details to front end.
+   Frontend supplies shared frame and event channel.
+ */
+static void backend_changed(struct xenbus_watch *watch, const char *node)
+{
+       int err;
+       char *p;
+       char *frontend;
+       long int handle, pdev;
+       struct backend_info *be
+               = container_of(watch, struct backend_info, backend_watch);
+       struct xenbus_device *dev = be->dev;
+
+       err = xenbus_scanf(dev->nodename, "frontend-id", "%li",
+                          &be->frontend_id);
+       if (err == -ENOENT || err == -ERANGE)
+               goto out;
+       if (err < 0) {
+               xenbus_dev_error(dev, err, "Reading frontend-id");
+               goto out;
+       }
+
+       err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
+       if (err == -ENOENT || err == -ERANGE)
+               goto out;
+       if (err < 0) {
+               xenbus_dev_error(dev, err, "Reading physical-device");
+               goto out;
+       }
+       if (be->pdev && be->pdev != pdev) {
+               printk(KERN_WARNING
+                      "changing physical-device not supported\n");
+               return;
+       }
+       be->pdev = pdev;
+
+       frontend = xenbus_read(dev->nodename, "frontend", NULL);
+       if (IS_ERR(frontend))
+               return;
+       if (strlen(frontend) == 0) {
+               kfree(frontend);
+               return;
+       }
+
+       /* If there's a read-only node, we're read only. */
+       p = xenbus_read(dev->nodename, "read-only", NULL);
+       if (!IS_ERR(p)) {
+               be->readonly = 1;
+               kfree(p);
+       }
+
+       if (!be->frontpath || strcmp(frontend, be->frontpath)) {
+               if (be->watch.node)
+                       unregister_xenbus_watch(&be->watch);
+               if (be->frontpath)
+                       kfree(be->frontpath);
+               be->frontpath = frontend;
+               be->watch.node = be->frontpath;
+               be->watch.callback = frontend_changed;
+               err = register_xenbus_watch(&be->watch);
+               if (err)
+                       goto out;
+
+               /* Front end dir is a number, which is used as the handle. */
+               p = strrchr(be->frontpath, '/') + 1;
+               handle = simple_strtoul(p, NULL, 0);
+
+               be->blkif = blkif_find(be->frontend_id);
+               if (IS_ERR(be->blkif)) {
+                       err = PTR_ERR(be->blkif);
+                       be->blkif = NULL;
+                       goto free_watch;
+               }
+
+               be->vbd = vbd_create(be->blkif, handle, be->pdev,
+                                    be->readonly);
+               if (IS_ERR(be->vbd)) {
+                       err = PTR_ERR(be->vbd);
+                       blkif_put(be->blkif);
+                       be->blkif = NULL;
+                       be->vbd = NULL;
+                       goto free_watch;
+               }
+
+               frontend_changed(&be->watch, be->frontpath);
+       } else
+               kfree(frontend);
+
+       return;
+
+ free_watch:
+       unregister_xenbus_watch(&be->watch);
+       be->watch.node = NULL;
+       kfree(be->frontpath);
+       be->frontpath = NULL;
+ out:
+       return;
+}
+
+static int blkback_probe(struct xenbus_device *dev,
+                        const struct xenbus_device_id *id)
+{
+       struct backend_info *be;
+       int err;
+
+       be = kmalloc(sizeof(*be), GFP_KERNEL);
+       if (!be)
+               return -ENOMEM;
+
+       memset(be, 0, sizeof(*be));
+
+       be->dev = dev;
+       be->backend_watch.node = dev->nodename;
+       be->backend_watch.callback = backend_changed;
+       err = register_xenbus_watch(&be->backend_watch);
+       if (err)
+               goto free_be;
+
+       dev->data = be;
+
+       backend_changed(&be->backend_watch, dev->nodename);
+       return err;
+ free_be:
+       kfree(be);
+       return err;
+}
+
+static struct xenbus_device_id blkback_ids[] = {
+       { "vbd" },
+       { "" }
+};
+
+static struct xenbus_driver blkback = {
+       .name = __stringify(KBUILD_MODNAME),
+       .owner = THIS_MODULE,
+       .ids = blkback_ids,
+       .probe = blkback_probe,
+       .remove = blkback_remove,
+};
+
+void blkif_xenbus_init(void)
+{
+       xenbus_register_backend(&blkback);
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.