ia64/xen-unstable

annotate linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @ 6766:219d96d545fc

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