From cf90523881521fe8396a728230169b6b8ea7e8da Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Feb 2013 19:14:35 +0100 Subject: [PATCH] device: protect device event broadcast against simultaneous deletions of multiple receivers in the callback (can happen with aliases) Signed-off-by: Felix Fietkau --- device.c | 25 +++++++++++++++++++------ device.h | 4 ++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/device.c b/device.c index 97fb27f..9ef444e 100644 --- a/device.c +++ b/device.c @@ -183,14 +183,27 @@ static void __init dev_init(void) static void __device_broadcast_event(struct list_head *head, enum device_event ev) { - struct device_user *dep, *tmp; + struct device_user *dep; + static uint8_t idx[__DEV_EVENT_MAX]; + bool found; - list_for_each_entry_safe(dep, tmp, head, list) { - if (!dep->cb) - continue; + idx[ev]++; + do { + found = false; - dep->cb(dep, ev); - } + list_for_each_entry(dep, head, list) { + if (!dep->cb) + continue; + + if (dep->ev_idx[ev] == idx[ev]) + continue; + + dep->cb(dep, ev); + dep->ev_idx[ev] = idx[ev]; + found = true; + break; + } + } while (found); } void device_broadcast_event(struct device *dev, enum device_event ev) diff --git a/device.h b/device.h index 8cedfba..1f852ab 100644 --- a/device.h +++ b/device.h @@ -75,6 +75,8 @@ enum device_event { DEV_EVENT_LINK_UP, DEV_EVENT_LINK_DOWN, + + __DEV_EVENT_MAX }; /* @@ -87,6 +89,8 @@ struct device_user { bool hotplug; bool alias; + uint8_t ev_idx[__DEV_EVENT_MAX]; + struct device *dev; void (*cb)(struct device_user *, enum device_event); }; -- 2.25.1