ia64/xen-unstable

changeset 11406:98a81d2ccf4c

[XENBUS] Introduce new "online" node for backend drivers.

Driver changes: Make backend drivers check it when entering Closed
state, only unregister devices when the "online" node is either "0" or
not present. The later maintains backward compatibility.

Tools changes: Update "online" node when creating and hot-unplugging
devices.

Background: When kexec'ing a new kernel, the old kernel's frontend
driver will shutdown, but the backend device should *NOT* disappear
due to that, so the new kernel instance can reconnect.

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
author kaf24@firebug.cl.cam.ac.uk
date Fri Sep 01 00:33:19 2006 +0100 (2006-09-01)
parents e036feb6a4ff
children 90d3ca978b40
files linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c linux-2.6-xen-sparse/drivers/xen/blktap/common.h linux-2.6-xen-sparse/drivers/xen/blktap/interface.c linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c linux-2.6-xen-sparse/include/xen/xenbus.h tools/python/xen/xend/server/DevController.py
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Fri Sep 01 00:20:42 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Fri Sep 01 00:33:19 2006 +0100
     1.3 @@ -301,11 +301,11 @@ static void frontend_changed(struct xenb
     1.4  	struct backend_info *be = dev->dev.driver_data;
     1.5  	int err;
     1.6  
     1.7 -	DPRINTK("");
     1.8 +	DPRINTK("%s", xenbus_strstate(frontend_state));
     1.9  
    1.10  	switch (frontend_state) {
    1.11  	case XenbusStateInitialising:
    1.12 -		if (dev->state == XenbusStateClosing) {
    1.13 +		if (dev->state == XenbusStateClosed) {
    1.14  			printk("%s: %s: prepare for reconnect\n",
    1.15  			       __FUNCTION__, dev->nodename);
    1.16  			xenbus_switch_state(dev, XenbusStateInitWait);
    1.17 @@ -331,8 +331,12 @@ static void frontend_changed(struct xenb
    1.18  		xenbus_switch_state(dev, XenbusStateClosing);
    1.19  		break;
    1.20  
    1.21 +	case XenbusStateClosed:
    1.22 +		xenbus_switch_state(dev, XenbusStateClosed);
    1.23 +		if (xenbus_dev_is_online(dev))
    1.24 +			break;
    1.25 +		/* fall through if not online */
    1.26  	case XenbusStateUnknown:
    1.27 -	case XenbusStateClosed:
    1.28  		device_unregister(&dev->dev);
    1.29  		break;
    1.30  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h	Fri Sep 01 00:20:42 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h	Fri Sep 01 00:33:19 2006 +0100
     2.3 @@ -91,6 +91,7 @@ blkif_t *tap_alloc_blkif(domid_t domid);
     2.4  void tap_blkif_free(blkif_t *blkif);
     2.5  int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, 
     2.6  		  unsigned int evtchn);
     2.7 +void tap_blkif_unmap(blkif_t *blkif);
     2.8  
     2.9  #define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
    2.10  #define blkif_put(_b)					\
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c	Fri Sep 01 00:20:42 2006 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c	Fri Sep 01 00:33:19 2006 +0100
     3.3 @@ -135,20 +135,25 @@ int tap_blkif_map(blkif_t *blkif, unsign
     3.4  	return 0;
     3.5  }
     3.6  
     3.7 +void tap_blkif_unmap(blkif_t *blkif)
     3.8 +{
     3.9 +	if (blkif->irq) {
    3.10 +		unbind_from_irqhandler(blkif->irq, blkif);
    3.11 +		blkif->irq = 0;
    3.12 +	}
    3.13 +	if (blkif->blk_ring.sring) {
    3.14 +		unmap_frontend_page(blkif);
    3.15 +		free_vm_area(blkif->blk_ring_area);
    3.16 +		blkif->blk_ring.sring = NULL;
    3.17 +	}
    3.18 +}
    3.19 +
    3.20  void tap_blkif_free(blkif_t *blkif)
    3.21  {
    3.22  	atomic_dec(&blkif->refcnt);
    3.23  	wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
    3.24  
    3.25 -	/* Already disconnected? */
    3.26 -	if (blkif->irq)
    3.27 -		unbind_from_irqhandler(blkif->irq, blkif);
    3.28 -
    3.29 -	if (blkif->blk_ring.sring) {
    3.30 -		unmap_frontend_page(blkif);
    3.31 -		free_vm_area(blkif->blk_ring_area);
    3.32 -	}
    3.33 -
    3.34 +	tap_blkif_unmap(blkif);
    3.35  	kmem_cache_free(blkif_cachep, blkif);
    3.36  }
    3.37  
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c	Fri Sep 01 00:20:42 2006 +0100
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c	Fri Sep 01 00:33:19 2006 +0100
     4.3 @@ -247,6 +247,11 @@ static void tap_frontend_changed(struct 
     4.4  
     4.5  	switch (frontend_state) {
     4.6  	case XenbusStateInitialising:
     4.7 +		if (dev->state == XenbusStateClosed) {
     4.8 +			printk("%s: %s: prepare for reconnect\n",
     4.9 +			       __FUNCTION__, dev->nodename);
    4.10 +			xenbus_switch_state(dev, XenbusStateInitWait);
    4.11 +		}
    4.12  		break;
    4.13  
    4.14  	case XenbusStateInitialised:
    4.15 @@ -264,11 +269,20 @@ static void tap_frontend_changed(struct 
    4.16  		break;
    4.17  
    4.18  	case XenbusStateClosing:
    4.19 +		if (be->blkif->xenblkd) {
    4.20 +			kthread_stop(be->blkif->xenblkd);
    4.21 +			be->blkif->xenblkd = NULL;
    4.22 +		}
    4.23 +		tap_blkif_unmap(be->blkif);
    4.24  		xenbus_switch_state(dev, XenbusStateClosing);
    4.25  		break;
    4.26  
    4.27 +	case XenbusStateClosed:
    4.28 +		xenbus_switch_state(dev, XenbusStateClosed);
    4.29 +		if (xenbus_dev_is_online(dev))
    4.30 +			break;
    4.31 +		/* fall through if not online */
    4.32  	case XenbusStateUnknown:
    4.33 -	case XenbusStateClosed:
    4.34  		device_unregister(&dev->dev);
    4.35  		break;
    4.36  
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Fri Sep 01 00:20:42 2006 +0100
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Fri Sep 01 00:33:19 2006 +0100
     5.3 @@ -228,13 +228,13 @@ static void frontend_changed(struct xenb
     5.4  {
     5.5  	struct backend_info *be = dev->dev.driver_data;
     5.6  
     5.7 -	DPRINTK("");
     5.8 +	DPRINTK("%s", xenbus_strstate(frontend_state));
     5.9  
    5.10  	be->frontend_state = frontend_state;
    5.11  
    5.12  	switch (frontend_state) {
    5.13  	case XenbusStateInitialising:
    5.14 -		if (dev->state == XenbusStateClosing) {
    5.15 +		if (dev->state == XenbusStateClosed) {
    5.16  			printk("%s: %s: prepare for reconnect\n",
    5.17  			       __FUNCTION__, dev->nodename);
    5.18  			if (be->netif) {
    5.19 @@ -260,8 +260,12 @@ static void frontend_changed(struct xenb
    5.20  		xenbus_switch_state(dev, XenbusStateClosing);
    5.21  		break;
    5.22  
    5.23 +	case XenbusStateClosed:
    5.24 +		xenbus_switch_state(dev, XenbusStateClosed);
    5.25 +		if (xenbus_dev_is_online(dev))
    5.26 +			break;
    5.27 +		/* fall through if not online */
    5.28  	case XenbusStateUnknown:
    5.29 -	case XenbusStateClosed:
    5.30  		if (be->netif != NULL)
    5.31  			kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
    5.32  		device_unregister(&dev->dev);
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c	Fri Sep 01 00:20:42 2006 +0100
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c	Fri Sep 01 00:33:19 2006 +0100
     6.3 @@ -132,4 +132,16 @@ int xenbus_unmap_ring(struct xenbus_devi
     6.4  }
     6.5  EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
     6.6  
     6.7 +int xenbus_dev_is_online(struct xenbus_device *dev)
     6.8 +{
     6.9 +	int rc, val;
    6.10 +
    6.11 +	rc = xenbus_scanf(XBT_NIL, dev->nodename, "online", "%d", &val);
    6.12 +	if (rc != 1)
    6.13 +		val = 0; /* no online node present */
    6.14 +
    6.15 +	return val;
    6.16 +}
    6.17 +EXPORT_SYMBOL_GPL(xenbus_dev_is_online);
    6.18 +
    6.19  MODULE_LICENSE("Dual BSD/GPL");
     7.1 --- a/linux-2.6-xen-sparse/include/xen/xenbus.h	Fri Sep 01 00:20:42 2006 +0100
     7.2 +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h	Fri Sep 01 00:33:19 2006 +0100
     7.3 @@ -298,5 +298,6 @@ void xenbus_dev_fatal(struct xenbus_devi
     7.4  int __init xenbus_dev_init(void);
     7.5  
     7.6  char *xenbus_strstate(enum xenbus_state state);
     7.7 +int xenbus_dev_is_online(struct xenbus_device *dev);
     7.8  
     7.9  #endif /* _XEN_XENBUS_H */
     8.1 --- a/tools/python/xen/xend/server/DevController.py	Fri Sep 01 00:20:42 2006 +0100
     8.2 +++ b/tools/python/xen/xend/server/DevController.py	Fri Sep 01 00:33:19 2006 +0100
     8.3 @@ -207,6 +207,9 @@ class DevController:
     8.4  
     8.5          devid = int(devid)
     8.6  
     8.7 +        # Modify online status /before/ updating state (latter is watched by
     8.8 +        # drivers, so this ordering avoids a race).
     8.9 +        self.writeBackend(devid, 'online', "0")
    8.10          self.writeBackend(devid, 'state', str(xenbusState['Closing']))
    8.11  
    8.12  
    8.13 @@ -406,7 +409,8 @@ class DevController:
    8.14              'domain' : self.vm.getName(),
    8.15              'frontend' : frontpath,
    8.16              'frontend-id' : "%i" % self.vm.getDomid(),
    8.17 -            'state' : str(xenbusState['Initialising'])
    8.18 +            'state' : str(xenbusState['Initialising']),
    8.19 +            'online' : "1"
    8.20              })
    8.21  
    8.22          return (backpath, frontpath)