aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-03-01 08:03:49 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-01 09:05:19 -0500
commit645e77def93f1dd0e211c7244fbe152dac8a7100 (patch)
tree319be421ebcaa108bfaf0f07de0820f42ba6cee3 /net
parentfeda30271e5455394c57e35eba66db88d1b15077 (diff)
nl80211: increase wiphy dump size dynamically
Given a device with many channels capabilities the wiphy information can still overflow even though its size in 3.9 was reduced to 3.8 levels. For new userspace and kernel 3.10 we're going to implement a new "split dump" protocol that can use multiple messages per wiphy. For now though, add a workaround to be able to send more information to userspace. Since generic netlink doesn't have a way to set the minimum dump size globally, and we wouldn't really want to set it globally anyway, increase the size only when needed, as described in the comments. As userspace might not be prepared for large buffers, we can only use 4k. Also increase the size for the get_wiphy command. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/wireless/nl80211.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7a7b621d45fd..d44ab216c0ec 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1307,7 +1307,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
1307 1307
1308static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) 1308static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1309{ 1309{
1310 int idx = 0; 1310 int idx = 0, ret;
1311 int start = cb->args[0]; 1311 int start = cb->args[0];
1312 struct cfg80211_registered_device *dev; 1312 struct cfg80211_registered_device *dev;
1313 1313
@@ -1317,9 +1317,29 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1317 continue; 1317 continue;
1318 if (++idx <= start) 1318 if (++idx <= start)
1319 continue; 1319 continue;
1320 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, 1320 ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
1321 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1321 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1322 dev) < 0) { 1322 dev);
1323 if (ret < 0) {
1324 /*
1325 * If sending the wiphy data didn't fit (ENOBUFS or
1326 * EMSGSIZE returned), this SKB is still empty (so
1327 * it's not too big because another wiphy dataset is
1328 * already in the skb) and we've not tried to adjust
1329 * the dump allocation yet ... then adjust the alloc
1330 * size to be bigger, and return 1 but with the empty
1331 * skb. This results in an empty message being RX'ed
1332 * in userspace, but that is ignored.
1333 *
1334 * We can then retry with the larger buffer.
1335 */
1336 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
1337 !skb->len &&
1338 cb->min_dump_alloc < 4096) {
1339 cb->min_dump_alloc = 4096;
1340 mutex_unlock(&cfg80211_mutex);
1341 return 1;
1342 }
1323 idx--; 1343 idx--;
1324 break; 1344 break;
1325 } 1345 }
@@ -1336,7 +1356,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
1336 struct sk_buff *msg; 1356 struct sk_buff *msg;
1337 struct cfg80211_registered_device *dev = info->user_ptr[0]; 1357 struct cfg80211_registered_device *dev = info->user_ptr[0];
1338 1358
1339 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1359 msg = nlmsg_new(4096, GFP_KERNEL);
1340 if (!msg) 1360 if (!msg)
1341 return -ENOMEM; 1361 return -ENOMEM;
1342 1362