Linux Kernel Markers: fix marker mutex not taken upon module load

Upon module load, we must take the markers mutex.  It implies that the marker
mutex must be nested inside the module mutex.

It implies changing the nesting order : now the marker mutex nests inside the
module mutex.  Make the necessary changes to reverse the order in which the
mutexes are taken.

Includes some cleanup from Dave Hansen <haveblue@us.ibm.com>.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Mathieu Desnoyers 2007-11-14 16:59:48 -08:00 committed by Linus Torvalds
parent f433dc5634
commit 314de8a9e1

View file

@ -28,7 +28,7 @@ extern struct marker __start___markers[];
extern struct marker __stop___markers[]; extern struct marker __stop___markers[];
/* /*
* module_mutex nests inside markers_mutex. Markers mutex protects the builtin * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
* and module markers, the hash table and deferred_sync. * and module markers, the hash table and deferred_sync.
*/ */
static DEFINE_MUTEX(markers_mutex); static DEFINE_MUTEX(markers_mutex);
@ -257,7 +257,6 @@ static void disable_marker(struct marker *elem)
* @refcount: number of references left to the given probe_module (out) * @refcount: number of references left to the given probe_module (out)
* *
* Updates the probe callback corresponding to a range of markers. * Updates the probe callback corresponding to a range of markers.
* Must be called with markers_mutex held.
*/ */
void marker_update_probe_range(struct marker *begin, void marker_update_probe_range(struct marker *begin,
struct marker *end, struct module *probe_module, struct marker *end, struct module *probe_module,
@ -266,6 +265,7 @@ void marker_update_probe_range(struct marker *begin,
struct marker *iter; struct marker *iter;
struct marker_entry *mark_entry; struct marker_entry *mark_entry;
mutex_lock(&markers_mutex);
for (iter = begin; iter < end; iter++) { for (iter = begin; iter < end; iter++) {
mark_entry = get_marker(iter->name); mark_entry = get_marker(iter->name);
if (mark_entry && mark_entry->refcount) { if (mark_entry && mark_entry->refcount) {
@ -281,6 +281,7 @@ void marker_update_probe_range(struct marker *begin,
disable_marker(iter); disable_marker(iter);
} }
} }
mutex_unlock(&markers_mutex);
} }
/* /*
@ -293,7 +294,6 @@ static void marker_update_probes(struct module *probe_module)
{ {
int refcount = 0; int refcount = 0;
mutex_lock(&markers_mutex);
/* Core kernel markers */ /* Core kernel markers */
marker_update_probe_range(__start___markers, marker_update_probe_range(__start___markers,
__stop___markers, probe_module, &refcount); __stop___markers, probe_module, &refcount);
@ -303,7 +303,6 @@ static void marker_update_probes(struct module *probe_module)
synchronize_sched(); synchronize_sched();
deferred_sync = 0; deferred_sync = 0;
} }
mutex_unlock(&markers_mutex);
} }
/** /**
@ -320,7 +319,7 @@ int marker_probe_register(const char *name, const char *format,
marker_probe_func *probe, void *private) marker_probe_func *probe, void *private)
{ {
struct marker_entry *entry; struct marker_entry *entry;
int ret = 0, need_update = 0; int ret = 0;
mutex_lock(&markers_mutex); mutex_lock(&markers_mutex);
entry = get_marker(name); entry = get_marker(name);
@ -335,11 +334,11 @@ int marker_probe_register(const char *name, const char *format,
ret = add_marker(name, format, probe, private); ret = add_marker(name, format, probe, private);
if (ret) if (ret)
goto end; goto end;
need_update = 1; mutex_unlock(&markers_mutex);
marker_update_probes(NULL);
return ret;
end: end:
mutex_unlock(&markers_mutex); mutex_unlock(&markers_mutex);
if (need_update)
marker_update_probes(NULL);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(marker_probe_register); EXPORT_SYMBOL_GPL(marker_probe_register);
@ -355,7 +354,6 @@ void *marker_probe_unregister(const char *name)
struct module *probe_module; struct module *probe_module;
struct marker_entry *entry; struct marker_entry *entry;
void *private; void *private;
int need_update = 0;
mutex_lock(&markers_mutex); mutex_lock(&markers_mutex);
entry = get_marker(name); entry = get_marker(name);
@ -368,11 +366,11 @@ void *marker_probe_unregister(const char *name)
probe_module = __module_text_address((unsigned long)entry->probe); probe_module = __module_text_address((unsigned long)entry->probe);
private = remove_marker(name); private = remove_marker(name);
deferred_sync = 1; deferred_sync = 1;
need_update = 1; mutex_unlock(&markers_mutex);
marker_update_probes(probe_module);
return private;
end: end:
mutex_unlock(&markers_mutex); mutex_unlock(&markers_mutex);
if (need_update)
marker_update_probes(probe_module);
return private; return private;
} }
EXPORT_SYMBOL_GPL(marker_probe_unregister); EXPORT_SYMBOL_GPL(marker_probe_unregister);
@ -392,7 +390,6 @@ void *marker_probe_unregister_private_data(void *private)
struct marker_entry *entry; struct marker_entry *entry;
int found = 0; int found = 0;
unsigned int i; unsigned int i;
int need_update = 0;
mutex_lock(&markers_mutex); mutex_lock(&markers_mutex);
for (i = 0; i < MARKER_TABLE_SIZE; i++) { for (i = 0; i < MARKER_TABLE_SIZE; i++) {
@ -414,11 +411,11 @@ void *marker_probe_unregister_private_data(void *private)
probe_module = __module_text_address((unsigned long)entry->probe); probe_module = __module_text_address((unsigned long)entry->probe);
private = remove_marker(entry->name); private = remove_marker(entry->name);
deferred_sync = 1; deferred_sync = 1;
need_update = 1; mutex_unlock(&markers_mutex);
marker_update_probes(probe_module);
return private;
end: end:
mutex_unlock(&markers_mutex); mutex_unlock(&markers_mutex);
if (need_update)
marker_update_probes(probe_module);
return private; return private;
} }
EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data); EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
@ -434,7 +431,7 @@ EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
int marker_arm(const char *name) int marker_arm(const char *name)
{ {
struct marker_entry *entry; struct marker_entry *entry;
int ret = 0, need_update = 0; int ret = 0;
mutex_lock(&markers_mutex); mutex_lock(&markers_mutex);
entry = get_marker(name); entry = get_marker(name);
@ -447,11 +444,9 @@ int marker_arm(const char *name)
*/ */
if (entry->refcount++) if (entry->refcount++)
goto end; goto end;
need_update = 1;
end: end:
mutex_unlock(&markers_mutex); mutex_unlock(&markers_mutex);
if (need_update) marker_update_probes(NULL);
marker_update_probes(NULL);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(marker_arm); EXPORT_SYMBOL_GPL(marker_arm);
@ -467,7 +462,7 @@ EXPORT_SYMBOL_GPL(marker_arm);
int marker_disarm(const char *name) int marker_disarm(const char *name)
{ {
struct marker_entry *entry; struct marker_entry *entry;
int ret = 0, need_update = 0; int ret = 0;
mutex_lock(&markers_mutex); mutex_lock(&markers_mutex);
entry = get_marker(name); entry = get_marker(name);
@ -486,11 +481,9 @@ int marker_disarm(const char *name)
ret = -EPERM; ret = -EPERM;
goto end; goto end;
} }
need_update = 1;
end: end:
mutex_unlock(&markers_mutex); mutex_unlock(&markers_mutex);
if (need_update) marker_update_probes(NULL);
marker_update_probes(NULL);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(marker_disarm); EXPORT_SYMBOL_GPL(marker_disarm);