Add documentation to the module.c marker functions. Update them to
follow the flags modifications.

Signed-off-by: Mathieu Desnoyers <[EMAIL PROTECTED]>

--- a/kernel/module.c
+++ b/kernel/module.c
@@ -303,24 +303,36 @@ static struct module *find_module(const char *name)
 }
 
 #ifdef CONFIG_MARKERS
-void __mark_empty_function(const char *fmt, ...)
+
+/* Empty callback provided as a probe to the markers. By providing this to a
+ * disabled marker, we makes sure the  execution flow is always valid even
+ * though the function pointer change and the marker enabling are two distinct
+ * operations that modifies the execution flow of preemptible code. */
+void __mark_empty_function(const struct __mark_marker_data *mdata,
+       const char *fmt, ...)
 {
 }
 EXPORT_SYMBOL_GPL(__mark_empty_function);
 
+/* Set the enable bit of the marker, choosing the generic or architecture
+ * specific functions depending on the marker's flags.
+ */
 static int marker_set_enable(void *address, char enable, int flags)
 {
-       if (flags & _MF_OPTIMIZED)
+       if (flags & MF_OPTIMIZED)
                return marker_optimized_set_enable(address, enable);
        else
                return marker_generic_set_enable(address, enable);
 }
 
-/* enable and function address are set out of order, and it's ok :
- * the state is always coherent. */
+/* Sets the probe callback and enables the markers corresponding to a range of
+ * markers. The enable bit and function address are set out of order, and it's
+ * ok : the state is always coherent because of the empty callback we provide.
+ */
 static int _marker_set_probe_range(int flags, const char *name,
        const char *format,
        marker_probe_func *probe,
+       void *pdata,
        const struct __mark_marker *begin,
        const struct __mark_marker *end)
 {
@@ -328,27 +340,27 @@ static int _marker_set_probe_range(int flags, const char 
*name,
        int found = 0;
 
        for (iter = begin; iter < end; iter++) {
-               if (strcmp(name, iter->cmark->name) == 0) {
+               if (strcmp(name, iter->mdata->name) == 0) {
                        if (format
-                               && strcmp(format, iter->cmark->format) != 0) {
+                               && strcmp(format, iter->mdata->format) != 0) {
                                printk(KERN_NOTICE
                                        "Format mismatch for probe %s "
                                        "(%s), marker (%s)\n",
                                        name,
                                        format,
-                                       iter->cmark->format);
+                                       iter->mdata->format);
                                continue;
                        }
-                       if (flags & _MF_LOCKDEP
-                               && !(iter->cmark->flags & _MF_LOCKDEP)) {
+                       if (flags & MF_LOCKDEP
+                               && !(iter->mdata->flags & MF_LOCKDEP)) {
                                        printk(KERN_NOTICE
                                        "Incompatible lockdep flags for "
                                        "probe %s\n",
                                        name);
                                        continue;
                        }
-                       if (flags & _MF_PRINTK
-                               && !(iter->cmark->flags & _MF_PRINTK)) {
+                       if (flags & MF_PRINTK
+                               && !(iter->mdata->flags & MF_PRINTK)) {
                                        printk(KERN_NOTICE
                                        "Incompatible printk flags for "
                                        "probe %s\n",
@@ -356,32 +368,33 @@ static int _marker_set_probe_range(int flags, const char 
*name,
                                        continue;
                        }
                        if (probe == __mark_empty_function) {
-                               if (*iter->cmark->call
+                               if (iter->mdata->call
                                        != __mark_empty_function) {
-                                       *iter->cmark->call =
+                                       iter->mdata->call =
                                                __mark_empty_function;
                                }
                                marker_set_enable(iter->enable, 0,
-                                       iter->cmark->flags);
+                                       iter->mdata->flags);
                        } else {
-                               if (*iter->cmark->call
+                               if (iter->mdata->call
                                        != __mark_empty_function) {
-                                       if (*iter->cmark->call != probe) {
+                                       if (iter->mdata->call != probe) {
                                                printk(KERN_NOTICE
                                                        "Marker %s busy, "
                                                        "probe %p already "
                                                        "installed\n",
                                                        name,
-                                                       *iter->cmark->call);
+                                                       iter->mdata->call);
                                                continue;
                                        }
                                } else {
                                        found++;
-                                       *iter->cmark->call = probe;
+                                       iter->mdata->call = probe;
                                }
-                               /* Can have many enables for one function */
+                               iter->mdata->pdata = pdata;
+                               smp_wmb();
                                marker_set_enable(iter->enable, 1,
-                                       iter->cmark->flags);
+                                       iter->mdata->flags);
                        }
                        found++;
                }
@@ -389,7 +402,9 @@ static int _marker_set_probe_range(int flags, const char 
*name,
        return found;
 }
 
-static int marker_remove_probe_range(marker_probe_func *probe,
+/* Sets a range of markers to a disabled state : unset the enable bit and
+ * provide the empty callback. */
+static int marker_remove_probe_range(const char *name,
        const struct __mark_marker *begin,
        const struct __mark_marker *end)
 {
@@ -397,16 +412,19 @@ static int marker_remove_probe_range(marker_probe_func 
*probe,
        int found = 0;
 
        for (iter = begin; iter < end; iter++) {
-               if (*iter->cmark->call == probe) {
+               if (strcmp(name, iter->mdata->name) == 0) {
                        marker_set_enable(iter->enable, 0,
-                               iter->cmark->flags);
-                       *iter->cmark->call = __mark_empty_function;
+                               iter->mdata->flags);
+                       iter->mdata->call = __mark_empty_function;
                        found++;
                }
        }
        return found;
 }
 
+/* Provides a listing of the markers present in the kernel with their type
+ * (optimized or generic), state (enabled or disabled), callback and format
+ * string. */
 static int marker_list_probe_range(marker_probe_func *probe,
        const struct __mark_marker *begin,
        const struct __mark_marker *end)
@@ -416,23 +434,26 @@ static int marker_list_probe_range(marker_probe_func 
*probe,
 
        for (iter = begin; iter < end; iter++) {
                if (probe)
-                       if (probe != *iter->cmark->call) continue;
-               printk("name %s \n", iter->cmark->name);
-               if (iter->cmark->flags & _MF_OPTIMIZED)
+                       if (probe != iter->mdata->call) continue;
+               printk("name %s \n", iter->mdata->name);
+               if (iter->mdata->flags & MF_OPTIMIZED)
                        printk("  enable %u optimized ",
                                MARK_OPTIMIZED_ENABLE(iter->enable));
                else
                        printk("  enable %u generic ",
                                MARK_GENERIC_ENABLE(iter->enable));
                printk("  func 0x%p format \"%s\"\n",
-                       *iter->cmark->call, iter->cmark->format);
+                       iter->mdata->call, iter->mdata->format);
                found++;
        }
        return found;
 }
-/* markers use the modlist_lock to to synchronise */
+
+/* Calls _marker_set_probe_range for the core markers and modules markers.
+ * Marker enabling/disabling use the modlist_lock to synchronise. */
 int _marker_set_probe(int flags, const char *name, const char *format,
-                               marker_probe_func *probe)
+                               marker_probe_func *probe,
+                               void *pdata)
 {
        struct module *mod;
        int found = 0;
@@ -440,31 +461,35 @@ int _marker_set_probe(int flags, const char *name, const 
char *format,
        mutex_lock(&module_mutex);
        /* Core kernel markers */
        found += _marker_set_probe_range(flags, name, format, probe,
+                       pdata,
                        __start___markers, __stop___markers);
        /* Markers in modules. */
        list_for_each_entry(mod, &modules, list) {
                if (!mod->taints)
                        found += _marker_set_probe_range(flags, name, format,
-                       probe, mod->markers, mod->markers+mod->num_markers);
+                       probe, pdata,
+                       mod->markers, mod->markers+mod->num_markers);
        }
        mutex_unlock(&module_mutex);
        return found;
 }
 EXPORT_SYMBOL_GPL(_marker_set_probe);
 
-int marker_remove_probe(marker_probe_func *probe)
+/* Calls _marker_remove_probe_range for the core markers and modules markers.
+ * Marker enabling/disabling use the modlist_lock to synchronise. */
+int marker_remove_probe(const char *name)
 {
        struct module *mod;
        int found = 0;
 
        mutex_lock(&module_mutex);
        /* Core kernel markers */
-       found += marker_remove_probe_range(probe,
+       found += marker_remove_probe_range(name,
                        __start___markers, __stop___markers);
        /* Markers in modules. */
        list_for_each_entry(mod, &modules, list) {
                if (!mod->taints)
-                       found += marker_remove_probe_range(probe,
+                       found += marker_remove_probe_range(name,
                                mod->markers, mod->markers+mod->num_markers);
        }
        mutex_unlock(&module_mutex);
@@ -472,6 +497,9 @@ int marker_remove_probe(marker_probe_func *probe)
 }
 EXPORT_SYMBOL_GPL(marker_remove_probe);
 
+/* Calls _marker_list_probe_range for the core markers and modules markers.
+ * Marker listing uses the modlist_lock to synchronise.
+ * TODO : should output this listing to a procfs file. */
 int marker_list_probe(marker_probe_func *probe)
 {
        struct module *mod;
@@ -1856,6 +1886,8 @@ static struct module *load_module(void __user *umod,
        unsigned int unusedgplindex;
        unsigned int unusedgplcrcindex;
        unsigned int markersindex;
+       unsigned int markersdataindex;
+       unsigned int markersstringsindex;
        struct module *mod;
        long err = 0;
        void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1952,7 +1984,10 @@ static struct module *load_module(void __user *umod,
 #ifdef ARCH_UNWIND_SECTION_NAME
        unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME);
 #endif
-       markersindex = find_sec(hdr, sechdrs, secstrings, ".markers");
+       markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
+       markersdataindex = find_sec(hdr, sechdrs, secstrings, "__markers_data");
+       markersstringsindex = find_sec(hdr, sechdrs, secstrings,
+                               "__markers_strings");
 
        /* Don't keep modinfo section */
        sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
@@ -1966,9 +2001,18 @@ static struct module *load_module(void __user *umod,
 #ifdef CONFIG_MARKERS
        if (markersindex)
                sechdrs[markersindex].sh_flags |= SHF_ALLOC;
+       if (markersdataindex)
+               sechdrs[markersdataindex].sh_flags |= SHF_ALLOC;
+       if (markersstringsindex)
+               sechdrs[markersstringsindex].sh_flags |= SHF_ALLOC;
 #else
        if (markersindex)
                sechdrs[markersindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
+       if (markersdataindex)
+               sechdrs[markersdataindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
+       if (markersstringsindex)
+               sechdrs[markersstringsindex].sh_flags
+                                       &= ~(unsigned long)SHF_ALLOC;
 #endif
 
        /* Check module struct version now, before we try to use module. */
@@ -2622,7 +2668,7 @@ void list_modules(void)
 #ifdef CONFIG_MODULE_UNLOAD
                refcount = local_read(&mod->ref[0].count);
 #endif //CONFIG_MODULE_UNLOAD
-               MARK(list_modules, "%s %d[enum module_state] %lu",
+               MARK(list_module, "%s %d %lu",
                                mod->name, mod->state, refcount);
        }
        mutex_unlock(&module_mutex);
-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to