ia64/xen-unstable

changeset 7792: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>
author emellor@leeni.uk.xensource.com
date Fri Nov 11 21:59:05 2005 +0100 (2005-11-11)
parents e2e7f47e6f79
children 776ef2fb6fd8
files linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6-xen-sparse/drivers/xen/blkfront/block.h linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c linux-2.6-xen-sparse/include/asm-xen/xenbus.h tools/python/xen/util/diagnose.py tools/python/xen/xend/server/DevController.py tools/python/xen/xend/xenstore/xstransact.py
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", &sectors,
   2.280 +				"info", "%u", &binfo,
   2.281 +				"sector-size", "%lu", &sector_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", &sectors,
   2.423 -			    "info", "%u", &binfo,
   2.424 -			    "sector-size", "%lu", &sector_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(&notifier_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(&notifier_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 +			       &current_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