summaryrefslogtreecommitdiffhomepage
path: root/device.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-09-04 15:00:25 +0200
committerFelix Fietkau <nbd@openwrt.org>2011-09-04 15:00:25 +0200
commit4e335f640fadda81aff9dd2dc06703961bea2826 (patch)
treebc9618ea20fdd6328f534488413dadd5530146ce /device.c
parentdca8c7133b1db463f6ae71ccc6d34cd12735daef (diff)
make device_claim/device_release operate on the device_user instead of the device to avoid refcount bugs
Diffstat (limited to 'device.c')
-rw-r--r--device.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/device.c b/device.c
index 0019b6c..c02335c 100644
--- a/device.c
+++ b/device.c
@@ -120,10 +120,15 @@ static int set_device_state(struct device *dev, bool state)
return 0;
}
-int device_claim(struct device *dev)
+int device_claim(struct device_user *dep)
{
+ struct device *dev = dep->dev;
int ret;
+ if (dep->claimed)
+ return 0;
+
+ dep->claimed = true;
DPRINTF("claim device %s, new refcount: %d\n", dev->ifname, dev->active + 1);
if (++dev->active != 1)
return 0;
@@ -138,8 +143,14 @@ int device_claim(struct device *dev)
return ret;
}
-void device_release(struct device *dev)
+void device_release(struct device_user *dep)
{
+ struct device *dev = dep->dev;
+
+ if (!dep->claimed)
+ return;
+
+ dep->claimed = false;
dev->active--;
DPRINTF("release device %s, new refcount: %d\n", dev->ifname, dev->active);
assert(dev->active >= 0);
@@ -254,6 +265,9 @@ void device_remove_user(struct device_user *dep)
{
struct device *dev = dep->dev;
+ if (dep->claimed)
+ device_release(dep);
+
list_del(&dep->list);
if (list_empty(&dev->users)) {