ia64/xen-unstable

changeset 9546:24aa3bd826ff

Remove the transaction parameter from xenbus_switch_state and move the state
switch out of a transaction, in the few cases where it is inside one.

In order to behave properly, it is necessary for a driver to know its own
xenbus state (see changeset 9469:b3cb19d2b07f, for example). This
value is stored as xenbus_device.state and updated by xenbus_switch_state.

If xenbus_switch_state occurs within a transaction, then there is a possibility
that the transaction would be aborted, leaving the state field dangerously out
of sync with the value currently in the store.

This fixes recent problems seen whereby bringing multiple devices up at the
same time results in some devices not coming up (often all of the even-numbered
ones, because of the pattern of transaction conflict).

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Fri Mar 31 00:24:54 2006 +0100 (2006-03-31)
parents 94971fe9c62a
children 8a8361994904
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/netback/xenbus.c linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c 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/include/xen/xenbus.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Fri Mar 31 00:15:12 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Fri Mar 31 00:24:54 2006 +0100
     1.3 @@ -142,7 +142,7 @@ static int blkback_probe(struct xenbus_d
     1.4  	if (err)
     1.5  		goto fail;
     1.6  
     1.7 -	err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
     1.8 +	err = xenbus_switch_state(dev, XenbusStateInitWait);
     1.9  	if (err)
    1.10  		goto fail;
    1.11  
    1.12 @@ -270,7 +270,7 @@ static void frontend_changed(struct xenb
    1.13  		break;
    1.14  
    1.15  	case XenbusStateClosing:
    1.16 -		xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
    1.17 +		xenbus_switch_state(dev, XenbusStateClosing);
    1.18  		break;
    1.19  
    1.20  	case XenbusStateClosed:
    1.21 @@ -343,15 +343,17 @@ again:
    1.22  		goto abort;
    1.23  	}
    1.24  
    1.25 -	err = xenbus_switch_state(dev, xbt, XenbusStateConnected);
    1.26 -	if (err)
    1.27 -		goto abort;
    1.28 -
    1.29  	err = xenbus_transaction_end(xbt, 0);
    1.30  	if (err == -EAGAIN)
    1.31  		goto again;
    1.32  	if (err)
    1.33  		xenbus_dev_fatal(dev, err, "ending transaction");
    1.34 +
    1.35 +	err = xenbus_switch_state(dev, XenbusStateConnected);
    1.36 +	if (err)
    1.37 +		xenbus_dev_fatal(dev, err, "switching to Connected state",
    1.38 +				 dev->nodename);
    1.39 +
    1.40  	return;
    1.41   abort:
    1.42  	xenbus_transaction_end(xbt, 1);
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri Mar 31 00:15:12 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri Mar 31 00:24:54 2006 +0100
     2.3 @@ -176,10 +176,6 @@ again:
     2.4  		goto abort_transaction;
     2.5  	}
     2.6  
     2.7 -	err = xenbus_switch_state(dev, xbt, XenbusStateInitialised);
     2.8 -	if (err)
     2.9 -		goto abort_transaction;
    2.10 -
    2.11  	err = xenbus_transaction_end(xbt, 0);
    2.12  	if (err) {
    2.13  		if (err == -EAGAIN)
    2.14 @@ -188,6 +184,8 @@ again:
    2.15  		goto destroy_blkring;
    2.16  	}
    2.17  
    2.18 +	xenbus_switch_state(dev, XenbusStateInitialised);
    2.19 +
    2.20  	return 0;
    2.21  
    2.22   abort_transaction:
    2.23 @@ -324,7 +322,7 @@ static void connect(struct blkfront_info
    2.24  		return;
    2.25  	}
    2.26  
    2.27 -	(void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected);
    2.28 +	(void)xenbus_switch_state(info->xbdev, XenbusStateConnected);
    2.29  
    2.30  	/* Kick pending requests. */
    2.31  	spin_lock_irq(&blkif_io_lock);
    2.32 @@ -349,7 +347,7 @@ static void blkfront_closing(struct xenb
    2.33  
    2.34  	xlvbd_del(info);
    2.35  
    2.36 -	xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
    2.37 +	xenbus_switch_state(dev, XenbusStateClosed);
    2.38  }
    2.39  
    2.40  
    2.41 @@ -755,7 +753,7 @@ static void blkif_recover(struct blkfron
    2.42  
    2.43  	kfree(copy);
    2.44  
    2.45 -	(void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected);
    2.46 +	(void)xenbus_switch_state(info->xbdev, XenbusStateConnected);
    2.47  
    2.48  	/* Now safe for us to use the shared ring */
    2.49  	spin_lock_irq(&blkif_io_lock);
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Fri Mar 31 00:15:12 2006 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Fri Mar 31 00:24:54 2006 +0100
     3.3 @@ -92,7 +92,7 @@ static int netback_probe(struct xenbus_d
     3.4  	if (err)
     3.5  		goto fail;
     3.6  
     3.7 -	err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
     3.8 +	err = xenbus_switch_state(dev, XenbusStateInitWait);
     3.9  	if (err) {
    3.10  		goto fail;
    3.11  	}
    3.12 @@ -209,7 +209,7 @@ static void frontend_changed(struct xenb
    3.13  		break;
    3.14  
    3.15  	case XenbusStateClosing:
    3.16 -		xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
    3.17 +		xenbus_switch_state(dev, XenbusStateClosing);
    3.18  		break;
    3.19  
    3.20  	case XenbusStateClosed:
    3.21 @@ -254,7 +254,7 @@ static void connect(struct backend_info 
    3.22  		return;
    3.23  	}
    3.24  
    3.25 -	xenbus_switch_state(dev, XBT_NULL, XenbusStateConnected);
    3.26 +	xenbus_switch_state(dev, XenbusStateConnected);
    3.27  }
    3.28  
    3.29  
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Fri Mar 31 00:15:12 2006 +0100
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Fri Mar 31 00:24:54 2006 +0100
     4.3 @@ -1216,7 +1216,7 @@ static void netfront_closing(struct xenb
     4.4  
     4.5  	close_netdev(info);
     4.6  
     4.7 -	xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
     4.8 +	xenbus_switch_state(dev, XenbusStateClosed);
     4.9  }
    4.10  
    4.11  
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c	Fri Mar 31 00:15:12 2006 +0100
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c	Fri Mar 31 00:24:54 2006 +0100
     5.3 @@ -137,7 +137,7 @@ static int pciback_attach(struct pciback
     5.4  
     5.5  	dev_dbg(&pdev->xdev->dev, "Connecting...\n");
     5.6  
     5.7 -	err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateConnected);
     5.8 +	err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
     5.9  	if (err)
    5.10  		xenbus_dev_fatal(pdev->xdev, err,
    5.11  				 "Error switching to connected state!");
    5.12 @@ -165,7 +165,7 @@ static void pciback_frontend_changed(str
    5.13  		break;
    5.14  
    5.15  	case XenbusStateClosing:
    5.16 -		xenbus_switch_state(xdev, XBT_NULL, XenbusStateClosing);
    5.17 +		xenbus_switch_state(xdev, XenbusStateClosing);
    5.18  		break;
    5.19  
    5.20  	case XenbusStateClosed:
    5.21 @@ -341,7 +341,7 @@ static int pciback_setup_backend(struct 
    5.22  		goto out;
    5.23  	}
    5.24  
    5.25 -	err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateInitialised);
    5.26 +	err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
    5.27  	if (err)
    5.28  		xenbus_dev_fatal(pdev->xdev, err,
    5.29  				 "Error switching to initialised state!");
    5.30 @@ -386,7 +386,7 @@ static int pciback_xenbus_probe(struct x
    5.31  	}
    5.32  
    5.33  	/* wait for xend to configure us */
    5.34 -	err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
    5.35 +	err = xenbus_switch_state(dev, XenbusStateInitWait);
    5.36  	if (err)
    5.37  		goto out;
    5.38  
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c	Fri Mar 31 00:15:12 2006 +0100
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c	Fri Mar 31 00:24:54 2006 +0100
     6.3 @@ -96,10 +96,6 @@ static int pcifront_publish_info(struct 
     6.4  	if (!err)
     6.5  		err = xenbus_printf(trans, pdev->xdev->nodename,
     6.6  				    "magic", XEN_PCI_MAGIC);
     6.7 -	if (!err)
     6.8 -		err =
     6.9 -		    xenbus_switch_state(pdev->xdev, trans,
    6.10 -					XenbusStateInitialised);
    6.11  
    6.12  	if (err) {
    6.13  		xenbus_transaction_end(trans, 1);
    6.14 @@ -118,6 +114,8 @@ static int pcifront_publish_info(struct 
    6.15  		}
    6.16  	}
    6.17  
    6.18 +	xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
    6.19 +
    6.20  	dev_dbg(&pdev->xdev->dev, "publishing successful!\n");
    6.21  
    6.22        out:
    6.23 @@ -186,7 +184,7 @@ static int pcifront_try_connect(struct p
    6.24  		}
    6.25  	}
    6.26  
    6.27 -	err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateConnected);
    6.28 +	err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
    6.29  	if (err)
    6.30  		goto out;
    6.31  
    6.32 @@ -205,8 +203,7 @@ static int pcifront_try_disconnect(struc
    6.33  	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
    6.34  
    6.35  	if (prev_state < XenbusStateClosing)
    6.36 -		err = xenbus_switch_state(pdev->xdev, XBT_NULL,
    6.37 -					XenbusStateClosing);
    6.38 +		err = xenbus_switch_state(pdev->xdev, XenbusStateClosing);
    6.39  
    6.40  	if (!err && prev_state == XenbusStateConnected)
    6.41  		pcifront_disconnect(pdev);
     7.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c	Fri Mar 31 00:15:12 2006 +0100
     7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c	Fri Mar 31 00:24:54 2006 +0100
     7.3 @@ -87,7 +87,7 @@ static int tpmback_probe(struct xenbus_d
     7.4  		goto fail;
     7.5  	}
     7.6  
     7.7 -	err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
     7.8 +	err = xenbus_switch_state(dev, XenbusStateInitWait);
     7.9  	if (err) {
    7.10  		goto fail;
    7.11  	}
    7.12 @@ -175,7 +175,7 @@ static void frontend_changed(struct xenb
    7.13  		break;
    7.14  
    7.15  	case XenbusStateClosing:
    7.16 -		xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
    7.17 +		xenbus_switch_state(dev, XenbusStateClosing);
    7.18  		break;
    7.19  
    7.20  	case XenbusStateClosed:
    7.21 @@ -247,18 +247,15 @@ again:
    7.22  		goto abort;
    7.23  	}
    7.24  
    7.25 -	err = xenbus_switch_state(dev, xbt, XenbusStateConnected);
    7.26 -	if (err)
    7.27 -		goto abort;
    7.28 -
    7.29 -	be->tpmif->status = CONNECTED;
    7.30 -
    7.31  	err = xenbus_transaction_end(xbt, 0);
    7.32  	if (err == -EAGAIN)
    7.33  		goto again;
    7.34 -	if (err) {
    7.35 +	if (err)
    7.36  		xenbus_dev_fatal(be->dev, err, "end of transaction");
    7.37 -	}
    7.38 +
    7.39 +	err = xenbus_switch_state(dev, XenbusStateConnected);
    7.40 +	if (!err)
    7.41 +		be->tpmif->status = CONNECTED;
    7.42  	return;
    7.43  abort:
    7.44  	xenbus_transaction_end(xbt, 1);
     8.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c	Fri Mar 31 00:15:12 2006 +0100
     8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c	Fri Mar 31 00:24:54 2006 +0100
     8.3 @@ -84,9 +84,7 @@ int xenbus_watch_path2(struct xenbus_dev
     8.4  EXPORT_SYMBOL_GPL(xenbus_watch_path2);
     8.5  
     8.6  
     8.7 -int xenbus_switch_state(struct xenbus_device *dev,
     8.8 -			xenbus_transaction_t xbt,
     8.9 -			XenbusState state)
    8.10 +int xenbus_switch_state(struct xenbus_device *dev, XenbusState state)
    8.11  {
    8.12  	/* We check whether the state is currently set to the given value, and
    8.13  	   if not, then the state is set.  We don't want to unconditionally
    8.14 @@ -94,6 +92,12 @@ int xenbus_switch_state(struct xenbus_de
    8.15  	   unnecessarily.  Furthermore, if the node has gone, we don't write
    8.16  	   to it, as the device will be tearing down, and we don't want to
    8.17  	   resurrect that directory.
    8.18 +
    8.19 +	   Note that, because of this cached value of our state, this function
    8.20 +	   will not work inside a Xenstore transaction (something it was
    8.21 +	   trying to in the past) because dev->state would not get reset if
    8.22 +	   the transaction was aborted.
    8.23 +
    8.24  	 */
    8.25  
    8.26  	int current_state;
    8.27 @@ -102,12 +106,12 @@ int xenbus_switch_state(struct xenbus_de
    8.28  	if (state == dev->state)
    8.29  		return 0;
    8.30  
    8.31 -	err = xenbus_scanf(xbt, dev->nodename, "state", "%d",
    8.32 -			       &current_state);
    8.33 +	err = xenbus_scanf(XBT_NULL, dev->nodename, "state", "%d",
    8.34 +			   &current_state);
    8.35  	if (err != 1)
    8.36  		return 0;
    8.37  
    8.38 -	err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
    8.39 +	err = xenbus_printf(XBT_NULL, dev->nodename, "state", "%d", state);
    8.40  	if (err) {
    8.41  		if (state != XenbusStateClosing) /* Avoid looping */
    8.42  			xenbus_dev_fatal(dev, err, "writing new state");
    8.43 @@ -193,7 +197,7 @@ void xenbus_dev_fatal(struct xenbus_devi
    8.44  	_dev_error(dev, err, fmt, ap);
    8.45  	va_end(ap);
    8.46  
    8.47 -	xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
    8.48 +	xenbus_switch_state(dev, XenbusStateClosing);
    8.49  }
    8.50  EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
    8.51  
     9.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Fri Mar 31 00:15:12 2006 +0100
     9.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Fri Mar 31 00:24:54 2006 +0100
     9.3 @@ -364,7 +364,7 @@ static int xenbus_dev_probe(struct devic
     9.4  	return 0;
     9.5  fail:
     9.6  	xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
     9.7 -	xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
     9.8 +	xenbus_switch_state(dev, XenbusStateClosed);
     9.9  	return -ENODEV;
    9.10  }
    9.11  
    9.12 @@ -381,7 +381,7 @@ static int xenbus_dev_remove(struct devi
    9.13  	if (drv->remove)
    9.14  		drv->remove(dev);
    9.15  
    9.16 -	xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
    9.17 +	xenbus_switch_state(dev, XenbusStateClosed);
    9.18  	return 0;
    9.19  }
    9.20  
    10.1 --- a/linux-2.6-xen-sparse/include/xen/xenbus.h	Fri Mar 31 00:15:12 2006 +0100
    10.2 +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h	Fri Mar 31 00:24:54 2006 +0100
    10.3 @@ -204,14 +204,10 @@ int xenbus_watch_path2(struct xenbus_dev
    10.4  
    10.5  /**
    10.6   * Advertise in the store a change of the given driver to the given new_state.
    10.7 - * Perform the change inside the given transaction xbt.  xbt may be NULL, in
    10.8 - * which case this is performed inside its own transaction.  Return 0 on
    10.9 - * success, or -errno on error.  On error, the device will switch to
   10.10 - * XenbusStateClosing, and the error will be saved in the store.
   10.11 + * Return 0 on success, or -errno on error.  On error, the device will switch
   10.12 + * to XenbusStateClosing, and the error will be saved in the store.
   10.13   */
   10.14 -int xenbus_switch_state(struct xenbus_device *dev,
   10.15 -			xenbus_transaction_t xbt,
   10.16 -			XenbusState new_state);
   10.17 +int xenbus_switch_state(struct xenbus_device *dev, XenbusState new_state);
   10.18  
   10.19  
   10.20  /**