summaryrefslogtreecommitdiffhomepage
path: root/device.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-10-19 03:20:09 +0200
committerFelix Fietkau <nbd@openwrt.org>2011-10-19 03:20:09 +0200
commitd16871c7a55370174eb672edee24feade74cd37e (patch)
tree39995e27e86f9efbf101a8b9f5a23e7d9821bae8 /device.c
parentccca61c97d460d73f29750abdf38cea20ac440f3 (diff)
rework device hotplug handling some more, add device_lock/device_unlock to prevent use-after-free bugs
Diffstat (limited to 'device.c')
-rw-r--r--device.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/device.c b/device.c
index 1136380..0a33f67 100644
--- a/device.c
+++ b/device.c
@@ -41,6 +41,20 @@ const struct config_param_list device_attr_list = {
.params = dev_attrs,
};
+static int __devlock = 0;
+
+void device_lock(void)
+{
+ __devlock++;
+}
+
+void device_unlock(void)
+{
+ __devlock--;
+ if (!__devlock)
+ device_free_unused(NULL);
+}
+
static struct device *
simple_device_create(const char *name, struct blob_attr *attr)
{
@@ -172,6 +186,8 @@ alias_notify_device(const char *name, struct device *dev)
{
struct alias_device *alias;
+ device_lock();
+
alias = avl_find_element(&aliases, name, alias, avl);
if (!alias)
return;
@@ -189,6 +205,8 @@ alias_notify_device(const char *name, struct device *dev)
if (!dev && alias->dep.dev && !alias->dep.dev->active)
device_remove_user(&alias->dep);
+
+ device_unlock();
}
static int set_device_state(struct device *dev, bool state)
@@ -398,6 +416,7 @@ void device_remove_user(struct device_user *dep)
if (!dep->dev)
return;
+ dep->hotplug = false;
if (dep->claimed)
device_release(dep);