aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2012-04-27 06:11:48 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-28 02:18:48 -0400
commitcde2e9a651b76d8db36ae94cd0febc82b637e5dd (patch)
treef38ea38cdde763a3a1d86412478dbcc9df892412 /net
parent651913ce9de2bbcedef608c5d6cf39c244248509 (diff)
drop_monitor: fix sleeping in invalid context warning
Eric Dumazet pointed out this warning in the drop_monitor protocol to me: [ 38.352571] BUG: sleeping function called from invalid context at kernel/mutex.c:85 [ 38.352576] in_atomic(): 1, irqs_disabled(): 0, pid: 4415, name: dropwatch [ 38.352580] Pid: 4415, comm: dropwatch Not tainted 3.4.0-rc2+ #71 [ 38.352582] Call Trace: [ 38.352592] [<ffffffff8153aaf0>] ? trace_napi_poll_hit+0xd0/0xd0 [ 38.352599] [<ffffffff81063f2a>] __might_sleep+0xca/0xf0 [ 38.352606] [<ffffffff81655b16>] mutex_lock+0x26/0x50 [ 38.352610] [<ffffffff8153aaf0>] ? trace_napi_poll_hit+0xd0/0xd0 [ 38.352616] [<ffffffff810b72d9>] tracepoint_probe_register+0x29/0x90 [ 38.352621] [<ffffffff8153a585>] set_all_monitor_traces+0x105/0x170 [ 38.352625] [<ffffffff8153a8ca>] net_dm_cmd_trace+0x2a/0x40 [ 38.352630] [<ffffffff8154a81a>] genl_rcv_msg+0x21a/0x2b0 [ 38.352636] [<ffffffff810f8029>] ? zone_statistics+0x99/0xc0 [ 38.352640] [<ffffffff8154a600>] ? genl_rcv+0x30/0x30 [ 38.352645] [<ffffffff8154a059>] netlink_rcv_skb+0xa9/0xd0 [ 38.352649] [<ffffffff8154a5f0>] genl_rcv+0x20/0x30 [ 38.352653] [<ffffffff81549a7e>] netlink_unicast+0x1ae/0x1f0 [ 38.352658] [<ffffffff81549d76>] netlink_sendmsg+0x2b6/0x310 [ 38.352663] [<ffffffff8150824f>] sock_sendmsg+0x10f/0x130 [ 38.352668] [<ffffffff8150abe0>] ? move_addr_to_kernel+0x60/0xb0 [ 38.352673] [<ffffffff81515f04>] ? verify_iovec+0x64/0xe0 [ 38.352677] [<ffffffff81509c46>] __sys_sendmsg+0x386/0x390 [ 38.352682] [<ffffffff810ffaf9>] ? handle_mm_fault+0x139/0x210 [ 38.352687] [<ffffffff8165b5bc>] ? do_page_fault+0x1ec/0x4f0 [ 38.352693] [<ffffffff8106ba4d>] ? set_next_entity+0x9d/0xb0 [ 38.352699] [<ffffffff81310b49>] ? tty_ldisc_deref+0x9/0x10 [ 38.352703] [<ffffffff8106d363>] ? pick_next_task_fair+0x63/0x140 [ 38.352708] [<ffffffff8150b8d4>] sys_sendmsg+0x44/0x80 [ 38.352713] [<ffffffff8165f8e2>] system_call_fastpath+0x16/0x1b It stems from holding a spinlock (trace_state_lock) while attempting to register or unregister tracepoint hooks, making in_atomic() true in this context, leading to the warning when the tracepoint calls might_sleep() while its taking a mutex. Since we only use the trace_state_lock to prevent trace protocol state races, as well as hardware stat list updates on an rcu write side, we can just convert the spinlock to a mutex to avoid this problem. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Reported-by: Eric Dumazet <eric.dumazet@gmail.com> CC: David Miller <davem@davemloft.net> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/drop_monitor.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 5c3c81a609e..a221a5bbecf 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -42,7 +42,7 @@ static void send_dm_alert(struct work_struct *unused);
42 * netlink alerts 42 * netlink alerts
43 */ 43 */
44static int trace_state = TRACE_OFF; 44static int trace_state = TRACE_OFF;
45static DEFINE_SPINLOCK(trace_state_lock); 45static DEFINE_MUTEX(trace_state_mutex);
46 46
47struct per_cpu_dm_data { 47struct per_cpu_dm_data {
48 struct work_struct dm_alert_work; 48 struct work_struct dm_alert_work;
@@ -214,7 +214,7 @@ static int set_all_monitor_traces(int state)
214 struct dm_hw_stat_delta *new_stat = NULL; 214 struct dm_hw_stat_delta *new_stat = NULL;
215 struct dm_hw_stat_delta *temp; 215 struct dm_hw_stat_delta *temp;
216 216
217 spin_lock(&trace_state_lock); 217 mutex_lock(&trace_state_mutex);
218 218
219 if (state == trace_state) { 219 if (state == trace_state) {
220 rc = -EAGAIN; 220 rc = -EAGAIN;
@@ -253,7 +253,7 @@ static int set_all_monitor_traces(int state)
253 rc = -EINPROGRESS; 253 rc = -EINPROGRESS;
254 254
255out_unlock: 255out_unlock:
256 spin_unlock(&trace_state_lock); 256 mutex_unlock(&trace_state_mutex);
257 257
258 return rc; 258 return rc;
259} 259}
@@ -296,12 +296,12 @@ static int dropmon_net_event(struct notifier_block *ev_block,
296 296
297 new_stat->dev = dev; 297 new_stat->dev = dev;
298 new_stat->last_rx = jiffies; 298 new_stat->last_rx = jiffies;
299 spin_lock(&trace_state_lock); 299 mutex_lock(&trace_state_mutex);
300 list_add_rcu(&new_stat->list, &hw_stats_list); 300 list_add_rcu(&new_stat->list, &hw_stats_list);
301 spin_unlock(&trace_state_lock); 301 mutex_unlock(&trace_state_mutex);
302 break; 302 break;
303 case NETDEV_UNREGISTER: 303 case NETDEV_UNREGISTER:
304 spin_lock(&trace_state_lock); 304 mutex_lock(&trace_state_mutex);
305 list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) { 305 list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) {
306 if (new_stat->dev == dev) { 306 if (new_stat->dev == dev) {
307 new_stat->dev = NULL; 307 new_stat->dev = NULL;
@@ -312,7 +312,7 @@ static int dropmon_net_event(struct notifier_block *ev_block,
312 } 312 }
313 } 313 }
314 } 314 }
315 spin_unlock(&trace_state_lock); 315 mutex_unlock(&trace_state_mutex);
316 break; 316 break;
317 } 317 }
318out: 318out: