aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-07 06:04:29 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-14 20:46:41 -0400
commit63044e9f54b6bac50d2380bf4d14f63e9e7de72b (patch)
tree9ceddf721c869fb9450429fd4932d8c40b765486 /net
parent45527c2c4f698f8927239cfdec9f515cafed5f10 (diff)
mac80211: fix debugfs lockup
When debugfs_create_dir fails, sta_info_debugfs_add_work will not terminate because it will find the same station again and again. This is possible whenever debugfs fails for whatever reason; one reason is a race condition in mac80211, unfortunately we cannot do much about it, so just document it, it just means some station may be missing from debugfs. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: Robin Holt <holt@sgi.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/debugfs_sta.c11
-rw-r--r--net/mac80211/sta_info.c7
-rw-r--r--net/mac80211/sta_info.h1
3 files changed, 18 insertions, 1 deletions
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index b9902e425f09..189d0bafa91a 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -249,11 +249,22 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
249 DECLARE_MAC_BUF(mbuf); 249 DECLARE_MAC_BUF(mbuf);
250 u8 *mac; 250 u8 *mac;
251 251
252 sta->debugfs.add_has_run = true;
253
252 if (!stations_dir) 254 if (!stations_dir)
253 return; 255 return;
254 256
255 mac = print_mac(mbuf, sta->sta.addr); 257 mac = print_mac(mbuf, sta->sta.addr);
256 258
259 /*
260 * This might fail due to a race condition:
261 * When mac80211 unlinks a station, the debugfs entries
262 * remain, but it is already possible to link a new
263 * station with the same address which triggers adding
264 * it to debugfs; therefore, if the old station isn't
265 * destroyed quickly enough the old station's debugfs
266 * dir might still be around.
267 */
257 sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); 268 sta->debugfs.dir = debugfs_create_dir(mac, stations_dir);
258 if (!sta->debugfs.dir) 269 if (!sta->debugfs.dir)
259 return; 270 return;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 9b72d15bc8dc..7fef8ea1f5ec 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -635,7 +635,12 @@ static void sta_info_debugfs_add_work(struct work_struct *work)
635 635
636 spin_lock_irqsave(&local->sta_lock, flags); 636 spin_lock_irqsave(&local->sta_lock, flags);
637 list_for_each_entry(tmp, &local->sta_list, list) { 637 list_for_each_entry(tmp, &local->sta_list, list) {
638 if (!tmp->debugfs.dir) { 638 /*
639 * debugfs.add_has_run will be set by
640 * ieee80211_sta_debugfs_add regardless
641 * of what else it does.
642 */
643 if (!tmp->debugfs.add_has_run) {
639 sta = tmp; 644 sta = tmp;
640 __sta_info_pin(sta); 645 __sta_info_pin(sta);
641 break; 646 break;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index a6b51862a89d..168a39a298bd 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -300,6 +300,7 @@ struct sta_info {
300 struct dentry *inactive_ms; 300 struct dentry *inactive_ms;
301 struct dentry *last_seq_ctrl; 301 struct dentry *last_seq_ctrl;
302 struct dentry *agg_status; 302 struct dentry *agg_status;
303 bool add_has_run;
303 } debugfs; 304 } debugfs;
304#endif 305#endif
305 306