浏览代码

markers: fix unregister

Impact: fix marker registers/unregister race

get_marker() can return a NULL entry because the mutex is released in
the middle of those functions. Make sure we check to see if it has been
concurrently removed.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Mathieu Desnoyers 16 年之前
父节点
当前提交
2bdba316c9
共有 1 个文件被更改,包括 7 次插入5 次删除
  1. 7 5
      kernel/marker.c

+ 7 - 5
kernel/marker.c

@@ -653,10 +653,11 @@ int marker_probe_register(const char *name, const char *format,
 		goto end;
 		goto end;
 	}
 	}
 	mutex_unlock(&markers_mutex);
 	mutex_unlock(&markers_mutex);
-	marker_update_probes();		/* may update entry */
+	marker_update_probes();
 	mutex_lock(&markers_mutex);
 	mutex_lock(&markers_mutex);
 	entry = get_marker(name);
 	entry = get_marker(name);
-	WARN_ON(!entry);
+	if (!entry)
+		goto end;
 	if (entry->rcu_pending)
 	if (entry->rcu_pending)
 		rcu_barrier_sched();
 		rcu_barrier_sched();
 	entry->oldptr = old;
 	entry->oldptr = old;
@@ -697,7 +698,7 @@ int marker_probe_unregister(const char *name,
 		rcu_barrier_sched();
 		rcu_barrier_sched();
 	old = marker_entry_remove_probe(entry, probe, probe_private);
 	old = marker_entry_remove_probe(entry, probe, probe_private);
 	mutex_unlock(&markers_mutex);
 	mutex_unlock(&markers_mutex);
-	marker_update_probes();		/* may update entry */
+	marker_update_probes();
 	mutex_lock(&markers_mutex);
 	mutex_lock(&markers_mutex);
 	entry = get_marker(name);
 	entry = get_marker(name);
 	if (!entry)
 	if (!entry)
@@ -778,10 +779,11 @@ int marker_probe_unregister_private_data(marker_probe_func *probe,
 		rcu_barrier_sched();
 		rcu_barrier_sched();
 	old = marker_entry_remove_probe(entry, NULL, probe_private);
 	old = marker_entry_remove_probe(entry, NULL, probe_private);
 	mutex_unlock(&markers_mutex);
 	mutex_unlock(&markers_mutex);
-	marker_update_probes();		/* may update entry */
+	marker_update_probes();
 	mutex_lock(&markers_mutex);
 	mutex_lock(&markers_mutex);
 	entry = get_marker_from_private_data(probe, probe_private);
 	entry = get_marker_from_private_data(probe, probe_private);
-	WARN_ON(!entry);
+	if (!entry)
+		goto end;
 	if (entry->rcu_pending)
 	if (entry->rcu_pending)
 		rcu_barrier_sched();
 		rcu_barrier_sched();
 	entry->oldptr = old;
 	entry->oldptr = old;