aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-06-23 21:34:48 -0400
committerDavid S. Miller <davem@davemloft.net>2009-07-15 11:53:32 -0400
commitb333b3d22822cf9b295990866798e9239c9dee72 (patch)
tree307298699e475eb93a3326384fff6f28b1e28b0f
parent97fd5bc7f2e442482a7a6cc4bc2a286cbb5f4754 (diff)
wireless extensions: make netns aware
This makes wireless extensions netns aware. The tasklet sending the events is converted to a work struct so that we can rtnl_lock() in it. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/net_namespace.h3
-rw-r--r--net/wireless/wext.c61
2 files changed, 32 insertions, 32 deletions
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 3882db1e263a..5c5136fceea8 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -80,6 +80,9 @@ struct net {
80#ifdef CONFIG_XFRM 80#ifdef CONFIG_XFRM
81 struct netns_xfrm xfrm; 81 struct netns_xfrm xfrm;
82#endif 82#endif
83#ifdef CONFIG_WIRELESS_EXT
84 struct sk_buff_head wext_nlevents;
85#endif
83 struct net_generic *gen; 86 struct net_generic *gen;
84}; 87};
85 88
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index 425f7d58b961..db8351a5a87d 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -1257,48 +1257,48 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
1257} 1257}
1258#endif 1258#endif
1259 1259
1260/************************* EVENT PROCESSING *************************/ 1260static int __net_init wext_pernet_init(struct net *net)
1261/* 1261{
1262 * Process events generated by the wireless layer or the driver. 1262 skb_queue_head_init(&net->wext_nlevents);
1263 * Most often, the event will be propagated through rtnetlink 1263 return 0;
1264 */ 1264}
1265 1265
1266/* ---------------------------------------------------------------- */ 1266static void __net_exit wext_pernet_exit(struct net *net)
1267/* 1267{
1268 * Locking... 1268 skb_queue_purge(&net->wext_nlevents);
1269 * ---------- 1269}
1270 *
1271 * Thanks to Herbert Xu <herbert@gondor.apana.org.au> for fixing
1272 * the locking issue in here and implementing this code !
1273 *
1274 * The issue : wireless_send_event() is often called in interrupt context,
1275 * while the Netlink layer can never be called in interrupt context.
1276 * The fully formed RtNetlink events are queued, and then a tasklet is run
1277 * to feed those to Netlink.
1278 * The skb_queue is interrupt safe, and its lock is not held while calling
1279 * Netlink, so there is no possibility of dealock.
1280 * Jean II
1281 */
1282 1270
1283static struct sk_buff_head wireless_nlevent_queue; 1271static struct pernet_operations wext_pernet_ops = {
1272 .init = wext_pernet_init,
1273 .exit = wext_pernet_exit,
1274};
1284 1275
1285static int __init wireless_nlevent_init(void) 1276static int __init wireless_nlevent_init(void)
1286{ 1277{
1287 skb_queue_head_init(&wireless_nlevent_queue); 1278 return register_pernet_subsys(&wext_pernet_ops);
1288 return 0; 1279 return 0;
1289} 1280}
1290 1281
1291subsys_initcall(wireless_nlevent_init); 1282subsys_initcall(wireless_nlevent_init);
1292 1283
1293static void wireless_nlevent_process(unsigned long data) 1284/* Process events generated by the wireless layer or the driver. */
1285static void wireless_nlevent_process(struct work_struct *work)
1294{ 1286{
1295 struct sk_buff *skb; 1287 struct sk_buff *skb;
1288 struct net *net;
1289
1290 rtnl_lock();
1296 1291
1297 while ((skb = skb_dequeue(&wireless_nlevent_queue))) 1292 for_each_net(net) {
1298 rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); 1293 while ((skb = skb_dequeue(&net->wext_nlevents)))
1294 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
1295 GFP_KERNEL);
1296 }
1297
1298 rtnl_unlock();
1299} 1299}
1300 1300
1301static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0); 1301static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
1302 1302
1303/* ---------------------------------------------------------------- */ 1303/* ---------------------------------------------------------------- */
1304/* 1304/*
@@ -1348,9 +1348,6 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
1348 struct sk_buff *skb; 1348 struct sk_buff *skb;
1349 int err; 1349 int err;
1350 1350
1351 if (!net_eq(dev_net(dev), &init_net))
1352 return;
1353
1354 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1351 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1355 if (!skb) 1352 if (!skb)
1356 return; 1353 return;
@@ -1363,8 +1360,8 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
1363 } 1360 }
1364 1361
1365 NETLINK_CB(skb).dst_group = RTNLGRP_LINK; 1362 NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1366 skb_queue_tail(&wireless_nlevent_queue, skb); 1363 skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
1367 tasklet_schedule(&wireless_nlevent_tasklet); 1364 schedule_work(&wireless_nlevent_work);
1368} 1365}
1369 1366
1370/* ---------------------------------------------------------------- */ 1367/* ---------------------------------------------------------------- */