aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/drop_monitor.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2012-05-17 06:04:00 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-17 16:09:07 -0400
commitcad456d5abbb6307be7a658d701bc44ca689e906 (patch)
tree116ce24c03c83876692e79ee9436dda976f86d84 /net/core/drop_monitor.c
parenta1c7fff7e18f59e684e07b0f9a770561cd39f395 (diff)
drop_monitor: convert to modular building
When I first wrote drop monitor I wrote it to just build monolithically. There is no reason it can't be built modularly as well, so lets give it that flexibiity. I've tested this by building it as both a module and monolithically, and it seems to work quite well Change notes: v2) * fixed for_each_present_cpu loops to be more correct as per Eric D. * Converted exit path failures to BUG_ON as per Ben H. v3) * Converted del_timer to del_timer_sync to close race noted by Ben H. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> CC: "David S. Miller" <davem@davemloft.net> CC: Eric Dumazet <eric.dumazet@gmail.com> CC: Ben Hutchings <bhutchings@solarflare.com> Reviewed-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/drop_monitor.c')
-rw-r--r--net/core/drop_monitor.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index eca00a96bcf3..3252e7e0a005 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -24,6 +24,7 @@
24#include <linux/timer.h> 24#include <linux/timer.h>
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/module.h>
27#include <net/genetlink.h> 28#include <net/genetlink.h>
28#include <net/netevent.h> 29#include <net/netevent.h>
29 30
@@ -263,9 +264,15 @@ static int set_all_monitor_traces(int state)
263 264
264 switch (state) { 265 switch (state) {
265 case TRACE_ON: 266 case TRACE_ON:
267 if (!try_module_get(THIS_MODULE)) {
268 rc = -ENODEV;
269 break;
270 }
271
266 rc |= register_trace_kfree_skb(trace_kfree_skb_hit, NULL); 272 rc |= register_trace_kfree_skb(trace_kfree_skb_hit, NULL);
267 rc |= register_trace_napi_poll(trace_napi_poll_hit, NULL); 273 rc |= register_trace_napi_poll(trace_napi_poll_hit, NULL);
268 break; 274 break;
275
269 case TRACE_OFF: 276 case TRACE_OFF:
270 rc |= unregister_trace_kfree_skb(trace_kfree_skb_hit, NULL); 277 rc |= unregister_trace_kfree_skb(trace_kfree_skb_hit, NULL);
271 rc |= unregister_trace_napi_poll(trace_napi_poll_hit, NULL); 278 rc |= unregister_trace_napi_poll(trace_napi_poll_hit, NULL);
@@ -281,6 +288,9 @@ static int set_all_monitor_traces(int state)
281 kfree_rcu(new_stat, rcu); 288 kfree_rcu(new_stat, rcu);
282 } 289 }
283 } 290 }
291
292 module_put(THIS_MODULE);
293
284 break; 294 break;
285 default: 295 default:
286 rc = 1; 296 rc = 1;
@@ -406,7 +416,7 @@ static int __init init_net_drop_monitor(void)
406 416
407 rc = 0; 417 rc = 0;
408 418
409 for_each_present_cpu(cpu) { 419 for_each_possible_cpu(cpu) {
410 data = &per_cpu(dm_cpu_data, cpu); 420 data = &per_cpu(dm_cpu_data, cpu);
411 data->cpu = cpu; 421 data->cpu = cpu;
412 INIT_WORK(&data->dm_alert_work, send_dm_alert); 422 INIT_WORK(&data->dm_alert_work, send_dm_alert);
@@ -425,4 +435,36 @@ out:
425 return rc; 435 return rc;
426} 436}
427 437
428late_initcall(init_net_drop_monitor); 438static void exit_net_drop_monitor(void)
439{
440 struct per_cpu_dm_data *data;
441 int cpu;
442
443 BUG_ON(unregister_netdevice_notifier(&dropmon_net_notifier));
444
445 /*
446 * Because of the module_get/put we do in the trace state change path
447 * we are guarnateed not to have any current users when we get here
448 * all we need to do is make sure that we don't have any running timers
449 * or pending schedule calls
450 */
451
452 for_each_possible_cpu(cpu) {
453 data = &per_cpu(dm_cpu_data, cpu);
454 del_timer_sync(&data->send_timer);
455 cancel_work_sync(&data->dm_alert_work);
456 /*
457 * At this point, we should have exclusive access
458 * to this struct and can free the skb inside it
459 */
460 kfree_skb(data->skb);
461 }
462
463 BUG_ON(genl_unregister_family(&net_drop_monitor_family));
464}
465
466module_init(init_net_drop_monitor);
467module_exit(exit_net_drop_monitor);
468
469MODULE_LICENSE("GPL v2");
470MODULE_AUTHOR("Neil Horman <nhorman@tuxdriver.com>");