OSDN Git Service

mac80211: allocate and fill tidstats only when needed
authorJohannes Berg <johannes.berg@intel.com>
Fri, 18 May 2018 09:40:44 +0000 (11:40 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 18 May 2018 09:40:44 +0000 (11:40 +0200)
This fixes memory leaks in the case where we just have the
station info on the stack for internal usage without sending
it to cfg80211.

Fixes: 8689c051a201 ("cfg80211: dynamically allocate per-tid stats for station info")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/ethtool.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h

index 5ce9d12..bdf6fa7 100644 (file)
@@ -695,7 +695,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
        if (sta) {
                ret = 0;
                memcpy(mac, sta->sta.addr, ETH_ALEN);
-               sta_set_sinfo(sta, sinfo);
+               sta_set_sinfo(sta, sinfo, true);
        }
 
        mutex_unlock(&local->sta_mtx);
@@ -724,7 +724,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
        sta = sta_info_get_bss(sdata, mac);
        if (sta) {
                ret = 0;
-               sta_set_sinfo(sta, sinfo);
+               sta_set_sinfo(sta, sinfo, true);
        }
 
        mutex_unlock(&local->sta_mtx);
index 2ba5686..690c142 100644 (file)
@@ -108,7 +108,7 @@ static void ieee80211_get_stats(struct net_device *dev,
                        goto do_survey;
 
                memset(&sinfo, 0, sizeof(sinfo));
-               sta_set_sinfo(sta, &sinfo);
+               sta_set_sinfo(sta, &sinfo, false);
 
                i = 0;
                ADD_STA_STATS(sta);
@@ -135,7 +135,7 @@ static void ieee80211_get_stats(struct net_device *dev,
                                continue;
 
                        memset(&sinfo, 0, sizeof(sinfo));
-                       sta_set_sinfo(sta, &sinfo);
+                       sta_set_sinfo(sta, &sinfo, false);
                        i = 0;
                        ADD_STA_STATS(sta);
                }
index 04d4768..6428f1a 100644 (file)
@@ -1008,7 +1008,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
 
        sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
        if (sinfo)
-               sta_set_sinfo(sta, sinfo);
+               sta_set_sinfo(sta, sinfo, true);
        cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
        kfree(sinfo);
 
@@ -2079,7 +2079,8 @@ static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
        return value;
 }
 
-void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
+void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
+                  bool tidstats)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        struct ieee80211_local *local = sdata->local;
@@ -2233,7 +2234,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                        sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
        }
 
-       if (!cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) {
+       if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) {
                for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
                        struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i];
 
index d79bd6e..81b35f6 100644 (file)
@@ -744,7 +744,8 @@ static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata)
 void sta_set_rate_info_tx(struct sta_info *sta,
                          const struct ieee80211_tx_rate *rate,
                          struct rate_info *rinfo);
-void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
+void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
+                  bool tidstats);
 
 u32 sta_get_expected_throughput(struct sta_info *sta);