diff --git a/drivers/xen/netback/xenbus.c b/drivers/xen/netback/xenbus.c index ba7b1de..805ce48 100644 --- a/drivers/xen/netback/xenbus.c +++ b/drivers/xen/netback/xenbus.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "common.h" @@ -28,6 +29,7 @@ printk("netback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) #endif +static DECLARE_RWSEM(teardown_sem); static int connect_rings(struct backend_info *); static void connect(struct backend_info *); @@ -41,14 +43,19 @@ static int netback_remove(struct xenbus_device *dev) //netback_remove_accelerators(be, dev); unregister_hotplug_status_watch(be); - if (be->netif) { + if (be->netif) kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); + + down_write(&teardown_sem); + if (be->netif) { xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); netif_disconnect(be->netif); be->netif = NULL; } - kfree(be); dev_set_drvdata(&dev->dev, NULL); + up_write(&teardown_sem); + kfree(be); + return 0; } @@ -168,7 +175,7 @@ static int netback_uevent(struct xenbus_device *xdev, struct kobj_uevent_env *en DPRINTK("netback_uevent"); - be = dev_get_drvdata(&xdev->dev); + be = dev_get_drvdata(&xdev->dev);/ if (!be) return 0; netif = be->netif; @@ -187,9 +194,14 @@ static int netback_uevent(struct xenbus_device *xdev, struct kobj_uevent_env *en kfree(val); } - if (add_uevent_var(env, "vif=%s", netif->dev->name)) - return -ENOMEM; - + down_read(&teardown_sem); + be = dev_get_drvdata(&xdev->dev); + if (be && be->netif) + if (add_uevent_var(env, "vif=%s", netif->dev->name)) { + up_read(&teardown_sem); + return -ENOMEM; + } + up_read(&teardown_sem); return 0; } @@ -199,6 +211,7 @@ static void backend_create_netif(struct backend_info *be) int err; long handle; struct xenbus_device *dev = be->dev; + netif_t *netif; if (be->netif != NULL) return; @@ -209,13 +222,13 @@ static void backend_create_netif(struct backend_info *be) return; } - be->netif = netif_alloc(&dev->dev, dev->otherend_id, handle); - if (IS_ERR(be->netif)) { - err = PTR_ERR(be->netif); - be->netif = NULL; + netif = netif_alloc(&dev->dev, dev->otherend_id, handle); + if (IS_ERR(netif)) { + err = PTR_ERR(netif); xenbus_dev_fatal(dev, err, "creating interface"); return; } + be->netif = netif; kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE); }