Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2030

kernel-2.6.18-238.el5.src.rpm

From: jbaron@redhat.com <jbaron@redhat.com>
Date: Fri, 22 Aug 2008 14:04:56 -0400
Subject: [misc] markers and tracepoints: kabi fix-up patch
Message-id: 1219428298-7519-13-git-send-email-jbaron@redhat.com
O-Subject: [rhel5.3 patch 12/14] markers and tracepoints - kabi fix-up patch
Bugzilla: 329821

bz# 329821

diff --git a/include/linux/module.h b/include/linux/module.h
index 14f1add..e511aad 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -355,14 +355,6 @@ struct module
 	/* The command line arguments (may be mangled).  People like
 	   keeping pointers to this stuff */
 	char *args;
-#ifdef CONFIG_TRACEPOINTS
-	struct tracepoint *tracepoints;
-	unsigned int num_tracepoints;
-#endif
-#ifdef CONFIG_MARKERS
-	struct marker *markers;
-	unsigned int num_markers;
-#endif
 };
 
 /* FIXME: It'd be nice to isolate modules during init, too, so they
diff --git a/kernel/module.c b/kernel/module.c
index 6cf428e..cfa1f20 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -67,6 +67,98 @@ static DEFINE_SPINLOCK(modlist_lock);
 static DEFINE_MUTEX(module_mutex);
 static LIST_HEAD(modules);
 
+#ifdef CONFIG_MARKERS
+struct module_marker_data
+{
+	struct list_head list;
+	struct module *mod;
+	struct marker *markers;
+	unsigned int num_markers;
+};
+
+/* List of module marker data, protected by module_mutex */
+static LIST_HEAD(marker_data_list);
+
+/* This function only gets called from load_module(), which is
+ * protected by module_mutex. */
+static int marker_data_add(struct module *mod, struct marker *markers,
+       unsigned int num_markers)
+{
+	struct module_marker_data *data;
+
+	data = kmalloc(sizeof(struct module_marker_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->mod = mod;
+	data->markers = markers;
+	data->num_markers = num_markers;
+	list_add(&data->list, &marker_data_list);
+	return 1;
+}
+
+/* This function is called from free_module() and load_module().  Both are
+ * protected by module_mutex. */
+static void marker_data_del(struct module *mod)
+{
+	struct module_marker_data *data;
+
+	list_for_each_entry(data, &marker_data_list, list) {
+		if (mod == data->mod) {
+			list_del(&data->list);
+			kfree(data);
+			break;
+               }
+       }
+}
+#endif
+
+#ifdef CONFIG_TRACEPOINTS
+struct module_tracepoint_data
+{
+	struct list_head list;
+	struct module *mod;
+	struct tracepoint *tracepoints;
+	unsigned int num_tracepoints;
+};
+
+/* List of module marker data, protected by module_mutex */
+static LIST_HEAD(tracepoint_data_list);
+
+/* This function only gets called from load_module(), which is
+ * protected by module_mutex. */
+static int tracepoint_data_add(struct module *mod, struct tracepoint *tracepoints,
+       unsigned int num_tracepoints)
+{
+	struct module_tracepoint_data *data;
+
+	data = kmalloc(sizeof(struct module_tracepoint_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->mod = mod;
+	data->tracepoints = tracepoints;
+	data->num_tracepoints = num_tracepoints;
+	list_add(&data->list, &tracepoint_data_list);
+	return 1;
+}
+
+/* This function is called from free_module() and load_module().  Both are
+ * protected by module_mutex. */
+static void tracepoint_data_del(struct module *mod)
+{
+	struct module_tracepoint_data *data;
+
+	list_for_each_entry(data, &tracepoint_data_list, list) {
+		if (mod == data->mod) {
+			list_del(&data->list);
+			kfree(data);
+			break;
+               }
+       }
+}
+#endif
+
 static BLOCKING_NOTIFIER_HEAD(module_notify_list);
 
 int register_module_notifier(struct notifier_block * nb)
@@ -1151,6 +1243,12 @@ static void free_module(struct module *mod)
 	/* Delete from various lists */
 	stop_machine_run(__unlink_module, mod, NR_CPUS);
 	remove_sect_attrs(mod);
+#ifdef CONFIG_MARKERS
+	marker_data_del(mod);
+#endif
+#ifdef CONFIG_TRACEPOINTS
+	tracepoint_data_del(mod);
+#endif
 	mod_kobject_remove(mod);
 
 	unwind_remove_table(mod->unwind_info, 0);
@@ -1537,7 +1635,16 @@ static struct module *load_module(void __user *umod,
 	struct exception_table_entry *extable;
 	mm_segment_t old_fs;
 	int gpgsig_ok;
-
+#ifdef CONFIG_MARKERS
+	struct marker *markers = NULL;
+	unsigned int num_markers = 0;
+	int marker_data_added = 0;
+#endif
+#ifdef CONFIG_TRACEPOINTS
+	struct tracepoint *tracepoints = NULL;
+	unsigned int num_tracepoints = 0;
+	int tracepoint_data_added = 0;
+#endif
 	DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
 	       umod, len, uargs);
 	if (len < sizeof(*hdr))
@@ -1811,14 +1918,16 @@ static struct module *load_module(void __user *umod,
 	}
 #endif
 #ifdef CONFIG_TRACEPOINTS
-	mod->tracepoints = (void *)sechdrs[tracepointsindex].sh_addr;
-	mod->num_tracepoints =
-		sechdrs[tracepointsindex].sh_size / sizeof(*mod->tracepoints);
+	if (tracepointsindex != 0) {
+		tracepoints = (void *)sechdrs[tracepointsindex].sh_addr;
+		num_tracepoints = sechdrs[tracepointsindex].sh_size / sizeof(*tracepoints);
+	}
 #endif
 #ifdef CONFIG_MARKERS
-	mod->markers = (void *)sechdrs[markersindex].sh_addr;
-	mod->num_markers =
-		sechdrs[markersindex].sh_size / sizeof(*mod->markers);
+	if (markersindex != 0) {
+		markers = (void *)sechdrs[markersindex].sh_addr;
+		num_markers = sechdrs[markersindex].sh_size / sizeof(*markers);
+	}
 #endif
 
 	/* Now do relocations. */
@@ -1861,12 +1970,24 @@ static struct module *load_module(void __user *umod,
 	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
 
 #ifdef CONFIG_TRACEPOINTS
-		tracepoint_update_probe_range(mod->tracepoints,
-			mod->tracepoints + mod->num_tracepoints);
+	if (tracepointsindex != 0) {
+		err = tracepoint_data_add(mod, tracepoints, num_tracepoints);
+		if (err < 0)
+			goto cleanup;
+		tracepoint_data_added = 1;
+		tracepoint_update_probe_range(tracepoints,
+			tracepoints + num_tracepoints);
+	}
 #endif
 #ifdef CONFIG_MARKERS
-	marker_update_probe_range(mod->markers,
-		mod->markers + mod->num_markers);
+	if (markersindex != 0) {
+		err = marker_data_add(mod, markers, num_markers);
+		if (err < 0)
+			goto cleanup;
+		marker_data_added = 1;
+		marker_update_probe_range(markers,
+			markers + num_markers);
+	}
 #endif
 	err = module_finalize(hdr, sechdrs, mod);
 	if (err < 0)
@@ -1928,6 +2049,14 @@ static struct module *load_module(void __user *umod,
  arch_cleanup:
 	module_arch_cleanup(mod);
  cleanup:
+#ifdef CONFIG_MARKERS
+	if (marker_data_added)
+		marker_data_del(mod);
+#endif
+#ifdef CONFIG_TRACEPOINTS
+	if (tracepoint_data_added)
+		tracepoint_data_del(mod);
+#endif
 	module_unload_free(mod);
 	module_free(mod, mod->module_init);
  free_core:
@@ -2365,12 +2494,12 @@ EXPORT_SYMBOL(struct_module);
 #ifdef CONFIG_TRACEPOINTS
 void module_update_tracepoints(void)
 {
-	struct module *mod;
+	struct module_tracepoint_data *data;
 
 	mutex_lock(&module_mutex);
-	list_for_each_entry(mod, &modules, list)
-			tracepoint_update_probe_range(mod->tracepoints,
-				mod->tracepoints + mod->num_tracepoints);
+	list_for_each_entry(data, &tracepoint_data_list, list)
+		tracepoint_update_probe_range(data->tracepoints,
+			data->tracepoints + data->num_tracepoints);
 	mutex_unlock(&module_mutex);
 }
 
@@ -2380,24 +2509,24 @@ void module_update_tracepoints(void)
  */
 int module_get_iter_tracepoints(struct tracepoint_iter *iter)
 {
-	struct module *iter_mod;
+	struct module_tracepoint_data *iter_mod;
 	int found = 0;
 
 	mutex_lock(&module_mutex);
-	list_for_each_entry(iter_mod, &modules, list) {
+	list_for_each_entry(iter_mod, &tracepoint_data_list, list) {
 		/*
 		 * Sorted module list
 		 */
-		if (iter_mod < iter->module)
+		if (iter_mod->mod < iter->module)
 			continue;
-		else if (iter_mod > iter->module)
+		else if (iter_mod->mod > iter->module)
 			iter->tracepoint = NULL;
 		found = tracepoint_get_iter_range(&iter->tracepoint,
 			iter_mod->tracepoints,
 			iter_mod->tracepoints
 				+ iter_mod->num_tracepoints);
 		if (found) {
-			iter->module = iter_mod;
+			iter->module = iter_mod->mod;
 			break;
 		}
 	}
@@ -2409,12 +2538,12 @@ int module_get_iter_tracepoints(struct tracepoint_iter *iter)
 #ifdef CONFIG_MARKERS
 void module_update_markers(void)
 {
-	struct module *mod;
+	struct module_marker_data *data;
 
 	mutex_lock(&module_mutex);
-	list_for_each_entry(mod, &modules, list)
-		marker_update_probe_range(mod->markers,
-			mod->markers + mod->num_markers);
+	list_for_each_entry(data, &marker_data_list, list)
+		marker_update_probe_range(data->markers,
+			data->markers + data->num_markers);
 	mutex_unlock(&module_mutex);
 }
 #endif