[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |