xen-vtx-unstable

annotate linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @ 6774:4d899a738d59

merge?
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 15:05:49 2005 +0000 (2005-09-13)
parents 219d96d545fc b6c98fe62e1a
children e7c7196fa329 8ca0f98ba8e2
rev   line source
cl349@6262 1 /* Xenbus code for blkif backend
cl349@6262 2 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
cl349@6262 3
cl349@6262 4 This program is free software; you can redistribute it and/or modify
cl349@6262 5 it under the terms of the GNU General Public License as published by
cl349@6262 6 the Free Software Foundation; either version 2 of the License, or
cl349@6262 7 (at your option) any later version.
cl349@6262 8
cl349@6262 9 This program is distributed in the hope that it will be useful,
cl349@6262 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
cl349@6262 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
cl349@6262 12 GNU General Public License for more details.
cl349@6262 13
cl349@6262 14 You should have received a copy of the GNU General Public License
cl349@6262 15 along with this program; if not, write to the Free Software
cl349@6262 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
cl349@6262 17 */
cl349@6262 18 #include <stdarg.h>
cl349@6262 19 #include <linux/module.h>
cl349@6262 20 #include <asm-xen/xenbus.h>
cl349@6262 21 #include "common.h"
cl349@6262 22
cl349@6262 23 struct backend_info
cl349@6262 24 {
cl349@6262 25 struct xenbus_device *dev;
cl349@6262 26
cl349@6262 27 /* our communications channel */
cl349@6262 28 blkif_t *blkif;
cl349@6262 29
cl349@6262 30 long int frontend_id;
cl349@6262 31 long int pdev;
cl349@6262 32 long int readonly;
cl349@6262 33
cl349@6262 34 /* watch back end for changes */
cl349@6262 35 struct xenbus_watch backend_watch;
cl349@6262 36
cl349@6262 37 /* watch front end for changes */
cl349@6262 38 struct xenbus_watch watch;
cl349@6262 39 char *frontpath;
cl349@6262 40 };
cl349@6262 41
cl349@6262 42 static int blkback_remove(struct xenbus_device *dev)
cl349@6262 43 {
cl349@6262 44 struct backend_info *be = dev->data;
cl349@6262 45
cl349@6263 46 if (be->watch.node)
cl349@6263 47 unregister_xenbus_watch(&be->watch);
cl349@6262 48 unregister_xenbus_watch(&be->backend_watch);
cl349@6263 49 if (be->blkif)
cl349@6263 50 blkif_put(be->blkif);
cl349@6263 51 if (be->frontpath)
cl349@6263 52 kfree(be->frontpath);
cl349@6262 53 kfree(be);
cl349@6262 54 return 0;
cl349@6262 55 }
cl349@6262 56
cl349@6262 57 /* Front end tells us frame. */
cl349@6262 58 static void frontend_changed(struct xenbus_watch *watch, const char *node)
cl349@6262 59 {
cl349@6387 60 unsigned long ring_ref;
cl349@6262 61 unsigned int evtchn;
cl349@6262 62 int err;
cl349@6262 63 struct backend_info *be
cl349@6262 64 = container_of(watch, struct backend_info, watch);
cl349@6262 65
cl349@6263 66 /* If other end is gone, delete ourself. */
cl349@6384 67 if (node && !xenbus_exists(be->frontpath, "")) {
cl349@6263 68 device_unregister(&be->dev->dev);
cl349@6262 69 return;
cl349@6262 70 }
cl349@6386 71 if (be->blkif == NULL || be->blkif->status == CONNECTED)
cl349@6263 72 return;
cl349@6262 73
cl349@6387 74 err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
cl349@6262 75 "event-channel", "%u", &evtchn, NULL);
cl349@6262 76 if (err) {
cl349@6372 77 xenbus_dev_error(be->dev, err,
cl349@6387 78 "reading %s/ring-ref and event-channel",
cl349@6262 79 be->frontpath);
cl349@6262 80 return;
cl349@6262 81 }
cl349@6262 82
cl349@6262 83 /* Supply the information about the device the frontend needs */
cl349@6262 84 err = xenbus_transaction_start(be->dev->nodename);
cl349@6262 85 if (err) {
cl349@6262 86 xenbus_dev_error(be->dev, err, "starting transaction");
cl349@6262 87 return;
cl349@6262 88 }
cl349@6262 89
cl349@6262 90 err = xenbus_printf(be->dev->nodename, "sectors", "%lu",
cl349@6353 91 vbd_size(&be->blkif->vbd));
cl349@6262 92 if (err) {
cl349@6262 93 xenbus_dev_error(be->dev, err, "writing %s/sectors",
cl349@6262 94 be->dev->nodename);
cl349@6262 95 goto abort;
cl349@6262 96 }
cl349@6262 97
cl349@6262 98 /* FIXME: use a typename instead */
cl349@6262 99 err = xenbus_printf(be->dev->nodename, "info", "%u",
cl349@6353 100 vbd_info(&be->blkif->vbd));
cl349@6262 101 if (err) {
cl349@6262 102 xenbus_dev_error(be->dev, err, "writing %s/info",
cl349@6262 103 be->dev->nodename);
cl349@6262 104 goto abort;
cl349@6262 105 }
cl349@6262 106 err = xenbus_printf(be->dev->nodename, "sector-size", "%lu",
cl349@6353 107 vbd_secsize(&be->blkif->vbd));
cl349@6262 108 if (err) {
cl349@6262 109 xenbus_dev_error(be->dev, err, "writing %s/sector-size",
cl349@6262 110 be->dev->nodename);
cl349@6262 111 goto abort;
cl349@6262 112 }
cl349@6262 113
cl349@6358 114 /* Map the shared frame, irq etc. */
cl349@6387 115 err = blkif_map(be->blkif, ring_ref, evtchn);
cl349@6358 116 if (err) {
cl349@6387 117 xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
cl349@6387 118 ring_ref, evtchn);
cl349@6358 119 goto abort;
cl349@6262 120 }
cl349@6262 121
cl349@6262 122 xenbus_transaction_end(0);
cl349@6262 123 xenbus_dev_ok(be->dev);
cl349@6262 124
cl349@6262 125 return;
cl349@6262 126
cl349@6262 127 abort:
cl349@6262 128 xenbus_transaction_end(1);
cl349@6262 129 }
cl349@6262 130
cl349@6262 131 /*
cl349@6262 132 Setup supplies physical device.
cl349@6262 133 We provide event channel and device details to front end.
cl349@6262 134 Frontend supplies shared frame and event channel.
cl349@6262 135 */
cl349@6262 136 static void backend_changed(struct xenbus_watch *watch, const char *node)
cl349@6262 137 {
cl349@6262 138 int err;
cl349@6262 139 char *p;
cl349@6262 140 long int handle, pdev;
cl349@6262 141 struct backend_info *be
cl349@6262 142 = container_of(watch, struct backend_info, backend_watch);
cl349@6262 143 struct xenbus_device *dev = be->dev;
cl349@6262 144
cl349@6263 145 err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
cl349@6283 146 if (XENBUS_EXIST_ERR(err))
cl349@6384 147 return;
cl349@6263 148 if (err < 0) {
cl349@6283 149 xenbus_dev_error(dev, err, "reading physical-device");
cl349@6384 150 return;
cl349@6263 151 }
cl349@6263 152 if (be->pdev && be->pdev != pdev) {
cl349@6263 153 printk(KERN_WARNING
cl349@6263 154 "changing physical-device not supported\n");
cl349@6384 155 return;
cl349@6263 156 }
cl349@6263 157 be->pdev = pdev;
cl349@6263 158
cl349@6263 159 /* If there's a read-only node, we're read only. */
cl349@6263 160 p = xenbus_read(dev->nodename, "read-only", NULL);
cl349@6263 161 if (!IS_ERR(p)) {
cl349@6263 162 be->readonly = 1;
cl349@6263 163 kfree(p);
cl349@6263 164 }
cl349@6263 165
cl349@6263 166 if (be->blkif == NULL) {
cl349@6262 167 /* Front end dir is a number, which is used as the handle. */
cl349@6262 168 p = strrchr(be->frontpath, '/') + 1;
cl349@6262 169 handle = simple_strtoul(p, NULL, 0);
cl349@6262 170
cl349@6352 171 be->blkif = alloc_blkif(be->frontend_id);
cl349@6262 172 if (IS_ERR(be->blkif)) {
cl349@6262 173 err = PTR_ERR(be->blkif);
cl349@6262 174 be->blkif = NULL;
cl349@6372 175 xenbus_dev_error(dev, err, "creating block interface");
cl349@6384 176 return;
cl349@6262 177 }
cl349@6262 178
cl349@6353 179 err = vbd_create(be->blkif, handle, be->pdev, be->readonly);
cl349@6372 180 if (err) {
cl349@6372 181 xenbus_dev_error(dev, err, "creating vbd structure");
cl349@6384 182 return;
cl349@6372 183 }
cl349@6262 184
cl349@6384 185 /* Pass in NULL node to skip exist test. */
cl349@6384 186 frontend_changed(&be->watch, NULL);
cl349@6263 187 }
cl349@6262 188 }
cl349@6262 189
cl349@6262 190 static int blkback_probe(struct xenbus_device *dev,
cl349@6262 191 const struct xenbus_device_id *id)
cl349@6262 192 {
cl349@6262 193 struct backend_info *be;
cl349@6384 194 char *frontend;
cl349@6262 195 int err;
cl349@6262 196
cl349@6262 197 be = kmalloc(sizeof(*be), GFP_KERNEL);
cl349@6372 198 if (!be) {
cl349@6372 199 xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
cl349@6262 200 return -ENOMEM;
cl349@6372 201 }
cl349@6262 202 memset(be, 0, sizeof(*be));
cl349@6262 203
cl349@6384 204 frontend = NULL;
cl349@6384 205 err = xenbus_gather(dev->nodename,
cl349@6384 206 "frontend-id", "%li", &be->frontend_id,
cl349@6384 207 "frontend", NULL, &frontend,
cl349@6384 208 NULL);
cl349@6384 209 if (XENBUS_EXIST_ERR(err))
cl349@6384 210 goto free_be;
cl349@6385 211 if (err < 0) {
cl349@6385 212 xenbus_dev_error(dev, err,
cl349@6385 213 "reading %s/frontend or frontend-id",
cl349@6385 214 dev->nodename);
cl349@6385 215 goto free_be;
cl349@6385 216 }
cl349@6385 217 if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
cl349@6384 218 /* If we can't get a frontend path and a frontend-id,
cl349@6384 219 * then our bus-id is no longer valid and we need to
cl349@6384 220 * destroy the backend device.
cl349@6384 221 */
cl349@6385 222 err = -ENOENT;
cl349@6384 223 goto free_be;
cl349@6384 224 }
cl349@6385 225
cl349@6385 226 be->dev = dev;
cl349@6385 227 be->backend_watch.node = dev->nodename;
cl349@6385 228 be->backend_watch.callback = backend_changed;
cl349@6385 229 err = register_xenbus_watch(&be->backend_watch);
cl349@6385 230 if (err) {
cl349@6385 231 be->backend_watch.node = NULL;
cl349@6385 232 xenbus_dev_error(dev, err, "adding backend watch on %s",
cl349@6384 233 dev->nodename);
cl349@6384 234 goto free_be;
cl349@6384 235 }
cl349@6384 236
cl349@6384 237 be->frontpath = frontend;
cl349@6384 238 be->watch.node = be->frontpath;
cl349@6384 239 be->watch.callback = frontend_changed;
cl349@6384 240 err = register_xenbus_watch(&be->watch);
cl349@6384 241 if (err) {
cl349@6384 242 be->watch.node = NULL;
cl349@6384 243 xenbus_dev_error(dev, err,
cl349@6384 244 "adding frontend watch on %s",
cl349@6384 245 be->frontpath);
cl349@6384 246 goto free_be;
cl349@6384 247 }
cl349@6384 248
cl349@6385 249 dev->data = be;
cl349@6385 250
cl349@6262 251 backend_changed(&be->backend_watch, dev->nodename);
cl349@6385 252 return 0;
cl349@6384 253
cl349@6262 254 free_be:
cl349@6385 255 if (be->backend_watch.node)
cl349@6385 256 unregister_xenbus_watch(&be->backend_watch);
cl349@6384 257 if (frontend)
cl349@6384 258 kfree(frontend);
cl349@6262 259 kfree(be);
cl349@6262 260 return err;
cl349@6262 261 }
cl349@6262 262
cl349@6262 263 static struct xenbus_device_id blkback_ids[] = {
cl349@6262 264 { "vbd" },
cl349@6262 265 { "" }
cl349@6262 266 };
cl349@6262 267
cl349@6262 268 static struct xenbus_driver blkback = {
cl349@6263 269 .name = "vbd",
cl349@6262 270 .owner = THIS_MODULE,
cl349@6262 271 .ids = blkback_ids,
cl349@6262 272 .probe = blkback_probe,
cl349@6262 273 .remove = blkback_remove,
cl349@6262 274 };
cl349@6262 275
cl349@6262 276 void blkif_xenbus_init(void)
cl349@6262 277 {
cl349@6262 278 xenbus_register_backend(&blkback);
cl349@6262 279 }