History

mac80211: fix mesh deadlock

The patch "cfg80211/mac80211: use cfg80211 wdev mutex in mac80211" introduced several deadlocks by converting the ifmsh->mtx to wdev->mtx. Solve these by: 1. drop the cancel_work_sync() in ieee80211_stop_mesh(). Instead make the mesh work conditional on whether the mesh is running or not. 2. lock the mesh work with sdata_lock() to protect beacon updates and prevent races with wdev->mesh_id_len or cfg80211.

Thomas Pedersen committed 13 years ago

Commit ecccd071 parent 780b40d2 files · +18 −18Browse files

Unified · Split

2 files
  1. net/mac80211/mesh.c +17 −12
  2. net/mac80211/mesh_plink.c +1 −6
net/mac80211/mesh.c+17−12
@@ -579,9 +579,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata) · 578 unmodified lines
579 mesh_path_expire(sdata);579 mesh_path_expire(sdata);
580 580
581 changed = mesh_accept_plinks_update(sdata);581 changed = mesh_accept_plinks_update(sdata);
582 sdata_lock(sdata);
583 ieee80211_mbss_info_change_notify(sdata, changed);582 ieee80211_mbss_info_change_notify(sdata, changed);
584 sdata_unlock(sdata);
585 583
586 mod_timer(&ifmsh->housekeeping_timer,584 mod_timer(&ifmsh->housekeeping_timer,
587 round_jiffies(jiffies +585 round_jiffies(jiffies +
@@ -788,12 +786,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) · 200 unmodified lines
788 sdata->vif.bss_conf.enable_beacon = false;786 sdata->vif.bss_conf.enable_beacon = false;
789 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);787 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
790 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);788 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
791 sdata_lock(sdata);
792 bcn = rcu_dereference_protected(ifmsh->beacon,789 bcn = rcu_dereference_protected(ifmsh->beacon,
793 lockdep_is_held(&sdata->wdev.mtx));790 lockdep_is_held(&sdata->wdev.mtx));
794 rcu_assign_pointer(ifmsh->beacon, NULL);791 rcu_assign_pointer(ifmsh->beacon, NULL);
795 kfree_rcu(bcn, rcu_head);792 kfree_rcu(bcn, rcu_head);
796 sdata_unlock(sdata);
797 793
798 /* flush STAs and mpaths on this iface */794 /* flush STAs and mpaths on this iface */
799 sta_info_flush(sdata);795 sta_info_flush(sdata);
@@ -806,14 +802,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) · 6 unmodified lines
806 del_timer_sync(&sdata->u.mesh.housekeeping_timer);802 del_timer_sync(&sdata->u.mesh.housekeeping_timer);
807 del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);803 del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);
808 del_timer_sync(&sdata->u.mesh.mesh_path_timer);804 del_timer_sync(&sdata->u.mesh.mesh_path_timer);
809 /*
810 * If the timer fired while we waited for it, it will have
811 * requeued the work. Now the work will be running again
812 * but will not rearm the timer again because it checks
813 * whether the interface is running, which, at this point,
814 * it no longer is.
815 */
816 cancel_work_sync(&sdata->work);
817 805
818 local->fif_other_bss--;806 local->fif_other_bss--;
819 atomic_dec(&local->iff_allmultis);807 atomic_dec(&local->iff_allmultis);
@@ -954,6 +942,12 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, · 134 unmodified lines
954 struct ieee80211_mgmt *mgmt;942 struct ieee80211_mgmt *mgmt;
955 u16 stype;943 u16 stype;
956 944
945 sdata_lock(sdata);
946
947 /* mesh already went down */
948 if (!sdata->wdev.mesh_id_len)
949 goto out;
950
957 rx_status = IEEE80211_SKB_RXCB(skb);951 rx_status = IEEE80211_SKB_RXCB(skb);
958 mgmt = (struct ieee80211_mgmt *) skb->data;952 mgmt = (struct ieee80211_mgmt *) skb->data;
959 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;953 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
@@ -971,12 +965,20 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, · 11 unmodified lines
971 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);965 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
972 break;966 break;
973 }967 }
968out:
969 sdata_unlock(sdata);
974}970}
975 971
976void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)972void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
977{973{
978 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;974 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
979 975
976 sdata_lock(sdata);
977
978 /* mesh already went down */
979 if (!sdata->wdev.mesh_id_len)
980 goto out;
981
980 if (ifmsh->preq_queue_len &&982 if (ifmsh->preq_queue_len &&
981 time_after(jiffies,983 time_after(jiffies,
982 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))984 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
@@ -996,6 +998,9 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) · 13 unmodified lines
996 998
997 if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags))999 if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags))
998 mesh_sync_adjust_tbtt(sdata);1000 mesh_sync_adjust_tbtt(sdata);
1001
1002out:
1003 sdata_unlock(sdata);
999}1004}
1000 1005
1001void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)1006void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
net/mac80211/mesh_plink.c+1−6
@@ -517,9 +517,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, · 516 unmodified lines
517 ieee80211_mps_frame_release(sta, elems);517 ieee80211_mps_frame_release(sta, elems);
518out:518out:
519 rcu_read_unlock();519 rcu_read_unlock();
520 sdata_lock(sdata);
521 ieee80211_mbss_info_change_notify(sdata, changed);520 ieee80211_mbss_info_change_notify(sdata, changed);
522 sdata_unlock(sdata);
523}521}
524 522
525static void mesh_plink_timer(unsigned long data)523static void mesh_plink_timer(unsigned long data)
@@ -1070,9 +1068,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, · 544 unmodified lines
1070 1068
1071 rcu_read_unlock();1069 rcu_read_unlock();
1072 1070
1073 if (changed) {1071 if (changed)
1074 sdata_lock(sdata);
1075 ieee80211_mbss_info_change_notify(sdata, changed);1072 ieee80211_mbss_info_change_notify(sdata, changed);
1076 sdata_unlock(sdata);
1077 }
1078}1073}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t