cfg80211: simplify netlink socket owner interface deletion
authorJohannes Berg <johannes.berg@intel.com>
Wed, 26 Apr 2017 05:43:41 +0000 (07:43 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 26 Apr 2017 21:17:35 +0000 (23:17 +0200)
There's no need to allocate a portid structure and then, for
each of those, walk the interfaces - we can just add a flag
to each interface and walk those directly. Due to padding in
the struct, we can even do it without any memory cost, and
it even simplifies the code.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c

index 2a200b964b7a9c074f26a78bf55adeff5d52530c..af958938b3b1e7e82b3ccbb92a9f7b7714655e72 100644 (file)
@@ -3988,6 +3988,7 @@ struct cfg80211_cqm_config;
  * @event_list: (private) list for internal event processing
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
+ * @nl_owner_dead: (private) owner socket went away
  * @cqm_config: (private) nl80211 RSSI monitor state
  */
 struct wireless_dev {
@@ -4037,12 +4038,13 @@ struct wireless_dev {
 
        u32 ap_unexpected_nlportid;
 
+       u32 owner_nlportid;
+       bool nl_owner_dead;
+
        bool cac_started;
        unsigned long cac_start_time;
        unsigned int cac_time_ms;
 
-       u32 owner_nlportid;
-
 #ifdef CONFIG_CFG80211_WEXT
        /* wext data */
        struct {
index b0d6761f0cdd77ba67bf3caff2df6fcab4733e3c..4ea28de3a63678b5e03ba07c292f04e9fc9eb65b 100644 (file)
@@ -305,30 +305,14 @@ static void cfg80211_event_work(struct work_struct *work)
 
 void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
 {
-       struct cfg80211_iface_destroy *item;
+       struct wireless_dev *wdev, *tmp;
 
        ASSERT_RTNL();
 
-       spin_lock_irq(&rdev->destroy_list_lock);
-       while ((item = list_first_entry_or_null(&rdev->destroy_list,
-                                               struct cfg80211_iface_destroy,
-                                               list))) {
-               struct wireless_dev *wdev, *tmp;
-               u32 nlportid = item->nlportid;
-
-               list_del(&item->list);
-               kfree(item);
-               spin_unlock_irq(&rdev->destroy_list_lock);
-
-               list_for_each_entry_safe(wdev, tmp,
-                                        &rdev->wiphy.wdev_list, list) {
-                       if (nlportid == wdev->owner_nlportid)
-                               rdev_del_virtual_intf(rdev, wdev);
-               }
-
-               spin_lock_irq(&rdev->destroy_list_lock);
+       list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
+               if (wdev->nl_owner_dead)
+                       rdev_del_virtual_intf(rdev, wdev);
        }
-       spin_unlock_irq(&rdev->destroy_list_lock);
 }
 
 static void cfg80211_destroy_iface_wk(struct work_struct *work)
@@ -484,8 +468,6 @@ use_default_name:
        rdev->wiphy.dev.platform_data = rdev;
        device_enable_async_suspend(&rdev->wiphy.dev);
 
-       INIT_LIST_HEAD(&rdev->destroy_list);
-       spin_lock_init(&rdev->destroy_list_lock);
        INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
        INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
        INIT_WORK(&rdev->propagate_radar_detect_wk,
index 5d27eca57d3b611b5c82edc283915d0842c4b7d5..f9b748e3425a07de281d2ab9fd89adfd38b69825 100644 (file)
@@ -91,10 +91,7 @@ struct cfg80211_registered_device {
 
        struct cfg80211_coalesce *coalesce;
 
-       spinlock_t destroy_list_lock;
-       struct list_head destroy_list;
        struct work_struct destroy_work;
-
        struct work_struct sched_scan_stop_wk;
 
        struct cfg80211_chan_def radar_chandef;
@@ -264,11 +261,6 @@ struct cfg80211_beacon_registration {
        u32 nlportid;
 };
 
-struct cfg80211_iface_destroy {
-       struct list_head list;
-       u32 nlportid;
-};
-
 struct cfg80211_cqm_config {
        u32 rssi_hyst;
        s32 last_rssi_event_value;
index 50c35affccad70c4cd8b76fae16d98f1ef7799ed..45f5f418e562cb776e1755fd4202fa264a024c0a 100644 (file)
@@ -14883,7 +14883,6 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
        rcu_read_lock();
 
        list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
-               bool schedule_destroy_work = false;
                struct cfg80211_sched_scan_request *sched_scan_req =
                        rcu_dereference(rdev->sched_scan_req);
 
@@ -14899,10 +14898,12 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
                list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
                        cfg80211_mlme_unregister_socket(wdev, notify->portid);
 
-                       if (wdev->owner_nlportid == notify->portid)
-                               schedule_destroy_work = true;
-                       else if (wdev->conn_owner_nlportid == notify->portid)
+                       if (wdev->owner_nlportid == notify->portid) {
+                               wdev->nl_owner_dead = true;
+                               schedule_work(&rdev->destroy_work);
+                       } else if (wdev->conn_owner_nlportid == notify->portid) {
                                schedule_work(&wdev->disconnect_wk);
+                       }
                }
 
                spin_lock_bh(&rdev->beacon_registrations_lock);
@@ -14915,19 +14916,6 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
                        }
                }
                spin_unlock_bh(&rdev->beacon_registrations_lock);
-
-               if (schedule_destroy_work) {
-                       struct cfg80211_iface_destroy *destroy;
-
-                       destroy = kzalloc(sizeof(*destroy), GFP_ATOMIC);
-                       if (destroy) {
-                               destroy->nlportid = notify->portid;
-                               spin_lock(&rdev->destroy_list_lock);
-                               list_add(&destroy->list, &rdev->destroy_list);
-                               spin_unlock(&rdev->destroy_list_lock);
-                               schedule_work(&rdev->destroy_work);
-                       }
-               }
        }
 
        rcu_read_unlock();