]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.git/commitdiff
Arrange that netback waits for the hotplug scripts to complete before
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Tue, 30 Jun 2009 11:55:48 +0000 (12:55 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Tue, 30 Jun 2009 11:55:48 +0000 (12:55 +0100)
going to state Connected.  WHQL gets quite upset if it sends packets
which don't arrive, and that can happen if our hotplug scripts are
slow and don't hook the network interface up to the bridge in time.

drivers/xen/netback/common.h
drivers/xen/netback/xenbus.c

index faa527fab8f887fcbd52b6a15867d40ad547530d..5d80145016f5c538cd076f2560615ac4f0d0ae3b 100644 (file)
@@ -152,7 +152,9 @@ struct backend_info {
        enum xenbus_state frontend_state;
        struct xenbus_watch csum_offload_watch;
        int have_csum_offload:1;
+       struct xenbus_watch hotplug_status_watch;
        int have_csum_offload_watch:1;
+       int have_hotplug_status_watch:1;
 
        /* State relating to the netback accelerator */
        void *netback_accel_priv;
index 1bb9140b64721648502b70334ff0390d2ff0a91d..986257f693b8997c37f886a778b1477655c26ab5 100644 (file)
@@ -34,6 +34,7 @@ static void connect(struct backend_info *);
 static void backend_create_netif(struct backend_info *be);
 static int register_csum_offload_watch(struct backend_info *be);
 static void unregister_csum_offload_watch(struct backend_info *be);
+static void unregister_hotplug_status_watch(struct backend_info *be);
 
 static int netback_remove(struct xenbus_device *dev)
 {
@@ -42,8 +43,10 @@ static int netback_remove(struct xenbus_device *dev)
        netback_remove_accelerators(be, dev);
 
        unregister_csum_offload_watch(be);
+       unregister_hotplug_status_watch(be);
        if (be->netif) {
                kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+               xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
                netif_disconnect(be->netif);
                be->netif = NULL;
        }
@@ -232,6 +235,7 @@ static void disconnect_backend(struct xenbus_device *dev)
 
        if (be->netif) {
                unregister_csum_offload_watch(be);
+               xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
                netif_disconnect(be->netif);
                be->netif = NULL;
        }
@@ -352,6 +356,36 @@ static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
        return 0;
 }
 
+static void unregister_hotplug_status_watch(struct backend_info *be)
+{
+       if (be->have_hotplug_status_watch) {
+               unregister_xenbus_watch(&be->hotplug_status_watch);
+               kfree(be->hotplug_status_watch.node);
+       }
+       be->have_hotplug_status_watch = 0;
+}
+
+static void hotplug_status_changed(struct xenbus_watch *watch,
+                                  const char **vec,
+                                  unsigned int vec_size)
+{
+       struct backend_info *be = container_of(watch,
+                                              struct backend_info,
+                                              hotplug_status_watch);
+       char *str;
+       unsigned int len;
+
+       str = xenbus_read(XBT_NIL, be->dev->nodename, "hotplug-status", &len);
+       if ( IS_ERR(str) )
+               return;
+       if ( len == sizeof("connected")-1 && !memcmp(str, "connected", len) ) {
+               xenbus_switch_state(be->dev, XenbusStateConnected);
+               /* Not interested in this watch anymore. */
+               unregister_hotplug_status_watch(be);
+       }
+       kfree(str);
+}
+
 static void connect(struct backend_info *be)
 {
        int err;
@@ -371,7 +405,16 @@ static void connect(struct backend_info *be)
                          &be->netif->credit_usec);
        be->netif->remaining_credit = be->netif->credit_bytes;
 
-       xenbus_switch_state(dev, XenbusStateConnected);
+       unregister_hotplug_status_watch(be);
+       err = xenbus_watch_path2(dev, dev->nodename, "hotplug-status",
+                                &be->hotplug_status_watch,
+                                hotplug_status_changed);
+       if (err) {
+               /* Switch now, since we can't do a watch. */
+               xenbus_switch_state(dev, XenbusStateConnected);
+       } else {
+               be->have_hotplug_status_watch = 1;
+       }
 
        netif_wake_queue(be->netif->dev);
 }