device: duplicate the config earlier to avoid using stale data
[project/netifd.git] / device.c
index f9ad25a..91a7867 100644 (file)
--- a/device.c
+++ b/device.c
@@ -99,7 +99,7 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
 
 static void __init dev_init(void)
 {
-       avl_init(&devices, avl_strcmp, false, NULL);
+       avl_init(&devices, avl_strcmp, true, NULL);
 }
 
 static void device_broadcast_event(struct device *dev, enum device_event ev)
@@ -337,8 +337,8 @@ device_replace(struct device *dev, struct device *odev)
                device_set_present(odev, false);
 
        list_for_each_entry_safe(dep, tmp, &odev->users, list) {
-               list_move_tail(&dep->list, &dev->users);
-               dep->dev = dev;
+               device_remove_user(dep);
+               device_add_user(dep, dev);
        }
        device_free(odev);
 
@@ -353,19 +353,25 @@ device_create(const char *name, const struct device_type *type,
        struct device *odev = NULL, *dev;
        enum dev_change_type change;
 
+       D(DEVICE, "Create new device '%s' (%s)\n", name, type->name);
+       config = config_memdup(config);
+       if (!config)
+               return NULL;
+
        odev = device_get(name, false);
        if (odev) {
                change = device_check_config(odev, config);
                switch (change) {
                case DEV_CONFIG_APPLIED:
                        free(odev->config);
-                       odev->config = config_memdup(config);
+                       odev->config = config;
                        if (odev->present) {
                                device_set_present(odev, false);
                                device_set_present(odev, true);
                        }
                        /* fall through */
                case DEV_CONFIG_NO_CHANGE:
+                       free(config);
                        return odev;
                case DEV_CONFIG_RECREATE:
                        break;
@@ -373,7 +379,7 @@ device_create(const char *name, const struct device_type *type,
        }
 
        dev = type->create(config);
-       dev->config = config_memdup(config);
+       dev->config = config;
        if (odev)
                device_replace(dev, odev);