direct-io.hg
changeset 7775:bf7c16e761fc
New Xenbus driver structure, bringing an explicit state machine to the table.
This will make the drivers more robust to failure of the other end, and makes
current driver state more visible. It also allows us to bring very similar
pieces of code from the drivers together into the xenbus driver. This should
be the start of a fix to the problem with block and net device hotplugging,
because the code was previously confused about the difference between the
connection state of the kernel device layer, and the state of the xenbus
communication. This confusion is addressed here.
Much of this work is influenced by Rusty Russell's skeleton driver, recently
posted to xen-devel, as that piece made suggestions as to structure and
arrangement that have been taken on board, albeit pushed down into the xenbus
layer.
A new file xenbus_client.c has been added. This file implements the interface
between the xenbus layer and the layer specific to the driver. Access to
lower layers is still allowed for those who do not need all the facilities of
the new driver.
xenbus_dev_error has moved from xenbus_xs.c into xenbus_client.c, and
xenbus_dev_ok has been removed, in favour of xenbus_switch_state.
DevController.py now closes down a device by writing a change to the Closing
state on the backend, to allow the frontend time to close down properly. Its
also writes the frontend and backend details within the same transaction.
The timeout on the hotplug scripts has been cranked down from 2 minutes to 5
seconds.
The diagnose script has been updated to parse the new states.
The blktab and tpm drivers have yet to be ported to this structure.
Signed-off-by: Ewan Mellor <ewan@xensource.com>
This will make the drivers more robust to failure of the other end, and makes
current driver state more visible. It also allows us to bring very similar
pieces of code from the drivers together into the xenbus driver. This should
be the start of a fix to the problem with block and net device hotplugging,
because the code was previously confused about the difference between the
connection state of the kernel device layer, and the state of the xenbus
communication. This confusion is addressed here.
Much of this work is influenced by Rusty Russell's skeleton driver, recently
posted to xen-devel, as that piece made suggestions as to structure and
arrangement that have been taken on board, albeit pushed down into the xenbus
layer.
A new file xenbus_client.c has been added. This file implements the interface
between the xenbus layer and the layer specific to the driver. Access to
lower layers is still allowed for those who do not need all the facilities of
the new driver.
xenbus_dev_error has moved from xenbus_xs.c into xenbus_client.c, and
xenbus_dev_ok has been removed, in favour of xenbus_switch_state.
DevController.py now closes down a device by writing a change to the Closing
state on the backend, to allow the frontend time to close down properly. Its
also writes the frontend and backend details within the same transaction.
The timeout on the hotplug scripts has been cranked down from 2 minutes to 5
seconds.
The diagnose script has been updated to parse the new states.
The blktab and tpm drivers have yet to be ported to this structure.
Signed-off-by: Ewan Mellor <ewan@xensource.com>
line diff
1.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Nov 11 18:01:44 2005 +0100 1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Nov 11 21:59:05 2005 +0100 1.3 @@ -1,5 +1,6 @@ 1.4 /* Xenbus code for blkif backend 1.5 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au> 1.6 + Copyright (C) 2005 XenSource Ltd 1.7 1.8 This program is free software; you can redistribute it and/or modify 1.9 it under the terms of the GNU General Public License as published by 1.10 @@ -15,160 +16,142 @@ 1.11 along with this program; if not, write to the Free Software 1.12 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.13 */ 1.14 + 1.15 + 1.16 #include <stdarg.h> 1.17 #include <linux/module.h> 1.18 #include <asm-xen/xenbus.h> 1.19 #include "common.h" 1.20 1.21 + 1.22 +#if 0 1.23 +#undef DPRINTK 1.24 +#define DPRINTK(fmt, args...) \ 1.25 + printk("blkback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) 1.26 +#endif 1.27 + 1.28 + 1.29 struct backend_info 1.30 { 1.31 struct xenbus_device *dev; 1.32 + blkif_t *blkif; 1.33 + struct xenbus_watch backend_watch; 1.34 1.35 - /* our communications channel */ 1.36 - blkif_t *blkif; 1.37 - 1.38 - long int frontend_id; 1.39 long int pdev; 1.40 long int readonly; 1.41 +}; 1.42 1.43 - /* watch back end for changes */ 1.44 - struct xenbus_watch backend_watch; 1.45 1.46 - /* watch front end for changes */ 1.47 - struct xenbus_watch watch; 1.48 - char *frontpath; 1.49 -}; 1.50 +static void maybe_connect(struct backend_info *); 1.51 +static void connect(struct backend_info *); 1.52 +static int connect_ring(struct backend_info *); 1.53 +static void backend_changed(struct xenbus_watch *, const char **, 1.54 + unsigned int); 1.55 + 1.56 1.57 static int blkback_remove(struct xenbus_device *dev) 1.58 { 1.59 struct backend_info *be = dev->data; 1.60 1.61 - if (be->watch.node) 1.62 - unregister_xenbus_watch(&be->watch); 1.63 - unregister_xenbus_watch(&be->backend_watch); 1.64 - if (be->blkif) 1.65 + DPRINTK(""); 1.66 + 1.67 + if (be->backend_watch.node) { 1.68 + unregister_xenbus_watch(&be->backend_watch); 1.69 + kfree(be->backend_watch.node); 1.70 + be->backend_watch.node = NULL; 1.71 + } 1.72 + if (be->blkif) { 1.73 blkif_put(be->blkif); 1.74 - kfree(be->frontpath); 1.75 + be->blkif = NULL; 1.76 + } 1.77 kfree(be); 1.78 + dev->data = NULL; 1.79 return 0; 1.80 } 1.81 1.82 -/* Front end tells us frame. */ 1.83 -static void frontend_changed(struct xenbus_watch *watch, 1.84 - const char **vec, unsigned int len) 1.85 -{ 1.86 - unsigned long ring_ref; 1.87 - unsigned int evtchn; 1.88 - int err; 1.89 - struct xenbus_transaction *xbt; 1.90 - struct backend_info *be 1.91 - = container_of(watch, struct backend_info, watch); 1.92 - 1.93 - /* If other end is gone, delete ourself. */ 1.94 - if (vec && !xenbus_exists(NULL, be->frontpath, "")) { 1.95 - device_unregister(&be->dev->dev); 1.96 - return; 1.97 - } 1.98 - if (be->blkif == NULL || be->blkif->status == CONNECTED) 1.99 - return; 1.100 1.101 - err = xenbus_gather(NULL, be->frontpath, "ring-ref", "%lu", &ring_ref, 1.102 - "event-channel", "%u", &evtchn, NULL); 1.103 - if (err) { 1.104 - xenbus_dev_error(be->dev, err, 1.105 - "reading %s/ring-ref and event-channel", 1.106 - be->frontpath); 1.107 - return; 1.108 +/** 1.109 + * Entry point to this code when a new device is created. Allocate the basic 1.110 + * structures, and watch the store waiting for the hotplug scripts to tell us 1.111 + * the device's physical-device. Switch to InitWait. 1.112 + */ 1.113 +static int blkback_probe(struct xenbus_device *dev, 1.114 + const struct xenbus_device_id *id) 1.115 +{ 1.116 + int err; 1.117 + struct backend_info *be = kmalloc(sizeof(struct backend_info), 1.118 + GFP_KERNEL); 1.119 + if (!be) { 1.120 + xenbus_dev_fatal(dev, -ENOMEM, 1.121 + "allocating backend structure"); 1.122 + return -ENOMEM; 1.123 } 1.124 + memset(be, 0, sizeof(*be)); 1.125 1.126 - /* Map the shared frame, irq etc. */ 1.127 - err = blkif_map(be->blkif, ring_ref, evtchn); 1.128 - if (err) { 1.129 - xenbus_dev_error(be->dev, err, 1.130 - "mapping ring-ref %lu port %u", 1.131 - ring_ref, evtchn); 1.132 - return; 1.133 - } 1.134 - /* XXX From here on should 'blkif_unmap' on error. */ 1.135 + be->dev = dev; 1.136 + dev->data = be; 1.137 1.138 -again: 1.139 - /* Supply the information about the device the frontend needs */ 1.140 - xbt = xenbus_transaction_start(); 1.141 - if (IS_ERR(xbt)) { 1.142 - xenbus_dev_error(be->dev, err, "starting transaction"); 1.143 - return; 1.144 + be->blkif = alloc_blkif(dev->otherend_id); 1.145 + if (IS_ERR(be->blkif)) { 1.146 + err = PTR_ERR(be->blkif); 1.147 + be->blkif = NULL; 1.148 + xenbus_dev_fatal(dev, err, "creating block interface"); 1.149 + goto fail; 1.150 } 1.151 1.152 - err = xenbus_printf(xbt, be->dev->nodename, "sectors", "%lu", 1.153 - vbd_size(&be->blkif->vbd)); 1.154 - if (err) { 1.155 - xenbus_dev_error(be->dev, err, "writing %s/sectors", 1.156 - be->dev->nodename); 1.157 - goto abort; 1.158 - } 1.159 + err = xenbus_watch_path2(dev, dev->nodename, "physical-device", 1.160 + &be->backend_watch, backend_changed); 1.161 + if (err) 1.162 + goto fail; 1.163 1.164 - /* FIXME: use a typename instead */ 1.165 - err = xenbus_printf(xbt, be->dev->nodename, "info", "%u", 1.166 - vbd_info(&be->blkif->vbd)); 1.167 - if (err) { 1.168 - xenbus_dev_error(be->dev, err, "writing %s/info", 1.169 - be->dev->nodename); 1.170 - goto abort; 1.171 - } 1.172 - err = xenbus_printf(xbt, be->dev->nodename, "sector-size", "%lu", 1.173 - vbd_secsize(&be->blkif->vbd)); 1.174 - if (err) { 1.175 - xenbus_dev_error(be->dev, err, "writing %s/sector-size", 1.176 - be->dev->nodename); 1.177 - goto abort; 1.178 - } 1.179 + err = xenbus_switch_state(dev, NULL, XenbusStateInitWait); 1.180 + if (err) 1.181 + goto fail; 1.182 1.183 - err = xenbus_transaction_end(xbt, 0); 1.184 - if (err == -EAGAIN) 1.185 - goto again; 1.186 - if (err) { 1.187 - xenbus_dev_error(be->dev, err, "ending transaction", 1.188 - ring_ref, evtchn); 1.189 - goto abort; 1.190 - } 1.191 + return 0; 1.192 1.193 - xenbus_dev_ok(be->dev); 1.194 - 1.195 - return; 1.196 - 1.197 - abort: 1.198 - xenbus_transaction_end(xbt, 1); 1.199 +fail: 1.200 + DPRINTK("failed"); 1.201 + blkback_remove(dev); 1.202 + return err; 1.203 } 1.204 1.205 -/* 1.206 - Setup supplies physical device. 1.207 - We provide event channel and device details to front end. 1.208 - Frontend supplies shared frame and event channel. 1.209 + 1.210 +/** 1.211 + * Callback received when the hotplug scripts have placed the physical-device 1.212 + * node. Read it and the read-only node, and create a vbd. If the frontend 1.213 + * is ready, connect. 1.214 */ 1.215 static void backend_changed(struct xenbus_watch *watch, 1.216 const char **vec, unsigned int len) 1.217 { 1.218 int err; 1.219 char *p; 1.220 - long int handle, pdev; 1.221 + long pdev; 1.222 struct backend_info *be 1.223 = container_of(watch, struct backend_info, backend_watch); 1.224 struct xenbus_device *dev = be->dev; 1.225 1.226 + DPRINTK(""); 1.227 + 1.228 err = xenbus_scanf(NULL, dev->nodename, 1.229 "physical-device", "%li", &pdev); 1.230 - if (XENBUS_EXIST_ERR(err)) 1.231 + if (XENBUS_EXIST_ERR(err)) { 1.232 + /* Since this watch will fire once immediately after it is 1.233 + registered, we expect this. Ignore it, and wait for the 1.234 + hotplug scripts. */ 1.235 return; 1.236 - if (err < 0) { 1.237 - xenbus_dev_error(dev, err, "reading physical-device"); 1.238 + } 1.239 + if (err != 1) { 1.240 + xenbus_dev_fatal(dev, err, "reading physical-device"); 1.241 return; 1.242 } 1.243 if (be->pdev && be->pdev != pdev) { 1.244 printk(KERN_WARNING 1.245 - "changing physical-device not supported\n"); 1.246 + "blkback: changing physical-device (from %ld to %ld) " 1.247 + "not supported.\n", be->pdev, pdev); 1.248 return; 1.249 } 1.250 - be->pdev = pdev; 1.251 1.252 /* If there's a read-only node, we're read only. */ 1.253 p = xenbus_read(NULL, dev->nodename, "read-only", NULL); 1.254 @@ -177,125 +160,198 @@ static void backend_changed(struct xenbu 1.255 kfree(p); 1.256 } 1.257 1.258 - if (be->blkif == NULL) { 1.259 + if (be->pdev == 0L) { 1.260 /* Front end dir is a number, which is used as the handle. */ 1.261 - p = strrchr(be->frontpath, '/') + 1; 1.262 + 1.263 + long handle; 1.264 + 1.265 + p = strrchr(dev->otherend, '/') + 1; 1.266 handle = simple_strtoul(p, NULL, 0); 1.267 1.268 - be->blkif = alloc_blkif(be->frontend_id); 1.269 - if (IS_ERR(be->blkif)) { 1.270 - err = PTR_ERR(be->blkif); 1.271 - be->blkif = NULL; 1.272 - xenbus_dev_error(dev, err, 1.273 - "creating block interface"); 1.274 - return; 1.275 - } 1.276 + be->pdev = pdev; 1.277 1.278 err = vbd_create(be->blkif, handle, be->pdev, be->readonly); 1.279 if (err) { 1.280 - blkif_put(be->blkif); 1.281 - be->blkif = NULL; 1.282 - xenbus_dev_error(dev, err, 1.283 + be->pdev = 0L; 1.284 + xenbus_dev_fatal(dev, err, 1.285 "creating vbd structure"); 1.286 return; 1.287 } 1.288 1.289 - /* Pass in NULL node to skip exist test. */ 1.290 - frontend_changed(&be->watch, NULL, 0); 1.291 + maybe_connect(be); 1.292 + } 1.293 +} 1.294 + 1.295 + 1.296 +/** 1.297 + * Callback received when the frontend's state changes. 1.298 + */ 1.299 +static void frontend_changed(struct xenbus_device *dev, 1.300 + XenbusState frontend_state) 1.301 +{ 1.302 + struct backend_info *be = dev->data; 1.303 + int err; 1.304 + 1.305 + DPRINTK(""); 1.306 + 1.307 + switch (frontend_state) { 1.308 + case XenbusStateInitialising: 1.309 + case XenbusStateConnected: 1.310 + break; 1.311 + 1.312 + case XenbusStateInitialised: 1.313 + err = connect_ring(be); 1.314 + if (err) { 1.315 + return; 1.316 + } 1.317 + maybe_connect(be); 1.318 + break; 1.319 + 1.320 + case XenbusStateClosing: 1.321 + xenbus_switch_state(dev, NULL, XenbusStateClosing); 1.322 + break; 1.323 + 1.324 + case XenbusStateClosed: 1.325 + device_unregister(&dev->dev); 1.326 + break; 1.327 + 1.328 + case XenbusStateUnknown: 1.329 + case XenbusStateInitWait: 1.330 + default: 1.331 + xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", 1.332 + frontend_state); 1.333 + break; 1.334 + } 1.335 +} 1.336 + 1.337 + 1.338 +/* ** Connection ** */ 1.339 + 1.340 + 1.341 +static void maybe_connect(struct backend_info *be) 1.342 +{ 1.343 + if (be->pdev != 0L && be->blkif->status == CONNECTED) { 1.344 + connect(be); 1.345 } 1.346 } 1.347 1.348 -static int blkback_probe(struct xenbus_device *dev, 1.349 - const struct xenbus_device_id *id) 1.350 + 1.351 +/** 1.352 + * Write the physical details regarding the block device to the store, and 1.353 + * switch to Connected state. 1.354 + */ 1.355 +static void connect(struct backend_info *be) 1.356 { 1.357 - struct backend_info *be; 1.358 - char *frontend; 1.359 + struct xenbus_transaction *xbt; 1.360 + int err; 1.361 + struct xenbus_device *dev = be->dev; 1.362 + 1.363 + DPRINTK("%s", dev->otherend); 1.364 + 1.365 + /* Supply the information about the device the frontend needs */ 1.366 +again: 1.367 + xbt = xenbus_transaction_start(); 1.368 + 1.369 + if (IS_ERR(xbt)) { 1.370 + err = PTR_ERR(xbt); 1.371 + xenbus_dev_fatal(dev, err, "starting transaction"); 1.372 + return; 1.373 + } 1.374 + 1.375 + err = xenbus_printf(xbt, dev->nodename, "sectors", "%lu", 1.376 + vbd_size(&be->blkif->vbd)); 1.377 + if (err) { 1.378 + xenbus_dev_fatal(dev, err, "writing %s/sectors", 1.379 + dev->nodename); 1.380 + goto abort; 1.381 + } 1.382 + 1.383 + /* FIXME: use a typename instead */ 1.384 + err = xenbus_printf(xbt, dev->nodename, "info", "%u", 1.385 + vbd_info(&be->blkif->vbd)); 1.386 + if (err) { 1.387 + xenbus_dev_fatal(dev, err, "writing %s/info", 1.388 + dev->nodename); 1.389 + goto abort; 1.390 + } 1.391 + err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu", 1.392 + vbd_secsize(&be->blkif->vbd)); 1.393 + if (err) { 1.394 + xenbus_dev_fatal(dev, err, "writing %s/sector-size", 1.395 + dev->nodename); 1.396 + goto abort; 1.397 + } 1.398 + 1.399 + err = xenbus_switch_state(dev, xbt, XenbusStateConnected); 1.400 + if (err) 1.401 + goto abort; 1.402 + 1.403 + err = xenbus_transaction_end(xbt, 0); 1.404 + if (err == -EAGAIN) 1.405 + goto again; 1.406 + if (err) 1.407 + xenbus_dev_fatal(dev, err, "ending transaction"); 1.408 + return; 1.409 + abort: 1.410 + xenbus_transaction_end(xbt, 1); 1.411 +} 1.412 + 1.413 + 1.414 +static int connect_ring(struct backend_info *be) 1.415 +{ 1.416 + struct xenbus_device *dev = be->dev; 1.417 + unsigned long ring_ref; 1.418 + unsigned int evtchn; 1.419 int err; 1.420 1.421 - be = kmalloc(sizeof(*be), GFP_KERNEL); 1.422 - if (!be) { 1.423 - xenbus_dev_error(dev, -ENOMEM, 1.424 - "allocating backend structure"); 1.425 - return -ENOMEM; 1.426 - } 1.427 - memset(be, 0, sizeof(*be)); 1.428 + DPRINTK("%s", dev->otherend); 1.429 1.430 - frontend = NULL; 1.431 - err = xenbus_gather(NULL, dev->nodename, 1.432 - "frontend-id", "%li", &be->frontend_id, 1.433 - "frontend", NULL, &frontend, 1.434 - NULL); 1.435 - if (XENBUS_EXIST_ERR(err)) 1.436 - goto free_be; 1.437 - if (err < 0) { 1.438 - xenbus_dev_error(dev, err, 1.439 - "reading %s/frontend or frontend-id", 1.440 - dev->nodename); 1.441 - goto free_be; 1.442 - } 1.443 - if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) { 1.444 - /* If we can't get a frontend path and a frontend-id, 1.445 - * then our bus-id is no longer valid and we need to 1.446 - * destroy the backend device. 1.447 - */ 1.448 - err = -ENOENT; 1.449 - goto free_be; 1.450 + err = xenbus_gather(NULL, dev->otherend, "ring-ref", "%lu", &ring_ref, 1.451 + "event-channel", "%u", &evtchn, NULL); 1.452 + if (err) { 1.453 + xenbus_dev_fatal(dev, err, 1.454 + "reading %s/ring-ref and event-channel", 1.455 + dev->otherend); 1.456 + return err; 1.457 } 1.458 1.459 - be->dev = dev; 1.460 - be->backend_watch.node = dev->nodename; 1.461 - be->backend_watch.callback = backend_changed; 1.462 - /* Will implicitly call backend_changed once. */ 1.463 - err = register_xenbus_watch(&be->backend_watch); 1.464 + /* Map the shared frame, irq etc. */ 1.465 + err = blkif_map(be->blkif, ring_ref, evtchn); 1.466 if (err) { 1.467 - be->backend_watch.node = NULL; 1.468 - xenbus_dev_error(dev, err, 1.469 - "adding backend watch on %s", 1.470 - dev->nodename); 1.471 - goto free_be; 1.472 + xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u", 1.473 + ring_ref, evtchn); 1.474 + return err; 1.475 } 1.476 1.477 - be->frontpath = frontend; 1.478 - be->watch.node = be->frontpath; 1.479 - be->watch.callback = frontend_changed; 1.480 - err = register_xenbus_watch(&be->watch); 1.481 - if (err) { 1.482 - be->watch.node = NULL; 1.483 - xenbus_dev_error(dev, err, 1.484 - "adding frontend watch on %s", 1.485 - be->frontpath); 1.486 - goto free_be; 1.487 - } 1.488 + return 0; 1.489 +} 1.490 1.491 - dev->data = be; 1.492 - return 0; 1.493 1.494 - free_be: 1.495 - if (be->backend_watch.node) 1.496 - unregister_xenbus_watch(&be->backend_watch); 1.497 - kfree(frontend); 1.498 - kfree(be); 1.499 - return err; 1.500 -} 1.501 +/* ** Driver Registration ** */ 1.502 + 1.503 1.504 static struct xenbus_device_id blkback_ids[] = { 1.505 { "vbd" }, 1.506 { "" } 1.507 }; 1.508 1.509 + 1.510 static struct xenbus_driver blkback = { 1.511 .name = "vbd", 1.512 .owner = THIS_MODULE, 1.513 .ids = blkback_ids, 1.514 .probe = blkback_probe, 1.515 .remove = blkback_remove, 1.516 + .otherend_changed = frontend_changed 1.517 }; 1.518 1.519 + 1.520 void blkif_xenbus_init(void) 1.521 { 1.522 xenbus_register_backend(&blkback); 1.523 } 1.524 1.525 + 1.526 /* 1.527 * Local variables: 1.528 * c-file-style: "linux"
2.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Fri Nov 11 18:01:44 2005 +0100 2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Fri Nov 11 21:59:05 2005 +0100 2.3 @@ -8,6 +8,7 @@ 2.4 * Copyright (c) 2004, Christian Limpach 2.5 * Copyright (c) 2004, Andrew Warfield 2.6 * Copyright (c) 2005, Christopher Clark 2.7 + * Copyright (c) 2005, XenSource Ltd 2.8 * 2.9 * This file may be distributed separately from the Linux kernel, or 2.10 * incorporated into other software packages, subject to the following license: 2.11 @@ -31,6 +32,7 @@ 2.12 * IN THE SOFTWARE. 2.13 */ 2.14 2.15 + 2.16 #if 1 2.17 #define ASSERT(p) \ 2.18 if (!(p)) { printk("Assertion '%s' failed, line %d, file %s", #p , \ 2.19 @@ -39,6 +41,7 @@ 2.20 #define ASSERT(_p) 2.21 #endif 2.22 2.23 + 2.24 #include <linux/version.h> 2.25 #include "block.h" 2.26 #include <linux/cdrom.h> 2.27 @@ -51,6 +54,7 @@ 2.28 #include <asm-xen/gnttab.h> 2.29 #include <asm/hypervisor.h> 2.30 2.31 + 2.32 #define BLKIF_STATE_DISCONNECTED 0 2.33 #define BLKIF_STATE_CONNECTED 1 2.34 2.35 @@ -58,9 +62,304 @@ 2.36 (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE) 2.37 #define GRANT_INVALID_REF 0 2.38 2.39 -static void kick_pending_request_queues(struct blkfront_info *info); 2.40 + 2.41 +static void connect(struct blkfront_info *); 2.42 +static void blkfront_closing(struct xenbus_device *); 2.43 +static int blkfront_remove(struct xenbus_device *); 2.44 +static int talk_to_backend(struct xenbus_device *, struct blkfront_info *); 2.45 +static int setup_blkring(struct xenbus_device *, struct blkfront_info *); 2.46 + 2.47 +static void kick_pending_request_queues(struct blkfront_info *); 2.48 + 2.49 +static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs); 2.50 +static void blkif_restart_queue(void *arg); 2.51 +static void blkif_recover(struct blkfront_info *); 2.52 +static void blkif_completion(struct blk_shadow *); 2.53 +static void blkif_free(struct blkfront_info *); 2.54 + 2.55 + 2.56 +/** 2.57 + * Entry point to this code when a new device is created. Allocate the basic 2.58 + * structures and the ring buffer for communication with the backend, and 2.59 + * inform the backend of the appropriate details for those. Switch to 2.60 + * Initialised state. 2.61 + */ 2.62 +static int blkfront_probe(struct xenbus_device *dev, 2.63 + const struct xenbus_device_id *id) 2.64 +{ 2.65 + int err, vdevice, i; 2.66 + struct blkfront_info *info; 2.67 + 2.68 + /* FIXME: Use dynamic device id if this is not set. */ 2.69 + err = xenbus_scanf(NULL, dev->nodename, 2.70 + "virtual-device", "%i", &vdevice); 2.71 + if (err != 1) { 2.72 + xenbus_dev_fatal(dev, err, "reading virtual-device"); 2.73 + return err; 2.74 + } 2.75 + 2.76 + info = kmalloc(sizeof(*info), GFP_KERNEL); 2.77 + if (!info) { 2.78 + xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure"); 2.79 + return -ENOMEM; 2.80 + } 2.81 + info->xbdev = dev; 2.82 + info->vdevice = vdevice; 2.83 + info->connected = BLKIF_STATE_DISCONNECTED; 2.84 + info->mi = NULL; 2.85 + info->gd = NULL; 2.86 + INIT_WORK(&info->work, blkif_restart_queue, (void *)info); 2.87 + 2.88 + info->shadow_free = 0; 2.89 + memset(info->shadow, 0, sizeof(info->shadow)); 2.90 + for (i = 0; i < BLK_RING_SIZE; i++) 2.91 + info->shadow[i].req.id = i+1; 2.92 + info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; 2.93 + 2.94 + /* Front end dir is a number, which is used as the id. */ 2.95 + info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0); 2.96 + dev->data = info; 2.97 + 2.98 + err = talk_to_backend(dev, info); 2.99 + if (err) { 2.100 + kfree(info); 2.101 + dev->data = NULL; 2.102 + return err; 2.103 + } 2.104 + 2.105 + return 0; 2.106 +} 2.107 + 2.108 + 2.109 +/** 2.110 + * We are reconnecting to the backend, due to a suspend/resume, or a backend 2.111 + * driver restart. We tear down our blkif structure and recreate it, but 2.112 + * leave the device-layer structures intact so that this is transparent to the 2.113 + * rest of the kernel. 2.114 + */ 2.115 +static int blkfront_resume(struct xenbus_device *dev) 2.116 +{ 2.117 + struct blkfront_info *info = dev->data; 2.118 + int err; 2.119 + 2.120 + DPRINTK("blkfront_resume: %s\n", dev->nodename); 2.121 + 2.122 + blkif_free(info); 2.123 + 2.124 + err = talk_to_backend(dev, info); 2.125 + if (!err) 2.126 + blkif_recover(info); 2.127 + 2.128 + return err; 2.129 +} 2.130 + 2.131 + 2.132 +/* Common code used when first setting up, and when resuming. */ 2.133 +static int talk_to_backend(struct xenbus_device *dev, 2.134 + struct blkfront_info *info) 2.135 +{ 2.136 + const char *message = NULL; 2.137 + struct xenbus_transaction *xbt; 2.138 + int err; 2.139 + 2.140 + /* Create shared ring, alloc event channel. */ 2.141 + err = setup_blkring(dev, info); 2.142 + if (err) 2.143 + goto out; 2.144 + 2.145 +again: 2.146 + xbt = xenbus_transaction_start(); 2.147 + if (IS_ERR(xbt)) { 2.148 + xenbus_dev_fatal(dev, err, "starting transaction"); 2.149 + goto destroy_blkring; 2.150 + } 2.151 + 2.152 + err = xenbus_printf(xbt, dev->nodename, 2.153 + "ring-ref","%u", info->ring_ref); 2.154 + if (err) { 2.155 + message = "writing ring-ref"; 2.156 + goto abort_transaction; 2.157 + } 2.158 + err = xenbus_printf(xbt, dev->nodename, 2.159 + "event-channel", "%u", info->evtchn); 2.160 + if (err) { 2.161 + message = "writing event-channel"; 2.162 + goto abort_transaction; 2.163 + } 2.164 + 2.165 + err = xenbus_switch_state(dev, xbt, XenbusStateInitialised); 2.166 + if (err) { 2.167 + goto abort_transaction; 2.168 + } 2.169 + 2.170 + err = xenbus_transaction_end(xbt, 0); 2.171 + if (err) { 2.172 + if (err == -EAGAIN) 2.173 + goto again; 2.174 + xenbus_dev_fatal(dev, err, "completing transaction"); 2.175 + goto destroy_blkring; 2.176 + } 2.177 + 2.178 + return 0; 2.179 2.180 -static void blkif_completion(struct blk_shadow *s); 2.181 + abort_transaction: 2.182 + xenbus_transaction_end(xbt, 1); 2.183 + if (message) 2.184 + xenbus_dev_fatal(dev, err, "%s", message); 2.185 + destroy_blkring: 2.186 + blkif_free(info); 2.187 + out: 2.188 + return err; 2.189 +} 2.190 + 2.191 + 2.192 +static int setup_blkring(struct xenbus_device *dev, 2.193 + struct blkfront_info *info) 2.194 +{ 2.195 + blkif_sring_t *sring; 2.196 + int err; 2.197 + 2.198 + info->ring_ref = GRANT_INVALID_REF; 2.199 + 2.200 + sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL); 2.201 + if (!sring) { 2.202 + xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); 2.203 + return -ENOMEM; 2.204 + } 2.205 + SHARED_RING_INIT(sring); 2.206 + FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); 2.207 + 2.208 + err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); 2.209 + if (err < 0) { 2.210 + free_page((unsigned long)sring); 2.211 + info->ring.sring = NULL; 2.212 + goto fail; 2.213 + } 2.214 + info->ring_ref = err; 2.215 + 2.216 + err = xenbus_alloc_evtchn(dev, &info->evtchn); 2.217 + if (err) 2.218 + goto fail; 2.219 + 2.220 + err = bind_evtchn_to_irqhandler( 2.221 + info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info); 2.222 + if (err <= 0) { 2.223 + xenbus_dev_fatal(dev, err, 2.224 + "bind_evtchn_to_irqhandler failed"); 2.225 + goto fail; 2.226 + } 2.227 + info->irq = err; 2.228 + 2.229 + return 0; 2.230 +fail: 2.231 + blkif_free(info); 2.232 + return err; 2.233 +} 2.234 + 2.235 + 2.236 +/** 2.237 + * Callback received when the backend's state changes. 2.238 + */ 2.239 +static void backend_changed(struct xenbus_device *dev, 2.240 + XenbusState backend_state) 2.241 +{ 2.242 + struct blkfront_info *info = dev->data; 2.243 + 2.244 + DPRINTK("blkfront:backend_changed.\n"); 2.245 + 2.246 + switch (backend_state) { 2.247 + case XenbusStateUnknown: 2.248 + case XenbusStateInitialising: 2.249 + case XenbusStateInitWait: 2.250 + case XenbusStateInitialised: 2.251 + case XenbusStateClosed: 2.252 + break; 2.253 + 2.254 + case XenbusStateConnected: 2.255 + connect(info); 2.256 + break; 2.257 + 2.258 + case XenbusStateClosing: 2.259 + blkfront_closing(dev); 2.260 + break; 2.261 + } 2.262 +} 2.263 + 2.264 + 2.265 +/* ** Connection ** */ 2.266 + 2.267 + 2.268 +static void connect(struct blkfront_info *info) 2.269 +{ 2.270 + unsigned long sectors, sector_size; 2.271 + unsigned int binfo; 2.272 + 2.273 + if (info->connected == BLKIF_STATE_CONNECTED) 2.274 + return; 2.275 + 2.276 + DPRINTK("blkfront.c:connect:%s.\n", info->xbdev->otherend); 2.277 + 2.278 + int err = xenbus_gather(NULL, info->xbdev->otherend, 2.279 + "sectors", "%lu", §ors, 2.280 + "info", "%u", &binfo, 2.281 + "sector-size", "%lu", §or_size, 2.282 + NULL); 2.283 + if (err) { 2.284 + xenbus_dev_fatal(info->xbdev, err, 2.285 + "reading backend fields at %s", 2.286 + info->xbdev->otherend); 2.287 + return; 2.288 + } 2.289 + 2.290 + info->connected = BLKIF_STATE_CONNECTED; 2.291 + xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); 2.292 + 2.293 + err = xenbus_switch_state(info->xbdev, NULL, XenbusStateConnected); 2.294 + if (err) 2.295 + return; 2.296 + 2.297 + /* Kick pending requests. */ 2.298 + spin_lock_irq(&blkif_io_lock); 2.299 + kick_pending_request_queues(info); 2.300 + spin_unlock_irq(&blkif_io_lock); 2.301 +} 2.302 + 2.303 + 2.304 +/** 2.305 + * Handle the change of state of the backend to Closing. We must delete our 2.306 + * device-layer structures now, to ensure that writes are flushed through to 2.307 + * the backend. Once is this done, we can switch to Closed in 2.308 + * acknowledgement. 2.309 + */ 2.310 +static void blkfront_closing(struct xenbus_device *dev) 2.311 +{ 2.312 + struct blkfront_info *info = dev->data; 2.313 + 2.314 + DPRINTK("blkfront_closing: %s removed\n", dev->nodename); 2.315 + 2.316 + if (info->mi) { 2.317 + DPRINTK("Calling xlvbd_del\n"); 2.318 + xlvbd_del(info); 2.319 + info->mi = NULL; 2.320 + } 2.321 + 2.322 + xenbus_switch_state(dev, NULL, XenbusStateClosed); 2.323 +} 2.324 + 2.325 + 2.326 +static int blkfront_remove(struct xenbus_device *dev) 2.327 +{ 2.328 + DPRINTK("blkfront_remove: %s removed\n", dev->nodename); 2.329 + 2.330 + struct blkfront_info *info = dev->data; 2.331 + 2.332 + blkif_free(info); 2.333 + 2.334 + kfree(info); 2.335 + 2.336 + return 0; 2.337 +} 2.338 + 2.339 2.340 static inline int GET_ID_FROM_FREELIST( 2.341 struct blkfront_info *info) 2.342 @@ -214,7 +513,7 @@ static int blkif_queue_request(struct re 2.343 2.344 gnttab_grant_foreign_access_ref( 2.345 ref, 2.346 - info->backend_id, 2.347 + info->xbdev->otherend_id, 2.348 buffer_mfn, 2.349 rq_data_dir(req) ); 2.350 2.351 @@ -360,6 +659,15 @@ static void blkif_free(struct blkfront_i 2.352 if (info->irq) 2.353 unbind_from_irqhandler(info->irq, info); 2.354 info->evtchn = info->irq = 0; 2.355 + 2.356 +} 2.357 + 2.358 +static void blkif_completion(struct blk_shadow *s) 2.359 +{ 2.360 + int i; 2.361 + for (i = 0; i < s->req.nr_segments; i++) 2.362 + gnttab_end_foreign_access( 2.363 + blkif_gref_from_fas(s->req.frame_and_sects[i]), 0, 0UL); 2.364 } 2.365 2.366 static void blkif_recover(struct blkfront_info *info) 2.367 @@ -400,7 +708,7 @@ static void blkif_recover(struct blkfron 2.368 for (j = 0; j < req->nr_segments; j++) 2.369 gnttab_grant_foreign_access_ref( 2.370 blkif_gref_from_fas(req->frame_and_sects[j]), 2.371 - info->backend_id, 2.372 + info->xbdev->otherend_id, 2.373 pfn_to_mfn(info->shadow[req->id].frame[j]), 2.374 rq_data_dir( 2.375 (struct request *) 2.376 @@ -422,21 +730,8 @@ static void blkif_recover(struct blkfron 2.377 info->connected = BLKIF_STATE_CONNECTED; 2.378 } 2.379 2.380 -static void blkif_connect(struct blkfront_info *info, u16 evtchn) 2.381 -{ 2.382 - int err = 0; 2.383 2.384 - info->evtchn = evtchn; 2.385 - 2.386 - err = bind_evtchn_to_irqhandler( 2.387 - info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info); 2.388 - if (err <= 0) { 2.389 - WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); 2.390 - return; 2.391 - } 2.392 - 2.393 - info->irq = err; 2.394 -} 2.395 +/* ** Driver Registration ** */ 2.396 2.397 2.398 static struct xenbus_device_id blkfront_ids[] = { 2.399 @@ -444,278 +739,6 @@ static struct xenbus_device_id blkfront_ 2.400 { "" } 2.401 }; 2.402 2.403 -static void watch_for_status(struct xenbus_watch *watch, 2.404 - const char **vec, unsigned int len) 2.405 -{ 2.406 - struct blkfront_info *info; 2.407 - unsigned int binfo; 2.408 - unsigned long sectors, sector_size; 2.409 - int err; 2.410 - const char *node; 2.411 - 2.412 - node = vec[XS_WATCH_PATH]; 2.413 - 2.414 - info = container_of(watch, struct blkfront_info, watch); 2.415 - node += strlen(watch->node); 2.416 - 2.417 - /* FIXME: clean up when error on the other end. */ 2.418 - if ((info->connected == BLKIF_STATE_CONNECTED) || info->mi) 2.419 - return; 2.420 - 2.421 - err = xenbus_gather(NULL, watch->node, 2.422 - "sectors", "%lu", §ors, 2.423 - "info", "%u", &binfo, 2.424 - "sector-size", "%lu", §or_size, 2.425 - NULL); 2.426 - if (err) { 2.427 - xenbus_dev_error(info->xbdev, err, 2.428 - "reading backend fields at %s", watch->node); 2.429 - return; 2.430 - } 2.431 - 2.432 - info->connected = BLKIF_STATE_CONNECTED; 2.433 - xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); 2.434 - 2.435 - xenbus_dev_ok(info->xbdev); 2.436 - 2.437 - /* Kick pending requests. */ 2.438 - spin_lock_irq(&blkif_io_lock); 2.439 - kick_pending_request_queues(info); 2.440 - spin_unlock_irq(&blkif_io_lock); 2.441 -} 2.442 - 2.443 -static int setup_blkring(struct xenbus_device *dev, struct blkfront_info *info) 2.444 -{ 2.445 - blkif_sring_t *sring; 2.446 - int err; 2.447 - evtchn_op_t op = { 2.448 - .cmd = EVTCHNOP_alloc_unbound, 2.449 - .u.alloc_unbound.dom = DOMID_SELF, 2.450 - .u.alloc_unbound.remote_dom = info->backend_id }; 2.451 - 2.452 - info->ring_ref = GRANT_INVALID_REF; 2.453 - 2.454 - sring = (void *)__get_free_page(GFP_KERNEL); 2.455 - if (!sring) { 2.456 - xenbus_dev_error(dev, -ENOMEM, "allocating shared ring"); 2.457 - return -ENOMEM; 2.458 - } 2.459 - SHARED_RING_INIT(sring); 2.460 - FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); 2.461 - 2.462 - err = gnttab_grant_foreign_access(info->backend_id, 2.463 - virt_to_mfn(info->ring.sring), 0); 2.464 - if (err == -ENOSPC) { 2.465 - free_page((unsigned long)info->ring.sring); 2.466 - info->ring.sring = 0; 2.467 - xenbus_dev_error(dev, err, "granting access to ring page"); 2.468 - return err; 2.469 - } 2.470 - info->ring_ref = err; 2.471 - 2.472 - err = HYPERVISOR_event_channel_op(&op); 2.473 - if (err) { 2.474 - gnttab_end_foreign_access(info->ring_ref, 0, 2.475 - (unsigned long)info->ring.sring); 2.476 - info->ring_ref = GRANT_INVALID_REF; 2.477 - info->ring.sring = NULL; 2.478 - xenbus_dev_error(dev, err, "allocating event channel"); 2.479 - return err; 2.480 - } 2.481 - 2.482 - blkif_connect(info, op.u.alloc_unbound.port); 2.483 - 2.484 - return 0; 2.485 -} 2.486 - 2.487 -/* Common code used when first setting up, and when resuming. */ 2.488 -static int talk_to_backend(struct xenbus_device *dev, 2.489 - struct blkfront_info *info) 2.490 -{ 2.491 - char *backend; 2.492 - const char *message; 2.493 - struct xenbus_transaction *xbt; 2.494 - int err; 2.495 - 2.496 - backend = NULL; 2.497 - err = xenbus_gather(NULL, dev->nodename, 2.498 - "backend-id", "%i", &info->backend_id, 2.499 - "backend", NULL, &backend, 2.500 - NULL); 2.501 - if (XENBUS_EXIST_ERR(err)) 2.502 - goto out; 2.503 - if (backend && strlen(backend) == 0) { 2.504 - err = -ENOENT; 2.505 - goto out; 2.506 - } 2.507 - if (err < 0) { 2.508 - xenbus_dev_error(dev, err, "reading %s/backend or backend-id", 2.509 - dev->nodename); 2.510 - goto out; 2.511 - } 2.512 - 2.513 - /* Create shared ring, alloc event channel. */ 2.514 - err = setup_blkring(dev, info); 2.515 - if (err) { 2.516 - xenbus_dev_error(dev, err, "setting up block ring"); 2.517 - goto out; 2.518 - } 2.519 - 2.520 -again: 2.521 - xbt = xenbus_transaction_start(); 2.522 - if (IS_ERR(xbt)) { 2.523 - xenbus_dev_error(dev, err, "starting transaction"); 2.524 - goto destroy_blkring; 2.525 - } 2.526 - 2.527 - err = xenbus_printf(xbt, dev->nodename, 2.528 - "ring-ref","%u", info->ring_ref); 2.529 - if (err) { 2.530 - message = "writing ring-ref"; 2.531 - goto abort_transaction; 2.532 - } 2.533 - err = xenbus_printf(xbt, dev->nodename, 2.534 - "event-channel", "%u", info->evtchn); 2.535 - if (err) { 2.536 - message = "writing event-channel"; 2.537 - goto abort_transaction; 2.538 - } 2.539 - 2.540 - err = xenbus_transaction_end(xbt, 0); 2.541 - if (err) { 2.542 - if (err == -EAGAIN) 2.543 - goto again; 2.544 - xenbus_dev_error(dev, err, "completing transaction"); 2.545 - goto destroy_blkring; 2.546 - } 2.547 - 2.548 - info->watch.node = backend; 2.549 - info->watch.callback = watch_for_status; 2.550 - err = register_xenbus_watch(&info->watch); 2.551 - if (err) { 2.552 - message = "registering watch on backend"; 2.553 - goto destroy_blkring; 2.554 - } 2.555 - 2.556 - info->backend = backend; 2.557 - 2.558 - return 0; 2.559 - 2.560 - abort_transaction: 2.561 - xenbus_transaction_end(xbt, 1); 2.562 - xenbus_dev_error(dev, err, "%s", message); 2.563 - destroy_blkring: 2.564 - blkif_free(info); 2.565 - out: 2.566 - kfree(backend); 2.567 - return err; 2.568 -} 2.569 - 2.570 -/* Setup supplies the backend dir, virtual device. 2.571 - 2.572 - We place an event channel and shared frame entries. 2.573 - We watch backend to wait if it's ok. */ 2.574 -static int blkfront_probe(struct xenbus_device *dev, 2.575 - const struct xenbus_device_id *id) 2.576 -{ 2.577 - int err, vdevice, i; 2.578 - struct blkfront_info *info; 2.579 - 2.580 - /* FIXME: Use dynamic device id if this is not set. */ 2.581 - err = xenbus_scanf(NULL, dev->nodename, 2.582 - "virtual-device", "%i", &vdevice); 2.583 - if (XENBUS_EXIST_ERR(err)) 2.584 - return err; 2.585 - if (err < 0) { 2.586 - xenbus_dev_error(dev, err, "reading virtual-device"); 2.587 - return err; 2.588 - } 2.589 - 2.590 - info = kmalloc(sizeof(*info), GFP_KERNEL); 2.591 - if (!info) { 2.592 - xenbus_dev_error(dev, err, "allocating info structure"); 2.593 - return err; 2.594 - } 2.595 - info->xbdev = dev; 2.596 - info->vdevice = vdevice; 2.597 - info->connected = BLKIF_STATE_DISCONNECTED; 2.598 - info->mi = NULL; 2.599 - info->gd = NULL; 2.600 - INIT_WORK(&info->work, blkif_restart_queue, (void *)info); 2.601 - 2.602 - info->shadow_free = 0; 2.603 - memset(info->shadow, 0, sizeof(info->shadow)); 2.604 - for (i = 0; i < BLK_RING_SIZE; i++) 2.605 - info->shadow[i].req.id = i+1; 2.606 - info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; 2.607 - 2.608 - /* Front end dir is a number, which is used as the id. */ 2.609 - info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0); 2.610 - dev->data = info; 2.611 - 2.612 - err = talk_to_backend(dev, info); 2.613 - if (err) { 2.614 - kfree(info); 2.615 - dev->data = NULL; 2.616 - return err; 2.617 - } 2.618 - 2.619 - { 2.620 - unsigned int len = max(XS_WATCH_PATH, XS_WATCH_TOKEN) + 1; 2.621 - const char *vec[len]; 2.622 - 2.623 - vec[XS_WATCH_PATH] = info->watch.node; 2.624 - vec[XS_WATCH_TOKEN] = NULL; 2.625 - 2.626 - /* Call once in case entries already there. */ 2.627 - watch_for_status(&info->watch, vec, len); 2.628 - } 2.629 - 2.630 - return 0; 2.631 -} 2.632 - 2.633 -static int blkfront_remove(struct xenbus_device *dev) 2.634 -{ 2.635 - struct blkfront_info *info = dev->data; 2.636 - 2.637 - if (info->backend) 2.638 - unregister_xenbus_watch(&info->watch); 2.639 - 2.640 - if (info->mi) 2.641 - xlvbd_del(info); 2.642 - 2.643 - blkif_free(info); 2.644 - 2.645 - kfree(info->backend); 2.646 - kfree(info); 2.647 - 2.648 - return 0; 2.649 -} 2.650 - 2.651 -static int blkfront_suspend(struct xenbus_device *dev) 2.652 -{ 2.653 - struct blkfront_info *info = dev->data; 2.654 - 2.655 - unregister_xenbus_watch(&info->watch); 2.656 - kfree(info->backend); 2.657 - info->backend = NULL; 2.658 - 2.659 - return 0; 2.660 -} 2.661 - 2.662 -static int blkfront_resume(struct xenbus_device *dev) 2.663 -{ 2.664 - struct blkfront_info *info = dev->data; 2.665 - int err; 2.666 - 2.667 - blkif_free(info); 2.668 - 2.669 - err = talk_to_backend(dev, info); 2.670 - if (!err) 2.671 - blkif_recover(info); 2.672 - 2.673 - return err; 2.674 -} 2.675 2.676 static struct xenbus_driver blkfront = { 2.677 .name = "vbd", 2.678 @@ -724,27 +747,28 @@ static struct xenbus_driver blkfront = { 2.679 .probe = blkfront_probe, 2.680 .remove = blkfront_remove, 2.681 .resume = blkfront_resume, 2.682 - .suspend = blkfront_suspend, 2.683 + .otherend_changed = backend_changed, 2.684 }; 2.685 2.686 + 2.687 static int __init xlblk_init(void) 2.688 { 2.689 if (xen_init() < 0) 2.690 return -ENODEV; 2.691 2.692 - xenbus_register_driver(&blkfront); 2.693 - return 0; 2.694 + return xenbus_register_frontend(&blkfront); 2.695 } 2.696 - 2.697 module_init(xlblk_init); 2.698 2.699 -static void blkif_completion(struct blk_shadow *s) 2.700 + 2.701 +static void xlblk_exit(void) 2.702 { 2.703 - int i; 2.704 - for (i = 0; i < s->req.nr_segments; i++) 2.705 - gnttab_end_foreign_access( 2.706 - blkif_gref_from_fas(s->req.frame_and_sects[i]), 0, 0UL); 2.707 + return xenbus_unregister_driver(&blkfront); 2.708 } 2.709 +module_exit(xlblk_exit); 2.710 + 2.711 +MODULE_LICENSE("BSD"); 2.712 + 2.713 2.714 /* 2.715 * Local variables:
3.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Fri Nov 11 18:01:44 2005 +0100 3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Fri Nov 11 21:59:05 2005 +0100 3.3 @@ -113,15 +113,11 @@ struct blk_shadow { 3.4 struct blkfront_info 3.5 { 3.6 struct xenbus_device *xbdev; 3.7 - /* We watch the backend */ 3.8 - struct xenbus_watch watch; 3.9 dev_t dev; 3.10 struct gendisk *gd; 3.11 int vdevice; 3.12 blkif_vdev_t handle; 3.13 int connected; 3.14 - char *backend; 3.15 - int backend_id; 3.16 int ring_ref; 3.17 blkif_front_ring_t ring; 3.18 unsigned int evtchn, irq;
4.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Nov 11 18:01:44 2005 +0100 4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Nov 11 21:59:05 2005 +0100 4.3 @@ -1,5 +1,6 @@ 4.4 /* Xenbus code for netif backend 4.5 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au> 4.6 + Copyright (C) 2005 XenSource Ltd 4.7 4.8 This program is free software; you can redistribute it and/or modify 4.9 it under the terms of the GNU General Public License as published by 4.10 @@ -15,148 +16,102 @@ 4.11 along with this program; if not, write to the Free Software 4.12 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 4.13 */ 4.14 + 4.15 + 4.16 #include <stdarg.h> 4.17 #include <linux/module.h> 4.18 #include <asm-xen/xenbus.h> 4.19 +#include <asm-xen/net_driver_util.h> 4.20 #include "common.h" 4.21 4.22 + 4.23 +#if 0 4.24 +#undef DPRINTK 4.25 +#define DPRINTK(fmt, args...) \ 4.26 + printk("netback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) 4.27 +#endif 4.28 + 4.29 + 4.30 struct backend_info 4.31 { 4.32 struct xenbus_device *dev; 4.33 + netif_t *netif; 4.34 + struct xenbus_watch backend_watch; 4.35 + XenbusState frontend_state; 4.36 +}; 4.37 4.38 - /* our communications channel */ 4.39 - netif_t *netif; 4.40 - 4.41 - long int frontend_id; 4.42 4.43 - /* watch back end for changes */ 4.44 - struct xenbus_watch backend_watch; 4.45 +static int connect_rings(struct backend_info *); 4.46 +static void connect(struct backend_info *); 4.47 +static void maybe_connect(struct backend_info *); 4.48 +static void backend_changed(struct xenbus_watch *, const char **, 4.49 + unsigned int); 4.50 4.51 - /* watch front end for changes */ 4.52 - struct xenbus_watch watch; 4.53 - char *frontpath; 4.54 -}; 4.55 4.56 static int netback_remove(struct xenbus_device *dev) 4.57 { 4.58 struct backend_info *be = dev->data; 4.59 4.60 - if (be->watch.node) 4.61 - unregister_xenbus_watch(&be->watch); 4.62 - unregister_xenbus_watch(&be->backend_watch); 4.63 - if (be->netif) 4.64 + if (be->backend_watch.node) { 4.65 + unregister_xenbus_watch(&be->backend_watch); 4.66 + kfree(be->backend_watch.node); 4.67 + be->backend_watch.node = NULL; 4.68 + } 4.69 + if (be->netif) { 4.70 netif_disconnect(be->netif); 4.71 - kfree(be->frontpath); 4.72 + be->netif = NULL; 4.73 + } 4.74 kfree(be); 4.75 + dev->data = NULL; 4.76 return 0; 4.77 } 4.78 4.79 -/* Front end tells us frame. */ 4.80 -static void frontend_changed(struct xenbus_watch *watch, 4.81 - const char **vec, unsigned int len) 4.82 -{ 4.83 - unsigned long tx_ring_ref, rx_ring_ref; 4.84 - unsigned int evtchn; 4.85 - int err; 4.86 - struct backend_info *be 4.87 - = container_of(watch, struct backend_info, watch); 4.88 - char *mac, *e, *s; 4.89 - int i; 4.90 - 4.91 - /* If other end is gone, delete ourself. */ 4.92 - if (vec && !xenbus_exists(NULL, be->frontpath, "")) { 4.93 - xenbus_rm(NULL, be->dev->nodename, ""); 4.94 - device_unregister(&be->dev->dev); 4.95 - return; 4.96 - } 4.97 - if (be->netif == NULL || be->netif->status == CONNECTED) 4.98 - return; 4.99 4.100 - mac = xenbus_read(NULL, be->frontpath, "mac", NULL); 4.101 - if (IS_ERR(mac)) { 4.102 - err = PTR_ERR(mac); 4.103 - xenbus_dev_error(be->dev, err, "reading %s/mac", 4.104 - be->dev->nodename); 4.105 - return; 4.106 +/** 4.107 + * Entry point to this code when a new device is created. Allocate the basic 4.108 + * structures, and watch the store waiting for the hotplug scripts to tell us 4.109 + * the device's handle. Switch to InitWait. 4.110 + */ 4.111 +static int netback_probe(struct xenbus_device *dev, 4.112 + const struct xenbus_device_id *id) 4.113 +{ 4.114 + int err; 4.115 + struct backend_info *be = kmalloc(sizeof(struct backend_info), 4.116 + GFP_KERNEL); 4.117 + if (!be) { 4.118 + xenbus_dev_fatal(dev, -ENOMEM, 4.119 + "allocating backend structure"); 4.120 + return -ENOMEM; 4.121 } 4.122 - s = mac; 4.123 - for (i = 0; i < ETH_ALEN; i++) { 4.124 - be->netif->fe_dev_addr[i] = simple_strtoul(s, &e, 16); 4.125 - if (s == e || (e[0] != ':' && e[0] != 0)) { 4.126 - kfree(mac); 4.127 - err = -ENOENT; 4.128 - xenbus_dev_error(be->dev, err, "parsing %s/mac", 4.129 - be->dev->nodename); 4.130 - return; 4.131 - } 4.132 - s = &e[1]; 4.133 - } 4.134 - kfree(mac); 4.135 + memset(be, 0, sizeof(*be)); 4.136 + 4.137 + be->dev = dev; 4.138 + dev->data = be; 4.139 4.140 - err = xenbus_gather(NULL, be->frontpath, 4.141 - "tx-ring-ref", "%lu", &tx_ring_ref, 4.142 - "rx-ring-ref", "%lu", &rx_ring_ref, 4.143 - "event-channel", "%u", &evtchn, NULL); 4.144 + err = xenbus_watch_path2(dev, dev->nodename, "handle", 4.145 + &be->backend_watch, backend_changed); 4.146 + if (err) 4.147 + goto fail; 4.148 + 4.149 + err = xenbus_switch_state(dev, NULL, XenbusStateInitWait); 4.150 if (err) { 4.151 - xenbus_dev_error(be->dev, err, 4.152 - "reading %s/ring-ref and event-channel", 4.153 - be->frontpath); 4.154 - return; 4.155 + goto fail; 4.156 } 4.157 4.158 - /* Map the shared frame, irq etc. */ 4.159 - err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn); 4.160 - if (err) { 4.161 - xenbus_dev_error(be->dev, err, 4.162 - "mapping shared-frames %lu/%lu port %u", 4.163 - tx_ring_ref, rx_ring_ref, evtchn); 4.164 - return; 4.165 - } 4.166 + return 0; 4.167 4.168 - xenbus_dev_ok(be->dev); 4.169 - 4.170 - return; 4.171 +fail: 4.172 + DPRINTK("failed"); 4.173 + netback_remove(dev); 4.174 + return err; 4.175 } 4.176 4.177 -/* 4.178 - Setup supplies physical device. 4.179 - We provide event channel and device details to front end. 4.180 - Frontend supplies shared frame and event channel. 4.181 + 4.182 +/** 4.183 + * Handle the creation of the hotplug script environment. We add the script 4.184 + * and vif variables to the environment, for the benefit of the vif-* hotplug 4.185 + * scripts. 4.186 */ 4.187 -static void backend_changed(struct xenbus_watch *watch, 4.188 - const char **vec, unsigned int len) 4.189 -{ 4.190 - int err; 4.191 - long int handle; 4.192 - struct backend_info *be 4.193 - = container_of(watch, struct backend_info, backend_watch); 4.194 - struct xenbus_device *dev = be->dev; 4.195 - u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; 4.196 - 4.197 - err = xenbus_scanf(NULL, dev->nodename, "handle", "%li", &handle); 4.198 - if (XENBUS_EXIST_ERR(err)) 4.199 - return; 4.200 - if (err < 0) { 4.201 - xenbus_dev_error(dev, err, "reading handle"); 4.202 - return; 4.203 - } 4.204 - 4.205 - if (be->netif == NULL) { 4.206 - be->netif = alloc_netif(be->frontend_id, handle, be_mac); 4.207 - if (IS_ERR(be->netif)) { 4.208 - err = PTR_ERR(be->netif); 4.209 - be->netif = NULL; 4.210 - xenbus_dev_error(dev, err, "creating interface"); 4.211 - return; 4.212 - } 4.213 - 4.214 - kobject_hotplug(&dev->dev.kobj, KOBJ_ONLINE); 4.215 - 4.216 - /* Pass in NULL node to skip exist test. */ 4.217 - frontend_changed(&be->watch, NULL, 0); 4.218 - } 4.219 -} 4.220 - 4.221 static int netback_hotplug(struct xenbus_device *xdev, char **envp, 4.222 int num_envp, char *buffer, int buffer_size) 4.223 { 4.224 @@ -164,10 +119,12 @@ static int netback_hotplug(struct xenbus 4.225 netif_t *netif = be->netif; 4.226 int i = 0, length = 0; 4.227 4.228 + DPRINTK("netback_hotplug"); 4.229 + 4.230 char *val = xenbus_read(NULL, xdev->nodename, "script", NULL); 4.231 if (IS_ERR(val)) { 4.232 int err = PTR_ERR(val); 4.233 - xenbus_dev_error(xdev, err, "reading script"); 4.234 + xenbus_dev_fatal(xdev, err, "reading script"); 4.235 return err; 4.236 } 4.237 else { 4.238 @@ -186,82 +143,162 @@ static int netback_hotplug(struct xenbus 4.239 return 0; 4.240 } 4.241 4.242 -static int netback_probe(struct xenbus_device *dev, 4.243 - const struct xenbus_device_id *id) 4.244 + 4.245 +/** 4.246 + * Callback received when the hotplug scripts have placed the handle node. 4.247 + * Read it, and create a netif structure. If the frontend is ready, connect. 4.248 + */ 4.249 +static void backend_changed(struct xenbus_watch *watch, 4.250 + const char **vec, unsigned int len) 4.251 +{ 4.252 + int err; 4.253 + long handle; 4.254 + struct backend_info *be 4.255 + = container_of(watch, struct backend_info, backend_watch); 4.256 + struct xenbus_device *dev = be->dev; 4.257 + 4.258 + DPRINTK(""); 4.259 + 4.260 + err = xenbus_scanf(NULL, dev->nodename, "handle", "%li", &handle); 4.261 + if (XENBUS_EXIST_ERR(err)) { 4.262 + /* Since this watch will fire once immediately after it is 4.263 + registered, we expect this. Ignore it, and wait for the 4.264 + hotplug scripts. */ 4.265 + return; 4.266 + } 4.267 + if (err != 1) { 4.268 + xenbus_dev_fatal(dev, err, "reading handle"); 4.269 + return; 4.270 + } 4.271 + 4.272 + if (be->netif == NULL) { 4.273 + u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; 4.274 + 4.275 + be->netif = alloc_netif(dev->otherend_id, handle, be_mac); 4.276 + if (IS_ERR(be->netif)) { 4.277 + err = PTR_ERR(be->netif); 4.278 + be->netif = NULL; 4.279 + xenbus_dev_fatal(dev, err, "creating interface"); 4.280 + return; 4.281 + } 4.282 + 4.283 + kobject_hotplug(&dev->dev.kobj, KOBJ_ONLINE); 4.284 + 4.285 + maybe_connect(be); 4.286 + } 4.287 +} 4.288 + 4.289 + 4.290 +/** 4.291 + * Callback received when the frontend's state changes. 4.292 + */ 4.293 +static void frontend_changed(struct xenbus_device *dev, 4.294 + XenbusState frontend_state) 4.295 { 4.296 - struct backend_info *be; 4.297 - char *frontend; 4.298 + struct backend_info *be = dev->data; 4.299 + 4.300 + DPRINTK(""); 4.301 + 4.302 + be->frontend_state = frontend_state; 4.303 + 4.304 + switch (frontend_state) { 4.305 + case XenbusStateInitialising: 4.306 + case XenbusStateInitialised: 4.307 + break; 4.308 + 4.309 + case XenbusStateConnected: 4.310 + maybe_connect(be); 4.311 + break; 4.312 + 4.313 + case XenbusStateClosing: 4.314 + xenbus_switch_state(dev, NULL, XenbusStateClosing); 4.315 + break; 4.316 + 4.317 + case XenbusStateClosed: 4.318 + device_unregister(&be->dev->dev); 4.319 + break; 4.320 + 4.321 + case XenbusStateUnknown: 4.322 + case XenbusStateInitWait: 4.323 + default: 4.324 + xenbus_dev_fatal(be->dev, -EINVAL, "saw state %d at frontend", 4.325 + frontend_state); 4.326 + break; 4.327 + } 4.328 +} 4.329 + 4.330 + 4.331 +/* ** Connection ** */ 4.332 + 4.333 + 4.334 +static void maybe_connect(struct backend_info *be) 4.335 +{ 4.336 + if (be->netif != NULL && be->frontend_state == XenbusStateConnected) { 4.337 + connect(be); 4.338 + } 4.339 +} 4.340 + 4.341 + 4.342 +static void connect(struct backend_info *be) 4.343 +{ 4.344 + int err; 4.345 + struct xenbus_device *dev = be->dev; 4.346 + 4.347 + err = connect_rings(be); 4.348 + if (err) 4.349 + return; 4.350 + 4.351 + err = xen_net_read_mac(dev, be->netif->fe_dev_addr); 4.352 + if (err) { 4.353 + xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); 4.354 + return; 4.355 + } 4.356 + 4.357 + xenbus_switch_state(dev, NULL, XenbusStateConnected); 4.358 +} 4.359 + 4.360 + 4.361 +static int connect_rings(struct backend_info *be) 4.362 +{ 4.363 + struct xenbus_device *dev = be->dev; 4.364 + unsigned long tx_ring_ref, rx_ring_ref; 4.365 + unsigned int evtchn; 4.366 int err; 4.367 4.368 - be = kmalloc(sizeof(*be), GFP_KERNEL); 4.369 - if (!be) { 4.370 - xenbus_dev_error(dev, -ENOMEM, "allocating backend structure"); 4.371 - return -ENOMEM; 4.372 - } 4.373 - memset(be, 0, sizeof(*be)); 4.374 + DPRINTK(""); 4.375 4.376 - frontend = NULL; 4.377 - err = xenbus_gather(NULL, dev->nodename, 4.378 - "frontend-id", "%li", &be->frontend_id, 4.379 - "frontend", NULL, &frontend, 4.380 - NULL); 4.381 - if (XENBUS_EXIST_ERR(err)) 4.382 - goto free_be; 4.383 - if (err < 0) { 4.384 - xenbus_dev_error(dev, err, 4.385 - "reading %s/frontend or frontend-id", 4.386 - dev->nodename); 4.387 - goto free_be; 4.388 - } 4.389 - if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) { 4.390 - /* If we can't get a frontend path and a frontend-id, 4.391 - * then our bus-id is no longer valid and we need to 4.392 - * destroy the backend device. 4.393 - */ 4.394 - err = -ENOENT; 4.395 - goto free_be; 4.396 + err = xenbus_gather(NULL, dev->otherend, 4.397 + "tx-ring-ref", "%lu", &tx_ring_ref, 4.398 + "rx-ring-ref", "%lu", &rx_ring_ref, 4.399 + "event-channel", "%u", &evtchn, NULL); 4.400 + if (err) { 4.401 + xenbus_dev_fatal(dev, err, 4.402 + "reading %s/ring-ref and event-channel", 4.403 + dev->otherend); 4.404 + return err; 4.405 } 4.406 4.407 - be->dev = dev; 4.408 - be->backend_watch.node = dev->nodename; 4.409 - be->backend_watch.callback = backend_changed; 4.410 - /* Registration implicitly calls backend_changed. */ 4.411 - err = register_xenbus_watch(&be->backend_watch); 4.412 - if (err) { 4.413 - be->backend_watch.node = NULL; 4.414 - xenbus_dev_error(dev, err, "adding backend watch on %s", 4.415 - dev->nodename); 4.416 - goto free_be; 4.417 - } 4.418 - 4.419 - be->frontpath = frontend; 4.420 - be->watch.node = be->frontpath; 4.421 - be->watch.callback = frontend_changed; 4.422 - err = register_xenbus_watch(&be->watch); 4.423 + /* Map the shared frame, irq etc. */ 4.424 + err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn); 4.425 if (err) { 4.426 - be->watch.node = NULL; 4.427 - xenbus_dev_error(dev, err, 4.428 - "adding frontend watch on %s", 4.429 - be->frontpath); 4.430 - goto free_be; 4.431 + xenbus_dev_fatal(dev, err, 4.432 + "mapping shared-frames %lu/%lu port %u", 4.433 + tx_ring_ref, rx_ring_ref, evtchn); 4.434 + return err; 4.435 } 4.436 - 4.437 - dev->data = be; 4.438 return 0; 4.439 +} 4.440 4.441 - free_be: 4.442 - if (be->backend_watch.node) 4.443 - unregister_xenbus_watch(&be->backend_watch); 4.444 - kfree(frontend); 4.445 - kfree(be); 4.446 - return err; 4.447 -} 4.448 + 4.449 +/* ** Driver Registration ** */ 4.450 + 4.451 4.452 static struct xenbus_device_id netback_ids[] = { 4.453 { "vif" }, 4.454 { "" } 4.455 }; 4.456 4.457 + 4.458 static struct xenbus_driver netback = { 4.459 .name = "vif", 4.460 .owner = THIS_MODULE, 4.461 @@ -269,13 +306,16 @@ static struct xenbus_driver netback = { 4.462 .probe = netback_probe, 4.463 .remove = netback_remove, 4.464 .hotplug = netback_hotplug, 4.465 + .otherend_changed = frontend_changed, 4.466 }; 4.467 4.468 + 4.469 void netif_xenbus_init(void) 4.470 { 4.471 xenbus_register_backend(&netback); 4.472 } 4.473 4.474 + 4.475 /* 4.476 * Local variables: 4.477 * c-file-style: "linux"
5.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Nov 11 18:01:44 2005 +0100 5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Nov 11 21:59:05 2005 +0100 5.3 @@ -2,6 +2,7 @@ 5.4 * Virtual network driver for conversing with remote driver backends. 5.5 * 5.6 * Copyright (c) 2002-2005, K A Fraser 5.7 + * Copyright (c) 2005, XenSource Ltd 5.8 * 5.9 * This file may be distributed separately from the Linux kernel, or 5.10 * incorporated into other software packages, subject to the following license: 5.11 @@ -56,6 +57,7 @@ 5.12 #include <asm/uaccess.h> 5.13 #include <asm-xen/xen-public/grant_table.h> 5.14 #include <asm-xen/gnttab.h> 5.15 +#include <asm-xen/net_driver_util.h> 5.16 5.17 #define GRANT_INVALID_REF 0 5.18 5.19 @@ -87,26 +89,11 @@ 5.20 #define TX_TEST_IDX req_cons /* conservative: not seen all our requests? */ 5.21 #endif 5.22 5.23 - 5.24 -static void network_tx_buf_gc(struct net_device *dev); 5.25 -static void network_alloc_rx_buffers(struct net_device *dev); 5.26 - 5.27 static unsigned long rx_pfn_array[NETIF_RX_RING_SIZE]; 5.28 static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1]; 5.29 static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE]; 5.30 5.31 -#ifdef CONFIG_PROC_FS 5.32 -static int xennet_proc_init(void); 5.33 -static int xennet_proc_addif(struct net_device *dev); 5.34 -static void xennet_proc_delif(struct net_device *dev); 5.35 -#else 5.36 -#define xennet_proc_init() (0) 5.37 -#define xennet_proc_addif(d) (0) 5.38 -#define xennet_proc_delif(d) ((void)0) 5.39 -#endif 5.40 - 5.41 -#define netfront_info net_private 5.42 -struct net_private 5.43 +struct netfront_info 5.44 { 5.45 struct list_head list; 5.46 struct net_device *netdev; 5.47 @@ -154,9 +141,6 @@ struct net_private 5.48 grant_ref_t grant_rx_ref[NETIF_TX_RING_SIZE + 1]; 5.49 5.50 struct xenbus_device *xbdev; 5.51 - char *backend; 5.52 - int backend_id; 5.53 - struct xenbus_watch watch; 5.54 int tx_ring_ref; 5.55 int rx_ring_ref; 5.56 u8 mac[ETH_ALEN]; 5.57 @@ -181,16 +165,256 @@ static char *be_state_name[] = { 5.58 5.59 #ifdef DEBUG 5.60 #define DPRINTK(fmt, args...) \ 5.61 - printk(KERN_ALERT "xen_net (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) 5.62 + printk(KERN_ALERT "netfront (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) 5.63 #else 5.64 #define DPRINTK(fmt, args...) ((void)0) 5.65 #endif 5.66 #define IPRINTK(fmt, args...) \ 5.67 - printk(KERN_INFO "xen_net: " fmt, ##args) 5.68 + printk(KERN_INFO "netfront: " fmt, ##args) 5.69 #define WPRINTK(fmt, args...) \ 5.70 - printk(KERN_WARNING "xen_net: " fmt, ##args) 5.71 + printk(KERN_WARNING "netfront: " fmt, ##args) 5.72 + 5.73 + 5.74 +static int talk_to_backend(struct xenbus_device *, struct netfront_info *); 5.75 +static int setup_device(struct xenbus_device *, struct netfront_info *); 5.76 +static int create_netdev(int, struct xenbus_device *, struct net_device **); 5.77 + 5.78 +static void netfront_closing(struct xenbus_device *); 5.79 + 5.80 +static void end_access(int, void *); 5.81 +static void netif_disconnect_backend(struct netfront_info *); 5.82 +static void close_netdev(struct netfront_info *); 5.83 +static void netif_free(struct netfront_info *); 5.84 + 5.85 +static void show_device(struct netfront_info *); 5.86 + 5.87 +static void network_connect(struct net_device *); 5.88 +static void network_tx_buf_gc(struct net_device *); 5.89 +static void network_alloc_rx_buffers(struct net_device *); 5.90 +static int send_fake_arp(struct net_device *); 5.91 + 5.92 +static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs); 5.93 + 5.94 +#ifdef CONFIG_PROC_FS 5.95 +static int xennet_proc_init(void); 5.96 +static int xennet_proc_addif(struct net_device *dev); 5.97 +static void xennet_proc_delif(struct net_device *dev); 5.98 +#else 5.99 +#define xennet_proc_init() (0) 5.100 +#define xennet_proc_addif(d) (0) 5.101 +#define xennet_proc_delif(d) ((void)0) 5.102 +#endif 5.103 + 5.104 + 5.105 +/** 5.106 + * Entry point to this code when a new device is created. Allocate the basic 5.107 + * structures and the ring buffers for communication with the backend, and 5.108 + * inform the backend of the appropriate details for those. Switch to 5.109 + * Connected state. 5.110 + */ 5.111 +static int netfront_probe(struct xenbus_device *dev, 5.112 + const struct xenbus_device_id *id) 5.113 +{ 5.114 + int err; 5.115 + struct net_device *netdev; 5.116 + struct netfront_info *info; 5.117 + unsigned int handle; 5.118 + 5.119 + err = xenbus_scanf(NULL, dev->nodename, "handle", "%u", &handle); 5.120 + if (err != 1) { 5.121 + xenbus_dev_fatal(dev, err, "reading handle"); 5.122 + return err; 5.123 + } 5.124 + 5.125 + err = create_netdev(handle, dev, &netdev); 5.126 + if (err) { 5.127 + xenbus_dev_fatal(dev, err, "creating netdev"); 5.128 + return err; 5.129 + } 5.130 + 5.131 + info = netdev_priv(netdev); 5.132 + dev->data = info; 5.133 + 5.134 + err = talk_to_backend(dev, info); 5.135 + if (err) { 5.136 + kfree(info); 5.137 + dev->data = NULL; 5.138 + return err; 5.139 + } 5.140 + 5.141 + return 0; 5.142 +} 5.143 + 5.144 + 5.145 +/** 5.146 + * We are reconnecting to the backend, due to a suspend/resume, or a backend 5.147 + * driver restart. We tear down our netif structure and recreate it, but 5.148 + * leave the device-layer structures intact so that this is transparent to the 5.149 + * rest of the kernel. 5.150 + */ 5.151 +static int netfront_resume(struct xenbus_device *dev) 5.152 +{ 5.153 + struct netfront_info *info = dev->data; 5.154 + 5.155 + DPRINTK("%s\n", dev->nodename); 5.156 + 5.157 + netif_disconnect_backend(info); 5.158 + return talk_to_backend(dev, info); 5.159 +} 5.160 + 5.161 + 5.162 +/* Common code used when first setting up, and when resuming. */ 5.163 +static int talk_to_backend(struct xenbus_device *dev, 5.164 + struct netfront_info *info) 5.165 +{ 5.166 + const char *message; 5.167 + struct xenbus_transaction *xbt; 5.168 + int err; 5.169 + 5.170 + err = xen_net_read_mac(dev, info->mac); 5.171 + if (err) { 5.172 + xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); 5.173 + goto out; 5.174 + } 5.175 + 5.176 + /* Create shared ring, alloc event channel. */ 5.177 + err = setup_device(dev, info); 5.178 + if (err) 5.179 + goto out; 5.180 + 5.181 +again: 5.182 + xbt = xenbus_transaction_start(); 5.183 + if (IS_ERR(xbt)) { 5.184 + xenbus_dev_fatal(dev, err, "starting transaction"); 5.185 + goto destroy_ring; 5.186 + } 5.187 5.188 -static void netif_free(struct netfront_info *info); 5.189 + err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u", 5.190 + info->tx_ring_ref); 5.191 + if (err) { 5.192 + message = "writing tx ring-ref"; 5.193 + goto abort_transaction; 5.194 + } 5.195 + err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u", 5.196 + info->rx_ring_ref); 5.197 + if (err) { 5.198 + message = "writing rx ring-ref"; 5.199 + goto abort_transaction; 5.200 + } 5.201 + err = xenbus_printf(xbt, dev->nodename, 5.202 + "event-channel", "%u", info->evtchn); 5.203 + if (err) { 5.204 + message = "writing event-channel"; 5.205 + goto abort_transaction; 5.206 + } 5.207 + 5.208 + err = xenbus_printf(xbt, dev->nodename, 5.209 + "state", "%d", XenbusStateConnected); 5.210 + if (err) { 5.211 + message = "writing frontend XenbusStateConnected"; 5.212 + goto abort_transaction; 5.213 + } 5.214 + 5.215 + err = xenbus_transaction_end(xbt, 0); 5.216 + if (err) { 5.217 + if (err == -EAGAIN) 5.218 + goto again; 5.219 + xenbus_dev_fatal(dev, err, "completing transaction"); 5.220 + goto destroy_ring; 5.221 + } 5.222 + 5.223 + return 0; 5.224 + 5.225 + abort_transaction: 5.226 + xenbus_transaction_end(xbt, 1); 5.227 + xenbus_dev_fatal(dev, err, "%s", message); 5.228 + destroy_ring: 5.229 + netif_free(info); 5.230 + out: 5.231 + return err; 5.232 +} 5.233 + 5.234 + 5.235 +static int setup_device(struct xenbus_device *dev, struct netfront_info *info) 5.236 +{ 5.237 + int err; 5.238 + struct net_device *netdev = info->netdev; 5.239 + 5.240 + info->tx_ring_ref = GRANT_INVALID_REF; 5.241 + info->rx_ring_ref = GRANT_INVALID_REF; 5.242 + info->rx = NULL; 5.243 + info->tx = NULL; 5.244 + info->irq = 0; 5.245 + 5.246 + info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); 5.247 + if (!info->tx) { 5.248 + err = -ENOMEM; 5.249 + xenbus_dev_fatal(dev, err, "allocating tx ring page"); 5.250 + goto fail; 5.251 + } 5.252 + info->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL); 5.253 + if (!info->rx) { 5.254 + err = -ENOMEM; 5.255 + xenbus_dev_fatal(dev, err, "allocating rx ring page"); 5.256 + goto fail; 5.257 + } 5.258 + memset(info->tx, 0, PAGE_SIZE); 5.259 + memset(info->rx, 0, PAGE_SIZE); 5.260 + info->backend_state = BEST_DISCONNECTED; 5.261 + 5.262 + err = xenbus_grant_ring(dev, virt_to_mfn(info->tx)); 5.263 + if (err < 0) 5.264 + goto fail; 5.265 + info->tx_ring_ref = err; 5.266 + 5.267 + err = xenbus_grant_ring(dev, virt_to_mfn(info->rx)); 5.268 + if (err < 0) 5.269 + goto fail; 5.270 + info->rx_ring_ref = err; 5.271 + 5.272 + err = xenbus_alloc_evtchn(dev, &info->evtchn); 5.273 + if (err) 5.274 + goto fail; 5.275 + 5.276 + memcpy(netdev->dev_addr, info->mac, ETH_ALEN); 5.277 + network_connect(netdev); 5.278 + info->irq = bind_evtchn_to_irqhandler( 5.279 + info->evtchn, netif_int, SA_SAMPLE_RANDOM, netdev->name, 5.280 + netdev); 5.281 + (void)send_fake_arp(netdev); 5.282 + show_device(info); 5.283 + 5.284 + return 0; 5.285 + 5.286 + fail: 5.287 + netif_free(info); 5.288 + return err; 5.289 +} 5.290 + 5.291 + 5.292 +/** 5.293 + * Callback received when the backend's state changes. 5.294 + */ 5.295 +static void backend_changed(struct xenbus_device *dev, 5.296 + XenbusState backend_state) 5.297 +{ 5.298 + DPRINTK("\n"); 5.299 + 5.300 + switch (backend_state) { 5.301 + case XenbusStateInitialising: 5.302 + case XenbusStateInitWait: 5.303 + case XenbusStateInitialised: 5.304 + case XenbusStateConnected: 5.305 + case XenbusStateUnknown: 5.306 + case XenbusStateClosed: 5.307 + break; 5.308 + 5.309 + case XenbusStateClosing: 5.310 + netfront_closing(dev); 5.311 + break; 5.312 + } 5.313 +} 5.314 + 5.315 5.316 /** Send a packet on a net device to encourage switches to learn the 5.317 * MAC. We send a fake ARP request. 5.318 @@ -220,9 +444,10 @@ static int send_fake_arp(struct net_devi 5.319 return dev_queue_xmit(skb); 5.320 } 5.321 5.322 + 5.323 static int network_open(struct net_device *dev) 5.324 { 5.325 - struct net_private *np = netdev_priv(dev); 5.326 + struct netfront_info *np = netdev_priv(dev); 5.327 5.328 memset(&np->stats, 0, sizeof(np->stats)); 5.329 5.330 @@ -240,7 +465,7 @@ static void network_tx_buf_gc(struct net 5.331 { 5.332 NETIF_RING_IDX i, prod; 5.333 unsigned short id; 5.334 - struct net_private *np = netdev_priv(dev); 5.335 + struct netfront_info *np = netdev_priv(dev); 5.336 struct sk_buff *skb; 5.337 5.338 if (np->backend_state != BEST_CONNECTED) 5.339 @@ -295,7 +520,7 @@ static void network_tx_buf_gc(struct net 5.340 static void network_alloc_rx_buffers(struct net_device *dev) 5.341 { 5.342 unsigned short id; 5.343 - struct net_private *np = netdev_priv(dev); 5.344 + struct netfront_info *np = netdev_priv(dev); 5.345 struct sk_buff *skb; 5.346 int i, batch_target; 5.347 NETIF_RING_IDX req_prod = np->rx->req_prod; 5.348 @@ -337,7 +562,8 @@ static void network_alloc_rx_buffers(str 5.349 ref = gnttab_claim_grant_reference(&np->gref_rx_head); 5.350 BUG_ON((signed short)ref < 0); 5.351 np->grant_rx_ref[id] = ref; 5.352 - gnttab_grant_foreign_transfer_ref(ref, np->backend_id); 5.353 + gnttab_grant_foreign_transfer_ref(ref, 5.354 + np->xbdev->otherend_id); 5.355 np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref; 5.356 rx_pfn_array[i] = virt_to_mfn(skb->head); 5.357 5.358 @@ -385,7 +611,7 @@ static void network_alloc_rx_buffers(str 5.359 static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) 5.360 { 5.361 unsigned short id; 5.362 - struct net_private *np = netdev_priv(dev); 5.363 + struct netfront_info *np = netdev_priv(dev); 5.364 netif_tx_request_t *tx; 5.365 NETIF_RING_IDX i; 5.366 grant_ref_t ref; 5.367 @@ -429,7 +655,7 @@ static int network_start_xmit(struct sk_ 5.368 BUG_ON((signed short)ref < 0); 5.369 mfn = virt_to_mfn(skb->data); 5.370 gnttab_grant_foreign_access_ref( 5.371 - ref, np->backend_id, mfn, GNTMAP_readonly); 5.372 + ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly); 5.373 tx->gref = np->grant_tx_ref[id] = ref; 5.374 tx->offset = (unsigned long)skb->data & ~PAGE_MASK; 5.375 tx->size = skb->len; 5.376 @@ -466,7 +692,7 @@ static int network_start_xmit(struct sk_ 5.377 static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs) 5.378 { 5.379 struct net_device *dev = dev_id; 5.380 - struct net_private *np = netdev_priv(dev); 5.381 + struct netfront_info *np = netdev_priv(dev); 5.382 unsigned long flags; 5.383 5.384 spin_lock_irqsave(&np->tx_lock, flags); 5.385 @@ -483,7 +709,7 @@ static irqreturn_t netif_int(int irq, vo 5.386 5.387 static int netif_poll(struct net_device *dev, int *pbudget) 5.388 { 5.389 - struct net_private *np = netdev_priv(dev); 5.390 + struct netfront_info *np = netdev_priv(dev); 5.391 struct sk_buff *skb, *nskb; 5.392 netif_rx_response_t *rx; 5.393 NETIF_RING_IDX i, rp; 5.394 @@ -534,7 +760,7 @@ static int netif_poll(struct net_device 5.395 if(ref == GRANT_INVALID_REF) { 5.396 printk(KERN_WARNING "Bad rx grant reference %d " 5.397 "from dom %d.\n", 5.398 - ref, np->backend_id); 5.399 + ref, np->xbdev->otherend_id); 5.400 np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)]. 5.401 req.id = rx->id; 5.402 wmb(); 5.403 @@ -678,7 +904,7 @@ static int netif_poll(struct net_device 5.404 5.405 static int network_close(struct net_device *dev) 5.406 { 5.407 - struct net_private *np = netdev_priv(dev); 5.408 + struct netfront_info *np = netdev_priv(dev); 5.409 np->user_state = UST_CLOSED; 5.410 netif_stop_queue(np->netdev); 5.411 return 0; 5.412 @@ -687,13 +913,13 @@ static int network_close(struct net_devi 5.413 5.414 static struct net_device_stats *network_get_stats(struct net_device *dev) 5.415 { 5.416 - struct net_private *np = netdev_priv(dev); 5.417 + struct netfront_info *np = netdev_priv(dev); 5.418 return &np->stats; 5.419 } 5.420 5.421 static void network_connect(struct net_device *dev) 5.422 { 5.423 - struct net_private *np; 5.424 + struct netfront_info *np; 5.425 int i, requeue_idx; 5.426 netif_tx_request_t *tx; 5.427 struct sk_buff *skb; 5.428 @@ -736,7 +962,7 @@ static void network_connect(struct net_d 5.429 5.430 tx->id = i; 5.431 gnttab_grant_foreign_access_ref( 5.432 - np->grant_tx_ref[i], np->backend_id, 5.433 + np->grant_tx_ref[i], np->xbdev->otherend_id, 5.434 virt_to_mfn(np->tx_skbs[i]->data), 5.435 GNTMAP_readonly); 5.436 tx->gref = np->grant_tx_ref[i]; 5.437 @@ -755,7 +981,7 @@ static void network_connect(struct net_d 5.438 if ((unsigned long)np->rx_skbs[i] < __PAGE_OFFSET) 5.439 continue; 5.440 gnttab_grant_foreign_transfer_ref( 5.441 - np->grant_rx_ref[i], np->backend_id); 5.442 + np->grant_rx_ref[i], np->xbdev->otherend_id); 5.443 np->rx->ring[requeue_idx].req.gref = 5.444 np->grant_rx_ref[i]; 5.445 np->rx->ring[requeue_idx].req.id = i; 5.446 @@ -782,7 +1008,7 @@ static void network_connect(struct net_d 5.447 spin_unlock_irq(&np->tx_lock); 5.448 } 5.449 5.450 -static void show_device(struct net_private *np) 5.451 +static void show_device(struct netfront_info *np) 5.452 { 5.453 #ifdef DEBUG 5.454 if (np) { 5.455 @@ -799,27 +1025,9 @@ static void show_device(struct net_priva 5.456 #endif 5.457 } 5.458 5.459 -/* 5.460 - * Move the vif into connected state. 5.461 - * Sets the mac and event channel from the message. 5.462 - * Binds the irq to the event channel. 5.463 - */ 5.464 -static void 5.465 -connect_device(struct net_private *np, unsigned int evtchn) 5.466 -{ 5.467 - struct net_device *dev = np->netdev; 5.468 - memcpy(dev->dev_addr, np->mac, ETH_ALEN); 5.469 - np->evtchn = evtchn; 5.470 - network_connect(dev); 5.471 - np->irq = bind_evtchn_to_irqhandler( 5.472 - np->evtchn, netif_int, SA_SAMPLE_RANDOM, dev->name, dev); 5.473 - (void)send_fake_arp(dev); 5.474 - show_device(np); 5.475 -} 5.476 - 5.477 static void netif_uninit(struct net_device *dev) 5.478 { 5.479 - struct net_private *np = netdev_priv(dev); 5.480 + struct netfront_info *np = netdev_priv(dev); 5.481 gnttab_free_grant_references(np->gref_tx_head); 5.482 gnttab_free_grant_references(np->gref_rx_head); 5.483 } 5.484 @@ -840,9 +1048,9 @@ static int create_netdev(int handle, str 5.485 { 5.486 int i, err = 0; 5.487 struct net_device *netdev = NULL; 5.488 - struct net_private *np = NULL; 5.489 + struct netfront_info *np = NULL; 5.490 5.491 - if ((netdev = alloc_etherdev(sizeof(struct net_private))) == NULL) { 5.492 + if ((netdev = alloc_etherdev(sizeof(struct netfront_info))) == NULL) { 5.493 printk(KERN_WARNING "%s> alloc_etherdev failed.\n", 5.494 __FUNCTION__); 5.495 err = -ENOMEM; 5.496 @@ -929,15 +1137,6 @@ static int create_netdev(int handle, str 5.497 goto exit; 5.498 } 5.499 5.500 -static int destroy_netdev(struct net_device *netdev) 5.501 -{ 5.502 -#ifdef CONFIG_PROC_FS 5.503 - xennet_proc_delif(netdev); 5.504 -#endif 5.505 - unregister_netdev(netdev); 5.506 - return 0; 5.507 -} 5.508 - 5.509 /* 5.510 * We use this notifier to send out a fake ARP reply to reset switches and 5.511 * router ARP caches when an IP interface is brought up on a VIF. 5.512 @@ -955,91 +1154,70 @@ inetdev_notify(struct notifier_block *th 5.513 return NOTIFY_DONE; 5.514 } 5.515 5.516 -static struct notifier_block notifier_inetdev = { 5.517 - .notifier_call = inetdev_notify, 5.518 - .next = NULL, 5.519 - .priority = 0 5.520 -}; 5.521 + 5.522 +/* ** Close down ** */ 5.523 + 5.524 5.525 -static struct xenbus_device_id netfront_ids[] = { 5.526 - { "vif" }, 5.527 - { "" } 5.528 -}; 5.529 +/** 5.530 + * Handle the change of state of the backend to Closing. We must delete our 5.531 + * device-layer structures now, to ensure that writes are flushed through to 5.532 + * the backend. Once is this done, we can switch to Closed in 5.533 + * acknowledgement. 5.534 + */ 5.535 +static void netfront_closing(struct xenbus_device *dev) 5.536 +{ 5.537 + struct netfront_info *info = dev->data; 5.538 5.539 -static void watch_for_status(struct xenbus_watch *watch, 5.540 - const char **vec, unsigned int len) 5.541 -{ 5.542 + DPRINTK("netfront_closing: %s removed\n", dev->nodename); 5.543 + 5.544 + close_netdev(info); 5.545 + 5.546 + xenbus_switch_state(dev, NULL, XenbusStateClosed); 5.547 } 5.548 5.549 -static int setup_device(struct xenbus_device *dev, struct netfront_info *info) 5.550 + 5.551 +static int netfront_remove(struct xenbus_device *dev) 5.552 { 5.553 - int err; 5.554 - evtchn_op_t op = { 5.555 - .cmd = EVTCHNOP_alloc_unbound, 5.556 - .u.alloc_unbound.dom = DOMID_SELF, 5.557 - .u.alloc_unbound.remote_dom = info->backend_id }; 5.558 - 5.559 - info->tx_ring_ref = GRANT_INVALID_REF; 5.560 - info->rx_ring_ref = GRANT_INVALID_REF; 5.561 - info->rx = NULL; 5.562 - info->tx = NULL; 5.563 - info->irq = 0; 5.564 + struct netfront_info *info = dev->data; 5.565 5.566 - info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); 5.567 - if (info->tx == 0) { 5.568 - err = -ENOMEM; 5.569 - xenbus_dev_error(dev, err, "allocating tx ring page"); 5.570 - goto out; 5.571 - } 5.572 - info->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL); 5.573 - if (info->rx == 0) { 5.574 - err = -ENOMEM; 5.575 - xenbus_dev_error(dev, err, "allocating rx ring page"); 5.576 - goto out; 5.577 - } 5.578 - memset(info->tx, 0, PAGE_SIZE); 5.579 - memset(info->rx, 0, PAGE_SIZE); 5.580 - info->backend_state = BEST_DISCONNECTED; 5.581 + DPRINTK("%s\n", dev->nodename); 5.582 5.583 - err = gnttab_grant_foreign_access(info->backend_id, 5.584 - virt_to_mfn(info->tx), 0); 5.585 - if (err < 0) { 5.586 - xenbus_dev_error(dev, err, "granting access to tx ring page"); 5.587 - goto out; 5.588 - } 5.589 - info->tx_ring_ref = err; 5.590 - 5.591 - err = gnttab_grant_foreign_access(info->backend_id, 5.592 - virt_to_mfn(info->rx), 0); 5.593 - if (err < 0) { 5.594 - xenbus_dev_error(dev, err, "granting access to rx ring page"); 5.595 - goto out; 5.596 - } 5.597 - info->rx_ring_ref = err; 5.598 - 5.599 - err = HYPERVISOR_event_channel_op(&op); 5.600 - if (err) { 5.601 - xenbus_dev_error(dev, err, "allocating event channel"); 5.602 - goto out; 5.603 - } 5.604 - 5.605 - connect_device(info, op.u.alloc_unbound.port); 5.606 + netif_free(info); 5.607 + kfree(info); 5.608 5.609 return 0; 5.610 - 5.611 - out: 5.612 - netif_free(info); 5.613 - return err; 5.614 } 5.615 5.616 -static void end_access(int ref, void *page) 5.617 -{ 5.618 - if (ref != GRANT_INVALID_REF) 5.619 - gnttab_end_foreign_access(ref, 0, (unsigned long)page); 5.620 -} 5.621 5.622 static void netif_free(struct netfront_info *info) 5.623 { 5.624 + netif_disconnect_backend(info); 5.625 + close_netdev(info); 5.626 +} 5.627 + 5.628 + 5.629 +static void close_netdev(struct netfront_info *info) 5.630 +{ 5.631 + if (info->netdev) { 5.632 +#ifdef CONFIG_PROC_FS 5.633 + xennet_proc_delif(info->netdev); 5.634 +#endif 5.635 + unregister_netdev(info->netdev); 5.636 + info->netdev = NULL; 5.637 + } 5.638 +} 5.639 + 5.640 + 5.641 +static void netif_disconnect_backend(struct netfront_info *info) 5.642 +{ 5.643 + /* Stop old i/f to prevent errors whilst we rebuild the state. */ 5.644 + spin_lock_irq(&info->tx_lock); 5.645 + spin_lock(&info->rx_lock); 5.646 + netif_stop_queue(info->netdev); 5.647 + /* info->backend_state = BEST_DISCONNECTED; */ 5.648 + spin_unlock(&info->rx_lock); 5.649 + spin_unlock_irq(&info->tx_lock); 5.650 + 5.651 end_access(info->tx_ring_ref, info->tx); 5.652 end_access(info->rx_ring_ref, info->rx); 5.653 info->tx_ring_ref = GRANT_INVALID_REF; 5.654 @@ -1052,202 +1230,22 @@ static void netif_free(struct netfront_i 5.655 info->evtchn = info->irq = 0; 5.656 } 5.657 5.658 -/* Stop network device and free tx/rx queues and irq. */ 5.659 -static void shutdown_device(struct net_private *np) 5.660 + 5.661 +static void end_access(int ref, void *page) 5.662 { 5.663 - /* Stop old i/f to prevent errors whilst we rebuild the state. */ 5.664 - spin_lock_irq(&np->tx_lock); 5.665 - spin_lock(&np->rx_lock); 5.666 - netif_stop_queue(np->netdev); 5.667 - /* np->backend_state = BEST_DISCONNECTED; */ 5.668 - spin_unlock(&np->rx_lock); 5.669 - spin_unlock_irq(&np->tx_lock); 5.670 - 5.671 - /* Free resources. */ 5.672 - netif_free(np); 5.673 + if (ref != GRANT_INVALID_REF) 5.674 + gnttab_end_foreign_access(ref, 0, (unsigned long)page); 5.675 } 5.676 5.677 -/* Common code used when first setting up, and when resuming. */ 5.678 -static int talk_to_backend(struct xenbus_device *dev, 5.679 - struct netfront_info *info) 5.680 -{ 5.681 - char *backend, *mac, *e, *s; 5.682 - const char *message; 5.683 - struct xenbus_transaction *xbt; 5.684 - int err, i; 5.685 - 5.686 - backend = NULL; 5.687 - err = xenbus_gather(NULL, dev->nodename, 5.688 - "backend-id", "%i", &info->backend_id, 5.689 - "backend", NULL, &backend, 5.690 - NULL); 5.691 - if (XENBUS_EXIST_ERR(err)) 5.692 - goto out; 5.693 - if (backend && strlen(backend) == 0) { 5.694 - err = -ENOENT; 5.695 - goto out; 5.696 - } 5.697 - if (err < 0) { 5.698 - xenbus_dev_error(dev, err, "reading %s/backend or backend-id", 5.699 - dev->nodename); 5.700 - goto out; 5.701 - } 5.702 5.703 - mac = xenbus_read(NULL, dev->nodename, "mac", NULL); 5.704 - if (IS_ERR(mac)) { 5.705 - err = PTR_ERR(mac); 5.706 - xenbus_dev_error(dev, err, "reading %s/mac", 5.707 - dev->nodename); 5.708 - goto out; 5.709 - } 5.710 - s = mac; 5.711 - for (i = 0; i < ETH_ALEN; i++) { 5.712 - info->mac[i] = simple_strtoul(s, &e, 16); 5.713 - if (s == e || (e[0] != ':' && e[0] != 0)) { 5.714 - kfree(mac); 5.715 - err = -ENOENT; 5.716 - xenbus_dev_error(dev, err, "parsing %s/mac", 5.717 - dev->nodename); 5.718 - goto out; 5.719 - } 5.720 - s = &e[1]; 5.721 - } 5.722 - kfree(mac); 5.723 - 5.724 - /* Create shared ring, alloc event channel. */ 5.725 - err = setup_device(dev, info); 5.726 - if (err) { 5.727 - xenbus_dev_error(dev, err, "setting up ring"); 5.728 - goto out; 5.729 - } 5.730 +/* ** Driver registration ** */ 5.731 5.732 -again: 5.733 - xbt = xenbus_transaction_start(); 5.734 - if (IS_ERR(xbt)) { 5.735 - xenbus_dev_error(dev, err, "starting transaction"); 5.736 - goto destroy_ring; 5.737 - } 5.738 - 5.739 - err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u", 5.740 - info->tx_ring_ref); 5.741 - if (err) { 5.742 - message = "writing tx ring-ref"; 5.743 - goto abort_transaction; 5.744 - } 5.745 - err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u", 5.746 - info->rx_ring_ref); 5.747 - if (err) { 5.748 - message = "writing rx ring-ref"; 5.749 - goto abort_transaction; 5.750 - } 5.751 - err = xenbus_printf(xbt, dev->nodename, 5.752 - "event-channel", "%u", info->evtchn); 5.753 - if (err) { 5.754 - message = "writing event-channel"; 5.755 - goto abort_transaction; 5.756 - } 5.757 - 5.758 - err = xenbus_transaction_end(xbt, 0); 5.759 - if (err) { 5.760 - if (err == -EAGAIN) 5.761 - goto again; 5.762 - xenbus_dev_error(dev, err, "completing transaction"); 5.763 - goto destroy_ring; 5.764 - } 5.765 5.766 - info->watch.node = backend; 5.767 - info->watch.callback = watch_for_status; 5.768 - err = register_xenbus_watch(&info->watch); 5.769 - if (err) { 5.770 - message = "registering watch on backend"; 5.771 - goto destroy_ring; 5.772 - } 5.773 - 5.774 - info->backend = backend; 5.775 - 5.776 - return 0; 5.777 - 5.778 - abort_transaction: 5.779 - xenbus_transaction_end(xbt, 1); 5.780 - xenbus_dev_error(dev, err, "%s", message); 5.781 - destroy_ring: 5.782 - shutdown_device(info); 5.783 - out: 5.784 - kfree(backend); 5.785 - return err; 5.786 -} 5.787 - 5.788 -/* 5.789 - * Setup supplies the backend dir, virtual device. 5.790 - * We place an event channel and shared frame entries. 5.791 - * We watch backend to wait if it's ok. 5.792 - */ 5.793 -static int netfront_probe(struct xenbus_device *dev, 5.794 - const struct xenbus_device_id *id) 5.795 -{ 5.796 - int err; 5.797 - struct net_device *netdev; 5.798 - struct netfront_info *info; 5.799 - unsigned int handle; 5.800 - 5.801 - err = xenbus_scanf(NULL, dev->nodename, "handle", "%u", &handle); 5.802 - if (XENBUS_EXIST_ERR(err)) 5.803 - return err; 5.804 - if (err < 0) { 5.805 - xenbus_dev_error(dev, err, "reading handle"); 5.806 - return err; 5.807 - } 5.808 +static struct xenbus_device_id netfront_ids[] = { 5.809 + { "vif" }, 5.810 + { "" } 5.811 +}; 5.812 5.813 - err = create_netdev(handle, dev, &netdev); 5.814 - if (err) { 5.815 - xenbus_dev_error(dev, err, "creating netdev"); 5.816 - return err; 5.817 - } 5.818 - 5.819 - info = netdev_priv(netdev); 5.820 - dev->data = info; 5.821 - 5.822 - err = talk_to_backend(dev, info); 5.823 - if (err) { 5.824 - destroy_netdev(netdev); 5.825 - kfree(netdev); 5.826 - dev->data = NULL; 5.827 - return err; 5.828 - } 5.829 - 5.830 - return 0; 5.831 -} 5.832 - 5.833 -static int netfront_remove(struct xenbus_device *dev) 5.834 -{ 5.835 - struct netfront_info *info = dev->data; 5.836 - 5.837 - if (info->backend) 5.838 - unregister_xenbus_watch(&info->watch); 5.839 - 5.840 - netif_free(info); 5.841 - 5.842 - kfree(info->backend); 5.843 - kfree(info); 5.844 - 5.845 - return 0; 5.846 -} 5.847 - 5.848 -static int netfront_suspend(struct xenbus_device *dev) 5.849 -{ 5.850 - struct netfront_info *info = dev->data; 5.851 - unregister_xenbus_watch(&info->watch); 5.852 - kfree(info->backend); 5.853 - info->backend = NULL; 5.854 - return 0; 5.855 -} 5.856 - 5.857 -static int netfront_resume(struct xenbus_device *dev) 5.858 -{ 5.859 - struct netfront_info *info = dev->data; 5.860 - netif_free(info); 5.861 - return talk_to_backend(dev, info); 5.862 -} 5.863 5.864 static struct xenbus_driver netfront = { 5.865 .name = "vif", 5.866 @@ -1256,13 +1254,15 @@ static struct xenbus_driver netfront = { 5.867 .probe = netfront_probe, 5.868 .remove = netfront_remove, 5.869 .resume = netfront_resume, 5.870 - .suspend = netfront_suspend, 5.871 + .otherend_changed = backend_changed, 5.872 }; 5.873 5.874 -static void __init init_net_xenbus(void) 5.875 -{ 5.876 - xenbus_register_driver(&netfront); 5.877 -} 5.878 + 5.879 +static struct notifier_block notifier_inetdev = { 5.880 + .notifier_call = inetdev_notify, 5.881 + .next = NULL, 5.882 + .priority = 0 5.883 +}; 5.884 5.885 static int __init netif_init(void) 5.886 { 5.887 @@ -1278,14 +1278,24 @@ static int __init netif_init(void) 5.888 5.889 (void)register_inetaddr_notifier(¬ifier_inetdev); 5.890 5.891 - init_net_xenbus(); 5.892 + return xenbus_register_frontend(&netfront); 5.893 +} 5.894 +module_init(netif_init); 5.895 5.896 - return err; 5.897 -} 5.898 5.899 static void netif_exit(void) 5.900 { 5.901 + unregister_inetaddr_notifier(¬ifier_inetdev); 5.902 + 5.903 + return xenbus_unregister_driver(&netfront); 5.904 } 5.905 +module_exit(netif_exit); 5.906 + 5.907 +MODULE_LICENSE("BSD"); 5.908 + 5.909 + 5.910 +/* ** /proc **/ 5.911 + 5.912 5.913 #ifdef CONFIG_PROC_FS 5.914 5.915 @@ -1298,7 +1308,7 @@ static int xennet_proc_read( 5.916 { 5.917 struct net_device *dev = 5.918 (struct net_device *)((unsigned long)data & ~3UL); 5.919 - struct net_private *np = netdev_priv(dev); 5.920 + struct netfront_info *np = netdev_priv(dev); 5.921 int len = 0, which_target = (long)data & 3; 5.922 5.923 switch (which_target) 5.924 @@ -1324,7 +1334,7 @@ static int xennet_proc_write( 5.925 { 5.926 struct net_device *dev = 5.927 (struct net_device *)((unsigned long)data & ~3UL); 5.928 - struct net_private *np = netdev_priv(dev); 5.929 + struct netfront_info *np = netdev_priv(dev); 5.930 int which_target = (long)data & 3; 5.931 char string[64]; 5.932 long target; 5.933 @@ -1438,8 +1448,6 @@ static void xennet_proc_delif(struct net 5.934 5.935 #endif 5.936 5.937 -module_init(netif_init); 5.938 -module_exit(netif_exit); 5.939 5.940 /* 5.941 * Local variables:
6.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile Fri Nov 11 18:01:44 2005 +0100 6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile Fri Nov 11 21:59:05 2005 +0100 6.3 @@ -1,6 +1,7 @@ 6.4 obj-y += xenbus.o 6.5 6.6 xenbus-objs = 6.7 +xenbus-objs += xenbus_client.o 6.8 xenbus-objs += xenbus_comms.o 6.9 xenbus-objs += xenbus_xs.o 6.10 xenbus-objs += xenbus_probe.o
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Fri Nov 11 21:59:05 2005 +0100 7.3 @@ -0,0 +1,253 @@ 7.4 +/****************************************************************************** 7.5 + * Client-facing interface for the Xenbus driver. In other words, the 7.6 + * interface between the Xenbus and the device-specific code, be it the 7.7 + * frontend or the backend of that driver. 7.8 + * 7.9 + * Copyright (C) 2005 XenSource Ltd 7.10 + * 7.11 + * This file may be distributed separately from the Linux kernel, or 7.12 + * incorporated into other software packages, subject to the following license: 7.13 + * 7.14 + * Permission is hereby granted, free of charge, to any person obtaining a copy 7.15 + * of this source file (the "Software"), to deal in the Software without 7.16 + * restriction, including without limitation the rights to use, copy, modify, 7.17 + * merge, publish, distribute, sublicense, and/or sell copies of the Software, 7.18 + * and to permit persons to whom the Software is furnished to do so, subject to 7.19 + * the following conditions: 7.20 + * 7.21 + * The above copyright notice and this permission notice shall be included in 7.22 + * all copies or substantial portions of the Software. 7.23 + * 7.24 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 7.25 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7.26 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 7.27 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 7.28 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 7.29 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 7.30 + * IN THE SOFTWARE. 7.31 + */ 7.32 + 7.33 + 7.34 +#if 0 7.35 +#define DPRINTK(fmt, args...) \ 7.36 + printk("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) 7.37 +#else 7.38 +#define DPRINTK(fmt, args...) ((void)0) 7.39 +#endif 7.40 + 7.41 + 7.42 +#include <asm-xen/evtchn.h> 7.43 +#include <asm-xen/gnttab.h> 7.44 +#include <asm-xen/xenbus.h> 7.45 + 7.46 + 7.47 +int xenbus_watch_path(struct xenbus_device *dev, const char *path, 7.48 + struct xenbus_watch *watch, 7.49 + void (*callback)(struct xenbus_watch *, 7.50 + const char **, unsigned int)) 7.51 +{ 7.52 + int err; 7.53 + 7.54 + watch->node = path; 7.55 + watch->callback = callback; 7.56 + 7.57 + err = register_xenbus_watch(watch); 7.58 + 7.59 + if (err) { 7.60 + watch->node = NULL; 7.61 + watch->callback = NULL; 7.62 + xenbus_dev_fatal(dev, err, "adding watch on %s", path); 7.63 + } 7.64 + 7.65 + return err; 7.66 +} 7.67 +EXPORT_SYMBOL(xenbus_watch_path); 7.68 + 7.69 + 7.70 +int xenbus_watch_path2(struct xenbus_device *dev, const char *path, 7.71 + const char *path2, struct xenbus_watch *watch, 7.72 + void (*callback)(struct xenbus_watch *, 7.73 + const char **, unsigned int)) 7.74 +{ 7.75 + int err; 7.76 + char *state = 7.77 + kmalloc(strlen(path) + 1 + strlen(path2) + 1, GFP_KERNEL); 7.78 + if (!state) { 7.79 + xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch"); 7.80 + return -ENOMEM; 7.81 + } 7.82 + strcpy(state, path); 7.83 + strcat(state, "/"); 7.84 + strcat(state, path2); 7.85 + 7.86 + err = xenbus_watch_path(dev, state, watch, callback); 7.87 + 7.88 + if (err) { 7.89 + kfree(state); 7.90 + } 7.91 + return err; 7.92 +} 7.93 +EXPORT_SYMBOL(xenbus_watch_path2); 7.94 + 7.95 + 7.96 +int xenbus_switch_state(struct xenbus_device *dev, 7.97 + struct xenbus_transaction *xbt, 7.98 + XenbusState state) 7.99 +{ 7.100 + /* We check whether the state is currently set to the given value, and 7.101 + if not, then the state is set. We don't want to unconditionally 7.102 + write the given state, because we don't want to fire watches 7.103 + unnecessarily. 7.104 + */ 7.105 + 7.106 + int current_state; 7.107 + 7.108 + int err = xenbus_scanf(xbt, dev->nodename, "state", "%d", 7.109 + ¤t_state); 7.110 + if (err == 1 && (XenbusState)current_state == state) 7.111 + return 0; 7.112 + 7.113 + err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); 7.114 + if (err) { 7.115 + xenbus_dev_fatal(dev, err, "writing new state"); 7.116 + return err; 7.117 + } 7.118 + return 0; 7.119 +} 7.120 +EXPORT_SYMBOL(xenbus_switch_state); 7.121 + 7.122 + 7.123 +/** 7.124 + * Return the path to the error node for the given device, or NULL on failure. 7.125 + * If the value returned is non-NULL, then it is the caller's to kfree. 7.126 + */ 7.127 +static char *error_path(struct xenbus_device *dev) 7.128 +{ 7.129 + char *path_buffer = kmalloc(strlen("error/") + strlen(dev->nodename) + 7.130 + 1, GFP_KERNEL); 7.131 + if (path_buffer == NULL) { 7.132 + return NULL; 7.133 + } 7.134 + 7.135 + strcpy(path_buffer, "error/"); 7.136 + strcpy(path_buffer + strlen("error/"), dev->nodename); 7.137 + 7.138 + return path_buffer; 7.139 +} 7.140 + 7.141 + 7.142 +void _dev_error(struct xenbus_device *dev, int err, const char *fmt, 7.143 + va_list ap) 7.144 +{ 7.145 + int ret; 7.146 + unsigned int len; 7.147 + char *printf_buffer = NULL, *path_buffer = NULL; 7.148 + 7.149 +#define PRINTF_BUFFER_SIZE 4096 7.150 + printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); 7.151 + if (printf_buffer == NULL) 7.152 + goto fail; 7.153 + 7.154 + len = sprintf(printf_buffer, "%i ", -err); 7.155 + ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); 7.156 + 7.157 + BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1); 7.158 + dev->has_error = 1; 7.159 + 7.160 + path_buffer = error_path(dev); 7.161 + 7.162 + if (path_buffer == NULL) { 7.163 + printk("xenbus: failed to write error node for %s (%s)\n", 7.164 + dev->nodename, printf_buffer); 7.165 + goto fail; 7.166 + } 7.167 + 7.168 + if (xenbus_write(NULL, path_buffer, "error", printf_buffer) != 0) { 7.169 + printk("xenbus: failed to write error node for %s (%s)\n", 7.170 + dev->nodename, printf_buffer); 7.171 + goto fail; 7.172 + } 7.173 + 7.174 +fail: 7.175 + if (printf_buffer) 7.176 + kfree(printf_buffer); 7.177 + if (path_buffer) 7.178 + kfree(path_buffer); 7.179 +} 7.180 + 7.181 + 7.182 +void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, 7.183 + ...) 7.184 +{ 7.185 + va_list ap; 7.186 + 7.187 + va_start(ap, fmt); 7.188 + _dev_error(dev, err, fmt, ap); 7.189 + va_end(ap); 7.190 +} 7.191 +EXPORT_SYMBOL(xenbus_dev_error); 7.192 + 7.193 + 7.194 +void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, 7.195 + ...) 7.196 +{ 7.197 + va_list ap; 7.198 + 7.199 + va_start(ap, fmt); 7.200 + _dev_error(dev, err, fmt, ap); 7.201 + va_end(ap); 7.202 + 7.203 + xenbus_switch_state(dev, NULL, XenbusStateClosing); 7.204 +} 7.205 +EXPORT_SYMBOL(xenbus_dev_fatal); 7.206 + 7.207 + 7.208 +int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn) 7.209 +{ 7.210 + int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0); 7.211 + if (err < 0) 7.212 + xenbus_dev_fatal(dev, err, "granting access to ring page"); 7.213 + return err; 7.214 +} 7.215 +EXPORT_SYMBOL(xenbus_grant_ring); 7.216 + 7.217 + 7.218 +int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port) 7.219 +{ 7.220 + evtchn_op_t op = { 7.221 + .cmd = EVTCHNOP_alloc_unbound, 7.222 + .u.alloc_unbound.dom = DOMID_SELF, 7.223 + .u.alloc_unbound.remote_dom = dev->otherend_id }; 7.224 + 7.225 + int err = HYPERVISOR_event_channel_op(&op); 7.226 + if (err) 7.227 + xenbus_dev_fatal(dev, err, "allocating event channel"); 7.228 + else 7.229 + *port = op.u.alloc_unbound.port; 7.230 + return err; 7.231 +} 7.232 +EXPORT_SYMBOL(xenbus_alloc_evtchn); 7.233 + 7.234 + 7.235 +XenbusState xenbus_read_driver_state(const char *path) 7.236 +{ 7.237 + XenbusState result; 7.238 + 7.239 + int err = xenbus_gather(NULL, path, "state", "%d", &result, NULL); 7.240 + if (err) 7.241 + result = XenbusStateClosed; 7.242 + 7.243 + return result; 7.244 +} 7.245 +EXPORT_SYMBOL(xenbus_read_driver_state); 7.246 + 7.247 + 7.248 +/* 7.249 + * Local variables: 7.250 + * c-file-style: "linux" 7.251 + * indent-tabs-mode: t 7.252 + * c-indent-level: 8 7.253 + * c-basic-offset: 8 7.254 + * tab-width: 8 7.255 + * End: 7.256 + */
8.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Nov 11 18:01:44 2005 +0100 8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Nov 11 21:59:05 2005 +0100 8.3 @@ -3,6 +3,7 @@ 8.4 * 8.5 * Copyright (C) 2005 Rusty Russell, IBM Corporation 8.6 * Copyright (C) 2005 Mike Wray, Hewlett-Packard 8.7 + * Copyright (C) 2005 XenSource Ltd 8.8 * 8.9 * This file may be distributed separately from the Linux kernel, or 8.10 * incorporated into other software packages, subject to the following license: 8.11 @@ -25,7 +26,13 @@ 8.12 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 8.13 * IN THE SOFTWARE. 8.14 */ 8.15 -#define DEBUG 8.16 + 8.17 +#if 0 8.18 +#define DPRINTK(fmt, args...) \ 8.19 + printk("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) 8.20 +#else 8.21 +#define DPRINTK(fmt, args...) ((void)0) 8.22 +#endif 8.23 8.24 #include <linux/kernel.h> 8.25 #include <linux/err.h> 8.26 @@ -85,6 +92,7 @@ struct xen_bus_type 8.27 struct device dev; 8.28 }; 8.29 8.30 + 8.31 /* device/<type>/<id> => <type>-<id> */ 8.32 static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) 8.33 { 8.34 @@ -103,6 +111,62 @@ static int frontend_bus_id(char bus_id[B 8.35 return 0; 8.36 } 8.37 8.38 + 8.39 +static int read_otherend_details(struct xenbus_device *xendev, 8.40 + char *id_node, char *path_node) 8.41 +{ 8.42 + int err = xenbus_gather(NULL, xendev->nodename, 8.43 + id_node, "%i", &xendev->otherend_id, 8.44 + path_node, NULL, &xendev->otherend, 8.45 + NULL); 8.46 + if (err) { 8.47 + xenbus_dev_fatal(xendev, err, 8.48 + "reading other end details from %s", 8.49 + xendev->nodename); 8.50 + return err; 8.51 + } 8.52 + if (strlen(xendev->otherend) == 0 || 8.53 + !xenbus_exists(NULL, xendev->otherend, "")) { 8.54 + xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s", 8.55 + xendev->nodename); 8.56 + kfree(xendev->otherend); 8.57 + xendev->otherend = NULL; 8.58 + return -ENOENT; 8.59 + } 8.60 + 8.61 + return 0; 8.62 +} 8.63 + 8.64 + 8.65 +static int read_backend_details(struct xenbus_device *xendev) 8.66 +{ 8.67 + return read_otherend_details(xendev, "backend-id", "backend"); 8.68 +} 8.69 + 8.70 + 8.71 +static int read_frontend_details(struct xenbus_device *xendev) 8.72 +{ 8.73 + return read_otherend_details(xendev, "frontend-id", "frontend"); 8.74 +} 8.75 + 8.76 + 8.77 +static void free_otherend_details(struct xenbus_device *dev) 8.78 +{ 8.79 + kfree(dev->otherend); 8.80 + dev->otherend = NULL; 8.81 +} 8.82 + 8.83 + 8.84 +static void free_otherend_watch(struct xenbus_device *dev) 8.85 +{ 8.86 + if (dev->otherend_watch.node) { 8.87 + unregister_xenbus_watch(&dev->otherend_watch); 8.88 + kfree(dev->otherend_watch.node); 8.89 + dev->otherend_watch.node = NULL; 8.90 + } 8.91 +} 8.92 + 8.93 + 8.94 /* Bus type for frontend drivers. */ 8.95 static int xenbus_probe_frontend(const char *type, const char *name); 8.96 static struct xen_bus_type xenbus_frontend = { 8.97 @@ -165,6 +229,8 @@ static int xenbus_hotplug_backend(struct 8.98 int i = 0; 8.99 int length = 0; 8.100 8.101 + DPRINTK(""); 8.102 + 8.103 if (dev == NULL) 8.104 return -ENODEV; 8.105 8.106 @@ -211,20 +277,86 @@ static struct xen_bus_type xenbus_backen 8.107 }, 8.108 }; 8.109 8.110 + 8.111 +static void otherend_changed(struct xenbus_watch *watch, 8.112 + const char **vec, unsigned int len) 8.113 +{ 8.114 + struct xenbus_device *dev = 8.115 + container_of(watch, struct xenbus_device, otherend_watch); 8.116 + struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); 8.117 + 8.118 + /* Protect us against watches firing on old details when the otherend 8.119 + details change, say immediately after a resume. */ 8.120 + if (!dev->otherend || 8.121 + strncmp(dev->otherend, vec[XS_WATCH_PATH], 8.122 + strlen(dev->otherend))) { 8.123 + DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]); 8.124 + return; 8.125 + } 8.126 + 8.127 + XenbusState state = xenbus_read_driver_state(dev->otherend); 8.128 + 8.129 + DPRINTK("state is %d, %s, %s", state, dev->otherend_watch.node, vec[XS_WATCH_PATH]); 8.130 + 8.131 + drv->otherend_changed(dev, state); 8.132 +} 8.133 + 8.134 + 8.135 +static int talk_to_otherend(struct xenbus_device *dev) 8.136 +{ 8.137 + struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); 8.138 + int err; 8.139 + 8.140 + free_otherend_watch(dev); 8.141 + free_otherend_details(dev); 8.142 + 8.143 + err = drv->read_otherend_details(dev); 8.144 + if (err) 8.145 + return err; 8.146 + 8.147 + return xenbus_watch_path2(dev, dev->otherend, "state", 8.148 + &dev->otherend_watch, otherend_changed); 8.149 +} 8.150 + 8.151 + 8.152 static int xenbus_dev_probe(struct device *_dev) 8.153 { 8.154 struct xenbus_device *dev = to_xenbus_device(_dev); 8.155 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); 8.156 const struct xenbus_device_id *id; 8.157 + int err; 8.158 8.159 - if (!drv->probe) 8.160 - return -ENODEV; 8.161 + DPRINTK(""); 8.162 + 8.163 + err = talk_to_otherend(dev); 8.164 + if (err) { 8.165 + printk(KERN_WARNING 8.166 + "xenbus_probe: talk_to_otherend on %s failed.\n", 8.167 + dev->nodename); 8.168 + return err; 8.169 + } 8.170 + 8.171 + if (!drv->probe) { 8.172 + err = -ENODEV; 8.173 + goto fail; 8.174 + } 8.175 8.176 id = match_device(drv->ids, dev); 8.177 - if (!id) 8.178 - return -ENODEV; 8.179 + if (!id) { 8.180 + err = -ENODEV; 8.181 + goto fail; 8.182 + } 8.183 8.184 - return drv->probe(dev, id); 8.185 + err = drv->probe(dev, id); 8.186 + if (err) 8.187 + goto fail; 8.188 + 8.189 + return 0; 8.190 +fail: 8.191 + xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename); 8.192 + xenbus_switch_state(dev, NULL, XenbusStateClosed); 8.193 + return -ENODEV; 8.194 + 8.195 } 8.196 8.197 static int xenbus_dev_remove(struct device *_dev) 8.198 @@ -232,9 +364,16 @@ static int xenbus_dev_remove(struct devi 8.199 struct xenbus_device *dev = to_xenbus_device(_dev); 8.200 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); 8.201 8.202 - if (!drv->remove) 8.203 - return 0; 8.204 - return drv->remove(dev); 8.205 + DPRINTK(""); 8.206 + 8.207 + free_otherend_watch(dev); 8.208 + free_otherend_details(dev); 8.209 + 8.210 + if (drv->remove) 8.211 + drv->remove(dev); 8.212 + 8.213 + xenbus_switch_state(dev, NULL, XenbusStateClosed); 8.214 + return 0; 8.215 } 8.216 8.217 static int xenbus_register_driver_common(struct xenbus_driver *drv, 8.218 @@ -254,16 +393,21 @@ static int xenbus_register_driver_common 8.219 return ret; 8.220 } 8.221 8.222 -int xenbus_register_driver(struct xenbus_driver *drv) 8.223 +int xenbus_register_frontend(struct xenbus_driver *drv) 8.224 { 8.225 + drv->read_otherend_details = read_backend_details; 8.226 + 8.227 return xenbus_register_driver_common(drv, &xenbus_frontend); 8.228 } 8.229 -EXPORT_SYMBOL(xenbus_register_driver); 8.230 +EXPORT_SYMBOL(xenbus_register_frontend); 8.231 8.232 int xenbus_register_backend(struct xenbus_driver *drv) 8.233 { 8.234 + drv->read_otherend_details = read_frontend_details; 8.235 + 8.236 return xenbus_register_driver_common(drv, &xenbus_backend); 8.237 } 8.238 +EXPORT_SYMBOL(xenbus_register_backend); 8.239 8.240 void xenbus_unregister_driver(struct xenbus_driver *drv) 8.241 { 8.242 @@ -305,6 +449,8 @@ static int cleanup_dev(struct device *de 8.243 struct xb_find_info *info = data; 8.244 int len = strlen(info->nodename); 8.245 8.246 + DPRINTK("%s", info->nodename); 8.247 + 8.248 if (!strncmp(xendev->nodename, info->nodename, len)) { 8.249 info->dev = xendev; 8.250 get_device(dev); 8.251 @@ -327,12 +473,15 @@ static void xenbus_cleanup_devices(const 8.252 } while (info.dev); 8.253 } 8.254 8.255 -static void xenbus_release_device(struct device *dev) 8.256 +static void xenbus_dev_free(struct xenbus_device *xendev) 8.257 +{ 8.258 + kfree(xendev); 8.259 +} 8.260 + 8.261 +static void xenbus_dev_release(struct device *dev) 8.262 { 8.263 if (dev) { 8.264 - struct xenbus_device *xendev = to_xenbus_device(dev); 8.265 - 8.266 - kfree(xendev); 8.267 + xenbus_dev_free(to_xenbus_device(dev)); 8.268 } 8.269 } 8.270 8.271 @@ -369,13 +518,31 @@ static ssize_t xendev_show_devtype(struc 8.272 } 8.273 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); 8.274 8.275 + 8.276 static int xenbus_probe_node(struct xen_bus_type *bus, 8.277 const char *type, 8.278 const char *nodename) 8.279 { 8.280 +#define CHECK_FAIL \ 8.281 + do { \ 8.282 + if (err) \ 8.283 + goto fail; \ 8.284 + } \ 8.285 + while (0) \ 8.286 + 8.287 + 8.288 int err; 8.289 struct xenbus_device *xendev; 8.290 - unsigned int stringlen; 8.291 + size_t stringlen; 8.292 + char *tmpstring; 8.293 + 8.294 + XenbusState state = xenbus_read_driver_state(nodename); 8.295 + 8.296 + if (state != XenbusStateInitialising) { 8.297 + /* Device is not new, so ignore it. This can happen if a 8.298 + device is going away after switching to Closed. */ 8.299 + return 0; 8.300 + } 8.301 8.302 stringlen = strlen(nodename) + 1 + strlen(type) + 1; 8.303 xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL); 8.304 @@ -384,31 +551,35 @@ static int xenbus_probe_node(struct xen_ 8.305 memset(xendev, 0, sizeof(*xendev)); 8.306 8.307 /* Copy the strings into the extra space. */ 8.308 - xendev->nodename = (char *)(xendev + 1); 8.309 - strcpy(xendev->nodename, nodename); 8.310 - xendev->devicetype = xendev->nodename + strlen(xendev->nodename) + 1; 8.311 - strcpy(xendev->devicetype, type); 8.312 + 8.313 + tmpstring = (char *)(xendev + 1); 8.314 + strcpy(tmpstring, nodename); 8.315 + xendev->nodename = tmpstring; 8.316 + 8.317 + tmpstring += strlen(tmpstring) + 1; 8.318 + strcpy(tmpstring, type); 8.319 + xendev->devicetype = tmpstring; 8.320 8.321 xendev->dev.parent = &bus->dev; 8.322 xendev->dev.bus = &bus->bus; 8.323 - xendev->dev.release = xenbus_release_device; 8.324 + xendev->dev.release = xenbus_dev_release; 8.325 8.326 err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename); 8.327 - if (err) { 8.328 - kfree(xendev); 8.329 - return err; 8.330 - } 8.331 + CHECK_FAIL; 8.332 8.333 /* Register with generic device framework. */ 8.334 err = device_register(&xendev->dev); 8.335 - if (err) { 8.336 - printk("XENBUS: Registering %s device %s: error %i\n", 8.337 - bus->bus.name, xendev->dev.bus_id, err); 8.338 - kfree(xendev); 8.339 - } else { 8.340 - device_create_file(&xendev->dev, &dev_attr_nodename); 8.341 - device_create_file(&xendev->dev, &dev_attr_devtype); 8.342 - } 8.343 + CHECK_FAIL; 8.344 + 8.345 + device_create_file(&xendev->dev, &dev_attr_nodename); 8.346 + device_create_file(&xendev->dev, &dev_attr_devtype); 8.347 + 8.348 + return 0; 8.349 + 8.350 +#undef CHECK_FAIL 8.351 + 8.352 +fail: 8.353 + xenbus_dev_free(xendev); 8.354 return err; 8.355 } 8.356 8.357 @@ -422,6 +593,8 @@ static int xenbus_probe_frontend(const c 8.358 if (!nodename) 8.359 return -ENOMEM; 8.360 8.361 + DPRINTK("%s", nodename); 8.362 + 8.363 err = xenbus_probe_node(&xenbus_frontend, type, nodename); 8.364 kfree(nodename); 8.365 return err; 8.366 @@ -439,6 +612,8 @@ static int xenbus_probe_backend_unit(con 8.367 if (!nodename) 8.368 return -ENOMEM; 8.369 8.370 + DPRINTK("%s\n", nodename); 8.371 + 8.372 err = xenbus_probe_node(&xenbus_backend, type, nodename); 8.373 kfree(nodename); 8.374 return err; 8.375 @@ -452,6 +627,8 @@ static int xenbus_probe_backend(const ch 8.376 char **dir; 8.377 unsigned int i, dir_n = 0; 8.378 8.379 + DPRINTK(""); 8.380 + 8.381 nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid); 8.382 if (!nodename) 8.383 return -ENOMEM; 8.384 @@ -574,12 +751,16 @@ static void dev_changed(const char *node 8.385 static void frontend_changed(struct xenbus_watch *watch, 8.386 const char **vec, unsigned int len) 8.387 { 8.388 + DPRINTK(""); 8.389 + 8.390 dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend); 8.391 } 8.392 8.393 static void backend_changed(struct xenbus_watch *watch, 8.394 const char **vec, unsigned int len) 8.395 { 8.396 + DPRINTK(""); 8.397 + 8.398 dev_changed(vec[XS_WATCH_PATH], &xenbus_backend); 8.399 } 8.400 8.401 @@ -600,6 +781,8 @@ static int suspend_dev(struct device *de 8.402 struct xenbus_driver *drv; 8.403 struct xenbus_device *xdev; 8.404 8.405 + DPRINTK(""); 8.406 + 8.407 if (dev->driver == NULL) 8.408 return 0; 8.409 drv = to_xenbus_driver(dev->driver); 8.410 @@ -607,33 +790,49 @@ static int suspend_dev(struct device *de 8.411 if (drv->suspend) 8.412 err = drv->suspend(xdev); 8.413 if (err) 8.414 - printk("xenbus: suspend %s failed: %i\n", dev->bus_id, err); 8.415 + printk(KERN_WARNING 8.416 + "xenbus: suspend %s failed: %i\n", dev->bus_id, err); 8.417 return 0; 8.418 } 8.419 8.420 static int resume_dev(struct device *dev, void *data) 8.421 { 8.422 - int err = 0; 8.423 + int err; 8.424 struct xenbus_driver *drv; 8.425 struct xenbus_device *xdev; 8.426 8.427 + DPRINTK(""); 8.428 + 8.429 if (dev->driver == NULL) 8.430 return 0; 8.431 drv = to_xenbus_driver(dev->driver); 8.432 xdev = container_of(dev, struct xenbus_device, dev); 8.433 + 8.434 + err = talk_to_otherend(xdev); 8.435 + if (err) { 8.436 + printk(KERN_WARNING 8.437 + "xenbus: resume (talk_to_otherend) %s failed: %i\n", 8.438 + dev->bus_id, err); 8.439 + return err; 8.440 + } 8.441 + 8.442 if (drv->resume) 8.443 err = drv->resume(xdev); 8.444 if (err) 8.445 - printk("xenbus: resume %s failed: %i\n", dev->bus_id, err); 8.446 - return 0; 8.447 + printk(KERN_WARNING 8.448 + "xenbus: resume %s failed: %i\n", dev->bus_id, err); 8.449 + return err; 8.450 } 8.451 8.452 void xenbus_suspend(void) 8.453 { 8.454 + DPRINTK(""); 8.455 + 8.456 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); 8.457 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); 8.458 xs_suspend(); 8.459 } 8.460 +EXPORT_SYMBOL(xenbus_suspend); 8.461 8.462 void xenbus_resume(void) 8.463 { 8.464 @@ -642,6 +841,7 @@ void xenbus_resume(void) 8.465 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); 8.466 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev); 8.467 } 8.468 +EXPORT_SYMBOL(xenbus_resume); 8.469 8.470 8.471 /* A flag to determine if xenstored is 'ready' (i.e. has started) */ 8.472 @@ -683,8 +883,6 @@ void xenbus_probe(void *unused) 8.473 8.474 /* Notify others that xenstore is up */ 8.475 notifier_call_chain(&xenstore_chain, 0, 0); 8.476 - 8.477 - return; 8.478 } 8.479 8.480 8.481 @@ -716,10 +914,10 @@ static int __init xenbus_probe_init(void 8.482 { 8.483 int err = 0, dom0; 8.484 8.485 - printk("xenbus_probe_init\n"); 8.486 + DPRINTK(""); 8.487 8.488 if (xen_init() < 0) { 8.489 - printk("xen_init failed\n"); 8.490 + DPRINTK("failed"); 8.491 return -ENODEV; 8.492 } 8.493 8.494 @@ -773,7 +971,8 @@ static int __init xenbus_probe_init(void 8.495 /* Initialize the interface to xenstore. */ 8.496 err = xs_init(); 8.497 if (err) { 8.498 - printk("XENBUS: Error initializing xenstore comms: %i\n", err); 8.499 + printk(KERN_WARNING 8.500 + "XENBUS: Error initializing xenstore comms: %i\n", err); 8.501 return err; 8.502 } 8.503
9.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Fri Nov 11 18:01:44 2005 +0100 9.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Fri Nov 11 21:59:05 2005 +0100 9.3 @@ -517,87 +517,6 @@ int xenbus_printf(struct xenbus_transact 9.4 } 9.5 EXPORT_SYMBOL(xenbus_printf); 9.6 9.7 -/** 9.8 - * Return the path to the error node for the given device, or NULL on failure. 9.9 - * If the value returned is non-NULL, then it is the caller's to kfree. 9.10 - */ 9.11 -static char *error_path(struct xenbus_device *dev) 9.12 -{ 9.13 - char *path_buffer = kmalloc(strlen("error/") + strlen(dev->nodename) + 9.14 - 1, GFP_KERNEL); 9.15 - if (path_buffer == NULL) { 9.16 - return NULL; 9.17 - } 9.18 - 9.19 - strcpy(path_buffer, "error/"); 9.20 - strcpy(path_buffer + strlen("error/"), dev->nodename); 9.21 - 9.22 - return path_buffer; 9.23 -} 9.24 - 9.25 -/* Report a (negative) errno into the store, with explanation. */ 9.26 -void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...) 9.27 -{ 9.28 - va_list ap; 9.29 - int ret; 9.30 - unsigned int len; 9.31 - char *printf_buffer = NULL, *path_buffer = NULL; 9.32 - 9.33 - printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); 9.34 - if (printf_buffer == NULL) 9.35 - goto fail; 9.36 - 9.37 - len = sprintf(printf_buffer, "%i ", -err); 9.38 - va_start(ap, fmt); 9.39 - ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); 9.40 - va_end(ap); 9.41 - 9.42 - BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1); 9.43 - dev->has_error = 1; 9.44 - 9.45 - path_buffer = error_path(dev); 9.46 - 9.47 - if (path_buffer == NULL) { 9.48 - printk("xenbus: failed to write error node for %s (%s)\n", 9.49 - dev->nodename, printf_buffer); 9.50 - goto fail; 9.51 - } 9.52 - 9.53 - if (xenbus_write(NULL, path_buffer, "error", printf_buffer) != 0) { 9.54 - printk("xenbus: failed to write error node for %s (%s)\n", 9.55 - dev->nodename, printf_buffer); 9.56 - goto fail; 9.57 - } 9.58 - 9.59 -fail: 9.60 - kfree(printf_buffer); 9.61 - kfree(path_buffer); 9.62 -} 9.63 -EXPORT_SYMBOL(xenbus_dev_error); 9.64 - 9.65 -/* Clear any error. */ 9.66 -void xenbus_dev_ok(struct xenbus_device *dev) 9.67 -{ 9.68 - if (dev->has_error) { 9.69 - char *path_buffer = error_path(dev); 9.70 - 9.71 - if (path_buffer == NULL) { 9.72 - printk("xenbus: failed to clear error node for %s\n", 9.73 - dev->nodename); 9.74 - return; 9.75 - } 9.76 - 9.77 - if (xenbus_rm(NULL, path_buffer, "error") != 0) 9.78 - printk("xenbus: failed to clear error node for %s\n", 9.79 - dev->nodename); 9.80 - else 9.81 - dev->has_error = 0; 9.82 - 9.83 - kfree(path_buffer); 9.84 - } 9.85 -} 9.86 -EXPORT_SYMBOL(xenbus_dev_ok); 9.87 - 9.88 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ 9.89 int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...) 9.90 {
10.1 --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Fri Nov 11 18:01:44 2005 +0100 10.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Fri Nov 11 21:59:05 2005 +0100 10.3 @@ -35,10 +35,48 @@ 10.4 #include <asm/semaphore.h> 10.5 #include <asm-xen/xen-public/io/xs_wire.h> 10.6 10.7 +/* Register callback to watch this node. */ 10.8 +struct xenbus_watch 10.9 +{ 10.10 + struct list_head list; 10.11 + 10.12 + /* Path being watched. */ 10.13 + const char *node; 10.14 + 10.15 + /* Callback (executed in a process context with no locks held). */ 10.16 + void (*callback)(struct xenbus_watch *, 10.17 + const char **vec, unsigned int len); 10.18 +}; 10.19 + 10.20 + 10.21 +/* The state of either end of the Xenbus, i.e. the current communication 10.22 + status of initialisation across the bus. States here imply nothing about 10.23 + the state of the connection between the driver and the kernel's device 10.24 + layers. */ 10.25 +typedef enum 10.26 +{ 10.27 + XenbusStateUnknown = 0, 10.28 + XenbusStateInitialising = 1, 10.29 + XenbusStateInitWait = 2, /* Finished early initialisation, but waiting 10.30 + for information from the peer or hotplug 10.31 + scripts. */ 10.32 + XenbusStateInitialised = 3, /* Initialised and waiting for a connection 10.33 + from the peer. */ 10.34 + XenbusStateConnected = 4, 10.35 + XenbusStateClosing = 5, /* The device is being closed due to an error 10.36 + or an unplug event. */ 10.37 + XenbusStateClosed = 6 10.38 + 10.39 +} XenbusState; 10.40 + 10.41 + 10.42 /* A xenbus device. */ 10.43 struct xenbus_device { 10.44 - char *devicetype; 10.45 - char *nodename; 10.46 + const char *devicetype; 10.47 + const char *nodename; 10.48 + const char *otherend; 10.49 + int otherend_id; 10.50 + struct xenbus_watch otherend_watch; 10.51 struct device dev; 10.52 int has_error; 10.53 void *data; 10.54 @@ -62,11 +100,14 @@ struct xenbus_driver { 10.55 const struct xenbus_device_id *ids; 10.56 int (*probe)(struct xenbus_device *dev, 10.57 const struct xenbus_device_id *id); 10.58 + void (*otherend_changed)(struct xenbus_device *dev, 10.59 + XenbusState backend_state); 10.60 int (*remove)(struct xenbus_device *dev); 10.61 int (*suspend)(struct xenbus_device *dev); 10.62 int (*resume)(struct xenbus_device *dev); 10.63 int (*hotplug)(struct xenbus_device *, char **, int, char *, int); 10.64 struct device_driver driver; 10.65 + int (*read_otherend_details)(struct xenbus_device *dev); 10.66 }; 10.67 10.68 static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv) 10.69 @@ -74,7 +115,7 @@ static inline struct xenbus_driver *to_x 10.70 return container_of(drv, struct xenbus_driver, driver); 10.71 } 10.72 10.73 -int xenbus_register_driver(struct xenbus_driver *drv); 10.74 +int xenbus_register_frontend(struct xenbus_driver *drv); 10.75 int xenbus_register_backend(struct xenbus_driver *drv); 10.76 void xenbus_unregister_driver(struct xenbus_driver *drv); 10.77 10.78 @@ -108,25 +149,6 @@ int xenbus_printf(struct xenbus_transact 10.79 * sprintf-style type string, and pointer. Returns 0 or errno.*/ 10.80 int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...); 10.81 10.82 -/* Report a (negative) errno into the store, with explanation. */ 10.83 -void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,...); 10.84 - 10.85 -/* Clear any error. */ 10.86 -void xenbus_dev_ok(struct xenbus_device *dev); 10.87 - 10.88 -/* Register callback to watch this node. */ 10.89 -struct xenbus_watch 10.90 -{ 10.91 - struct list_head list; 10.92 - 10.93 - /* Path being watched. */ 10.94 - char *node; 10.95 - 10.96 - /* Callback (executed in a process context with no locks held). */ 10.97 - void (*callback)(struct xenbus_watch *, 10.98 - const char **vec, unsigned int len); 10.99 -}; 10.100 - 10.101 /* notifer routines for when the xenstore comes up */ 10.102 int register_xenstore_notifier(struct notifier_block *nb); 10.103 void unregister_xenstore_notifier(struct notifier_block *nb); 10.104 @@ -153,6 +175,89 @@ void xenbus_resume(void); 10.105 10.106 #define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE) 10.107 10.108 + 10.109 +/** 10.110 + * Register a watch on the given path, using the given xenbus_watch structure 10.111 + * for storage, and the given callback function as the callback. Return 0 on 10.112 + * success, or -errno on error. On success, the given path will be saved as 10.113 + * watch->node, and remains the caller's to free. On error, watch->node will 10.114 + * be NULL, the device will switch to XenbusStateClosing, and the error will 10.115 + * be saved in the store. 10.116 + */ 10.117 +int xenbus_watch_path(struct xenbus_device *dev, const char *path, 10.118 + struct xenbus_watch *watch, 10.119 + void (*callback)(struct xenbus_watch *, 10.120 + const char **, unsigned int)); 10.121 + 10.122 + 10.123 +/** 10.124 + * Register a watch on the given path/path2, using the given xenbus_watch 10.125 + * structure for storage, and the given callback function as the callback. 10.126 + * Return 0 on success, or -errno on error. On success, the watched path 10.127 + * (path/path2) will be saved as watch->node, and becomes the caller's to 10.128 + * kfree(). On error, watch->node will be NULL, so the caller has nothing to 10.129 + * free, the device will switch to XenbusStateClosing, and the error will be 10.130 + * saved in the store. 10.131 + */ 10.132 +int xenbus_watch_path2(struct xenbus_device *dev, const char *path, 10.133 + const char *path2, struct xenbus_watch *watch, 10.134 + void (*callback)(struct xenbus_watch *, 10.135 + const char **, unsigned int)); 10.136 + 10.137 + 10.138 +/** 10.139 + * Advertise in the store a change of the given driver to the given new_state. 10.140 + * Perform the change inside the given transaction xbt. xbt may be NULL, in 10.141 + * which case this is performed inside its own transaction. Return 0 on 10.142 + * success, or -errno on error. On error, the device will switch to 10.143 + * XenbusStateClosing, and the error will be saved in the store. 10.144 + */ 10.145 +int xenbus_switch_state(struct xenbus_device *dev, 10.146 + struct xenbus_transaction *xbt, 10.147 + XenbusState new_state); 10.148 + 10.149 + 10.150 +/** 10.151 + * Grant access to the given ring_mfn to the peer of the given device. Return 10.152 + * 0 on success, or -errno on error. On error, the device will switch to 10.153 + * XenbusStateClosing, and the error will be saved in the store. 10.154 + */ 10.155 +int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn); 10.156 + 10.157 + 10.158 +/** 10.159 + * Allocate an event channel for the given xenbus_device, assigning the newly 10.160 + * created local port to *port. Return 0 on success, or -errno on error. On 10.161 + * error, the device will switch to XenbusStateClosing, and the error will be 10.162 + * saved in the store. 10.163 + */ 10.164 +int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port); 10.165 + 10.166 + 10.167 +/** 10.168 + * Return the state of the driver rooted at the given store path, or 10.169 + * XenbusStateClosed if no state can be read. 10.170 + */ 10.171 +XenbusState xenbus_read_driver_state(const char *path); 10.172 + 10.173 + 10.174 +/*** 10.175 + * Report the given negative errno into the store, along with the given 10.176 + * formatted message. 10.177 + */ 10.178 +void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, 10.179 + ...); 10.180 + 10.181 + 10.182 +/*** 10.183 + * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by 10.184 + * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly 10.185 + * closedown of this driver and its peer. 10.186 + */ 10.187 +void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, 10.188 + ...); 10.189 + 10.190 + 10.191 #endif /* _ASM_XEN_XENBUS_H */ 10.192 10.193 /*
11.1 --- a/tools/python/xen/util/diagnose.py Fri Nov 11 18:01:44 2005 +0100 11.2 +++ b/tools/python/xen/util/diagnose.py Fri Nov 11 21:59:05 2005 +0100 11.3 @@ -22,6 +22,7 @@ from xen.xend import sxp 11.4 from xen.xend.XendClient import server 11.5 from xen.xend.XendError import XendError 11.6 from xen.xend.xenstore.xstransact import xstransact 11.7 +from xen.xend.server import DevController 11.8 11.9 import xen.xend.XendProtocol 11.10 11.11 @@ -107,34 +108,57 @@ def diagnose_devices(): 11.12 print ("Cannot find backend path for device %s, %s." % 11.13 (deviceClass, device)) 11.14 else: 11.15 - backend_error = xstransact.Read( 11.16 - backendPath.replace('backend/', 'error/backend/'), 11.17 - 'error') 11.18 + frontend_state = xstransact.Read(frontendPath, 'state') 11.19 + backend_state = xstransact.Read(backendPath, 'state') 11.20 11.21 - if backend_error: 11.22 - diagnose_device_error(backend_error) 11.23 + print "Backend is in state %s." % stateString(backend_state) 11.24 + print "Frontend is in state %s." % stateString(frontend_state) 11.25 + 11.26 + check_for_error(True) 11.27 + check_for_error(False) 11.28 + 11.29 + diagnose_hotplugging() 11.30 11.31 11.32 -def diagnose_device_error(err): 11.33 - if re.search("2 reading .*/ring-ref and event-channel", err): 11.34 - print ("Backend is stuck waiting for frontend for device %s, %s." % 11.35 - (deviceClass, device)) 11.36 - diagnose_stuck_frontend() 11.37 +def check_for_error(backend): 11.38 + if backend: 11.39 + path = backendPath.replace('backend/', 'error/backend/') 11.40 else: 11.41 - print ("Device %s, %s shows error %s." % 11.42 - (deviceClass, device, err)) 11.43 + path = frontendPath.replace('device/', 'error/device/') 11.44 + 11.45 + err = xstransact.Read(path, 'error') 11.46 + 11.47 + if err: 11.48 + print ("%s for device %s, %s shows error %s." % 11.49 + (backend and 'Backend' or 'Frontend', deviceClass, device, 11.50 + err)) 11.51 11.52 11.53 -def diagnose_stuck_frontend(): 11.54 - if deviceClass == "vbd": 11.55 +def diagnose_hotplugging(): 11.56 + if deviceClass == 'vbd': 11.57 phy = xstransact.Read(backendPath, 'physical-device') 11.58 11.59 if phy: 11.60 - print ("Device %s, %s hotplugging has completed successfully." % 11.61 - (deviceClass, device)) 11.62 + print ('Device %s, %s hotplugging has completed successfully, ' 11.63 + 'and is connected to physical device %s.' % 11.64 + (deviceClass, device, phy)) 11.65 else: 11.66 - print ("Device %s, %s hotplugging failed." % 11.67 + print ('Device %s, %s hotplugging failed.' % 11.68 (deviceClass, device)) 11.69 + elif deviceClass == 'vif': 11.70 + handle = xstransact.Read(backendPath, 'handle') 11.71 + 11.72 + if handle: 11.73 + print ('Device %s, %s hotplugging has completed successfully, ' 11.74 + 'and is using handle %s.' % 11.75 + (deviceClass, device, handle)) 11.76 + else: 11.77 + print ('Device %s, %s hotplugging failed.' % 11.78 + (deviceClass, device)) 11.79 + 11.80 + 11.81 +def stateString(state): 11.82 + return state and DevController.xenbusState[int(state)] or '<None>' 11.83 11.84 11.85 def main(argv = None):
12.1 --- a/tools/python/xen/xend/server/DevController.py Fri Nov 11 18:01:44 2005 +0100 12.2 +++ b/tools/python/xen/xend/server/DevController.py Fri Nov 11 21:59:05 2005 +0100 12.3 @@ -25,10 +25,23 @@ from xen.xend.XendLogging import log 12.4 from xen.xend.xenstore.xstransact import xstransact 12.5 from xen.xend.xenstore.xswatch import xswatch 12.6 12.7 -DEVICE_CREATE_TIMEOUT = 120 12.8 +DEVICE_CREATE_TIMEOUT = 5 12.9 HOTPLUG_STATUS_NODE = "hotplug-status" 12.10 HOTPLUG_STATUS_ERROR = "error" 12.11 12.12 +xenbusState = { 12.13 + 'Unknown' : 0, 12.14 + 'Initialising' : 1, 12.15 + 'InitWait' : 2, 12.16 + 'Initialised' : 3, 12.17 + 'Connected' : 4, 12.18 + 'Closing' : 5, 12.19 + 'Closed' : 6, 12.20 + } 12.21 + 12.22 +xenbusState.update(dict(zip(xenbusState.values(), xenbusState.keys()))) 12.23 + 12.24 + 12.25 class DevController: 12.26 """Abstract base class for a device controller. Device controllers create 12.27 appropriate entries in the store to trigger the creation, reconfiguration, 12.28 @@ -116,10 +129,8 @@ class DevController: 12.29 frontpath = self.frontendPath(devid) 12.30 backpath = xstransact.Read(frontpath, "backend") 12.31 12.32 - xstransact.Remove(frontpath) 12.33 - 12.34 if backpath: 12.35 - xstransact.Remove(backpath) 12.36 + xstransact.Write(backpath, 'state', str(xenbusState['Closing'])) 12.37 else: 12.38 raise VmError("Device %s not connected" % devid) 12.39 12.40 @@ -257,18 +268,18 @@ class DevController: 12.41 frontpath = self.frontendPath(devid) 12.42 backpath = self.backendPath(backdom, devid) 12.43 12.44 - xstransact.Remove(backpath, HOTPLUG_STATUS_NODE) 12.45 - 12.46 frontDetails.update({ 12.47 'backend' : backpath, 12.48 - 'backend-id' : "%i" % backdom.getDomid() 12.49 + 'backend-id' : "%i" % backdom.getDomid(), 12.50 + 'state' : str(xenbusState['Initialising']) 12.51 }) 12.52 12.53 12.54 backDetails.update({ 12.55 'domain' : self.vm.getName(), 12.56 'frontend' : frontpath, 12.57 - 'frontend-id' : "%i" % self.vm.getDomid() 12.58 + 'frontend-id' : "%i" % self.vm.getDomid(), 12.59 + 'state' : str(xenbusState['Initialising']) 12.60 }) 12.61 12.62 log.debug('DevController: writing %s to %s.', str(frontDetails), 12.63 @@ -276,8 +287,20 @@ class DevController: 12.64 log.debug('DevController: writing %s to %s.', str(backDetails), 12.65 backpath) 12.66 12.67 - xstransact.Write(frontpath, frontDetails) 12.68 - xstransact.Write(backpath, backDetails) 12.69 + while True: 12.70 + t = xstransact() 12.71 + try: 12.72 + t.remove2(backpath, HOTPLUG_STATUS_NODE) 12.73 + 12.74 + t.write2(frontpath, frontDetails) 12.75 + t.write2(backpath, backDetails) 12.76 + 12.77 + if t.commit(): 12.78 + return 12.79 + except: 12.80 + t.abort() 12.81 + raise 12.82 + 12.83 12.84 def waitForBackend(self,devid): 12.85 ev = Event()
13.1 --- a/tools/python/xen/xend/xenstore/xstransact.py Fri Nov 11 18:01:44 2005 +0100 13.2 +++ b/tools/python/xen/xend/xenstore/xstransact.py Fri Nov 11 21:59:05 2005 +0100 13.3 @@ -10,7 +10,7 @@ from xen.xend.xenstore.xsutil import xsh 13.4 13.5 class xstransact: 13.6 13.7 - def __init__(self, path): 13.8 + def __init__(self, path = ""): 13.9 assert path is not None 13.10 13.11 self.in_transaction = False # Set this temporarily -- if this 13.12 @@ -41,7 +41,7 @@ class xstransact: 13.13 return rc 13.14 13.15 def _read(self, key): 13.16 - path = "%s/%s" % (self.path, key) 13.17 + path = self.prependPath(key) 13.18 try: 13.19 return xshandle().read(self.transaction, path) 13.20 except RuntimeError, ex: 13.21 @@ -66,7 +66,7 @@ class xstransact: 13.22 return ret 13.23 13.24 def _write(self, key, data): 13.25 - path = "%s/%s" % (self.path, key) 13.26 + path = self.prependPath(key) 13.27 try: 13.28 xshandle().write(self.transaction, path, data) 13.29 except RuntimeError, ex: 13.30 @@ -99,7 +99,7 @@ class xstransact: 13.31 raise TypeError 13.32 13.33 def _remove(self, key): 13.34 - path = "%s/%s" % (self.path, key) 13.35 + path = self.prependPath(key) 13.36 return xshandle().rm(self.transaction, path) 13.37 13.38 def remove(self, *args): 13.39 @@ -114,7 +114,7 @@ class xstransact: 13.40 self._remove(key) 13.41 13.42 def _list(self, key): 13.43 - path = "%s/%s" % (self.path, key) 13.44 + path = self.prependPath(key) 13.45 l = xshandle().ls(self.transaction, path) 13.46 if l: 13.47 return map(lambda x: key + "/" + x, l) 13.48 @@ -215,6 +215,30 @@ class xstransact: 13.49 self._write(key, fmt % val) 13.50 13.51 13.52 + def remove2(self, middlePath, *args): 13.53 + self.callRebased(middlePath, self.remove, *args) 13.54 + 13.55 + 13.56 + def write2(self, middlePath, *args): 13.57 + self.callRebased(middlePath, self.write, *args) 13.58 + 13.59 + 13.60 + def callRebased(self, middlePath, func, *args): 13.61 + oldpath = self.path 13.62 + self.path = self.prependPath(middlePath) 13.63 + try: 13.64 + func(*args) 13.65 + finally: 13.66 + self.path = oldpath 13.67 + 13.68 + 13.69 + def prependPath(self, key): 13.70 + if self.path: 13.71 + return self.path + '/' + key 13.72 + else: 13.73 + return key 13.74 + 13.75 + 13.76 def Read(cls, path, *args): 13.77 """If only one argument is given (path), return the value stored at 13.78 that path. If two arguments are given, treat the second argument as a