Updated from Linux LTS 3.10.19 to 3.10.20
This commit is contained in:
@@ -24,6 +24,12 @@
|
||||
struct backend_info {
|
||||
struct xenbus_device *dev;
|
||||
struct xenvif *vif;
|
||||
|
||||
/* This is the state that will be reflected in xenstore when any
|
||||
* active hotplug script completes.
|
||||
*/
|
||||
enum xenbus_state state;
|
||||
|
||||
enum xenbus_state frontend_state;
|
||||
struct xenbus_watch hotplug_status_watch;
|
||||
u8 have_hotplug_status_watch:1;
|
||||
@@ -33,11 +39,15 @@ static int connect_rings(struct backend_info *);
|
||||
static void connect(struct backend_info *);
|
||||
static void backend_create_xenvif(struct backend_info *be);
|
||||
static void unregister_hotplug_status_watch(struct backend_info *be);
|
||||
static void set_backend_state(struct backend_info *be,
|
||||
enum xenbus_state state);
|
||||
|
||||
static int netback_remove(struct xenbus_device *dev)
|
||||
{
|
||||
struct backend_info *be = dev_get_drvdata(&dev->dev);
|
||||
|
||||
set_backend_state(be, XenbusStateClosed);
|
||||
|
||||
unregister_hotplug_status_watch(be);
|
||||
if (be->vif) {
|
||||
kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
|
||||
@@ -126,6 +136,8 @@ static int netback_probe(struct xenbus_device *dev,
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
be->state = XenbusStateInitWait;
|
||||
|
||||
/* This kicks hotplug scripts, so do it immediately. */
|
||||
backend_create_xenvif(be);
|
||||
|
||||
@@ -198,24 +210,113 @@ static void backend_create_xenvif(struct backend_info *be)
|
||||
kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
|
||||
}
|
||||
|
||||
|
||||
static void disconnect_backend(struct xenbus_device *dev)
|
||||
static void backend_disconnect(struct backend_info *be)
|
||||
{
|
||||
struct backend_info *be = dev_get_drvdata(&dev->dev);
|
||||
|
||||
if (be->vif)
|
||||
xenvif_disconnect(be->vif);
|
||||
}
|
||||
|
||||
static void destroy_backend(struct xenbus_device *dev)
|
||||
static void backend_connect(struct backend_info *be)
|
||||
{
|
||||
struct backend_info *be = dev_get_drvdata(&dev->dev);
|
||||
if (be->vif)
|
||||
connect(be);
|
||||
}
|
||||
|
||||
if (be->vif) {
|
||||
kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
|
||||
xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
|
||||
xenvif_free(be->vif);
|
||||
be->vif = NULL;
|
||||
static inline void backend_switch_state(struct backend_info *be,
|
||||
enum xenbus_state state)
|
||||
{
|
||||
struct xenbus_device *dev = be->dev;
|
||||
|
||||
pr_debug("%s -> %s\n", dev->nodename, xenbus_strstate(state));
|
||||
be->state = state;
|
||||
|
||||
/* If we are waiting for a hotplug script then defer the
|
||||
* actual xenbus state change.
|
||||
*/
|
||||
if (!be->have_hotplug_status_watch)
|
||||
xenbus_switch_state(dev, state);
|
||||
}
|
||||
|
||||
/* Handle backend state transitions:
|
||||
*
|
||||
* The backend state starts in InitWait and the following transitions are
|
||||
* allowed.
|
||||
*
|
||||
* InitWait -> Connected
|
||||
*
|
||||
* ^ \ |
|
||||
* | \ |
|
||||
* | \ |
|
||||
* | \ |
|
||||
* | \ |
|
||||
* | \ |
|
||||
* | V V
|
||||
*
|
||||
* Closed <-> Closing
|
||||
*
|
||||
* The state argument specifies the eventual state of the backend and the
|
||||
* function transitions to that state via the shortest path.
|
||||
*/
|
||||
static void set_backend_state(struct backend_info *be,
|
||||
enum xenbus_state state)
|
||||
{
|
||||
while (be->state != state) {
|
||||
switch (be->state) {
|
||||
case XenbusStateClosed:
|
||||
switch (state) {
|
||||
case XenbusStateInitWait:
|
||||
case XenbusStateConnected:
|
||||
pr_info("%s: prepare for reconnect\n",
|
||||
be->dev->nodename);
|
||||
backend_switch_state(be, XenbusStateInitWait);
|
||||
break;
|
||||
case XenbusStateClosing:
|
||||
backend_switch_state(be, XenbusStateClosing);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
case XenbusStateInitWait:
|
||||
switch (state) {
|
||||
case XenbusStateConnected:
|
||||
backend_connect(be);
|
||||
backend_switch_state(be, XenbusStateConnected);
|
||||
break;
|
||||
case XenbusStateClosing:
|
||||
case XenbusStateClosed:
|
||||
backend_switch_state(be, XenbusStateClosing);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
case XenbusStateConnected:
|
||||
switch (state) {
|
||||
case XenbusStateInitWait:
|
||||
case XenbusStateClosing:
|
||||
case XenbusStateClosed:
|
||||
backend_disconnect(be);
|
||||
backend_switch_state(be, XenbusStateClosing);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
case XenbusStateClosing:
|
||||
switch (state) {
|
||||
case XenbusStateInitWait:
|
||||
case XenbusStateConnected:
|
||||
case XenbusStateClosed:
|
||||
backend_switch_state(be, XenbusStateClosed);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,41 +328,33 @@ static void frontend_changed(struct xenbus_device *dev,
|
||||
{
|
||||
struct backend_info *be = dev_get_drvdata(&dev->dev);
|
||||
|
||||
pr_debug("frontend state %s", xenbus_strstate(frontend_state));
|
||||
pr_debug("%s -> %s\n", dev->otherend, xenbus_strstate(frontend_state));
|
||||
|
||||
be->frontend_state = frontend_state;
|
||||
|
||||
switch (frontend_state) {
|
||||
case XenbusStateInitialising:
|
||||
if (dev->state == XenbusStateClosed) {
|
||||
printk(KERN_INFO "%s: %s: prepare for reconnect\n",
|
||||
__func__, dev->nodename);
|
||||
xenbus_switch_state(dev, XenbusStateInitWait);
|
||||
}
|
||||
set_backend_state(be, XenbusStateInitWait);
|
||||
break;
|
||||
|
||||
case XenbusStateInitialised:
|
||||
break;
|
||||
|
||||
case XenbusStateConnected:
|
||||
if (dev->state == XenbusStateConnected)
|
||||
break;
|
||||
if (be->vif)
|
||||
connect(be);
|
||||
set_backend_state(be, XenbusStateConnected);
|
||||
break;
|
||||
|
||||
case XenbusStateClosing:
|
||||
disconnect_backend(dev);
|
||||
xenbus_switch_state(dev, XenbusStateClosing);
|
||||
set_backend_state(be, XenbusStateClosing);
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
set_backend_state(be, XenbusStateClosed);
|
||||
if (xenbus_dev_is_online(dev))
|
||||
break;
|
||||
destroy_backend(dev);
|
||||
/* fall through if not online */
|
||||
case XenbusStateUnknown:
|
||||
set_backend_state(be, XenbusStateClosed);
|
||||
device_unregister(&dev->dev);
|
||||
break;
|
||||
|
||||
@@ -354,7 +447,9 @@ static void hotplug_status_changed(struct xenbus_watch *watch,
|
||||
if (IS_ERR(str))
|
||||
return;
|
||||
if (len == sizeof("connected")-1 && !memcmp(str, "connected", len)) {
|
||||
xenbus_switch_state(be->dev, XenbusStateConnected);
|
||||
/* Complete any pending state change */
|
||||
xenbus_switch_state(be->dev, be->state);
|
||||
|
||||
/* Not interested in this watch anymore. */
|
||||
unregister_hotplug_status_watch(be);
|
||||
}
|
||||
@@ -384,12 +479,8 @@ static void connect(struct backend_info *be)
|
||||
err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
|
||||
hotplug_status_changed,
|
||||
"%s/%s", dev->nodename, "hotplug-status");
|
||||
if (err) {
|
||||
/* Switch now, since we can't do a watch. */
|
||||
xenbus_switch_state(dev, XenbusStateConnected);
|
||||
} else {
|
||||
if (!err)
|
||||
be->have_hotplug_status_watch = 1;
|
||||
}
|
||||
|
||||
netif_wake_queue(be->vif->dev);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user