s/get_module_symbol/inter_module_xxx/ in MTD CVS.

Keith Owens kaos at ocs.com.au
Thu Nov 16 15:20:27 EST 2000


On Thu, 16 Nov 2000 13:21:24 +0000 (GMT), 
Alan Cox <alan at lxorguk.ukuu.org.uk> wrote:
>> Alan - please could you consider Keith's patch for 2.2.next, because its
>> impact is fairly limited - it shouldn't break anything and it's important 
>> for backwards-compatibility of 2.4 drivers. 
>
>If Keith submits it. 

I sent it to you last week.  Here it is again, against 2.2.18-pre21.

Index: 18-pre21.1/kernel/module.c
--- 18-pre21.1/kernel/module.c Fri, 05 May 2000 00:28:16 +1000 kaos (linux-2.2/h/18_module.c 1.1.9.1 644)
+++ 18-pre21.1(w)/kernel/module.c Mon, 13 Nov 2000 22:29:46 +1100 kaos (linux-2.2/h/18_module.c 1.1.9.1 644)
@@ -6,6 +6,8 @@
 #include <linux/smp_lock.h>
 #include <asm/pgtable.h>
 #include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
 
 /*
  * Originally by Anonymous (as far as I know...)
@@ -14,11 +16,12 @@
  * Heavily modified by Bjorn Ekwall <bj0rn at blox.se> May 1994 (C)
  * Rewritten by Richard Henderson <rth at tamu.edu> Dec 1996
  * Add MOD_INITIALIZING Keith Owens <kaos at ocs.com.au> Nov 1999
+ * Backport inter_module_xxx from 2.4.  Keith Owens <kaos at ocs.com.au> Oct 2000
  *
  * This source is covered by the GNU GPL, the same as all kernel sources.
  */
 
-#ifdef CONFIG_MODULES		/* a *big* #ifdef block... */
+#ifdef CONFIG_MODULES
 
 extern struct module_symbol __start___ksymtab[];
 extern struct module_symbol __stop___ksymtab[];
@@ -47,6 +50,173 @@ static struct module kernel_module =
 };
 
 struct module *module_list = &kernel_module;
+
+#endif	/* CONFIG_MODULES */
+
+/* inter_module functions are always available, even when the kernel is
+ * compiled without modules.  Consumers of inter_module_xxx routines
+ * will always work, even when both are built into the kernel, this
+ * approach removes lots of #ifdefs in mainline code.
+ */
+
+static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
+static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;
+static int kmalloc_failed;
+
+/**
+ * inter_module_register - register a new set of inter module data.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ * @owner: module that is registering the data, always use THIS_MODULE
+ * @userdata: pointer to arbitrary userdata to be registered
+ *
+ * Description: Check that the im_name has not already been registered,
+ * complain if it has.  For new data, add it to the inter_module_entry
+ * list.
+ */
+void inter_module_register(const char *im_name, struct module *owner, const void *userdata)
+{
+	struct list_head *tmp;
+	struct inter_module_entry *ime, *ime_new;
+
+	if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
+		/* Overloaded kernel, not fatal */
+		printk(KERN_ERR
+			"Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
+			im_name);
+		kmalloc_failed = 1;
+		return;
+	}
+	memset(ime_new, 0, sizeof(*ime_new));
+	ime_new->im_name = im_name;
+	ime_new->owner = owner;
+	ime_new->userdata = userdata;
+
+	spin_lock(&ime_lock);
+	list_for_each(tmp, &ime_list) {
+		ime = list_entry(tmp, struct inter_module_entry, list);
+		if (strcmp(ime->im_name, im_name) == 0) {
+			spin_unlock(&ime_lock);
+			kfree(ime_new);
+			/* Program logic error, fatal */
+			panic("inter_module_register: duplicate im_name '%s'", im_name);
+		}
+	}
+	list_add(&(ime_new->list), &ime_list);
+	spin_unlock(&ime_lock);
+}
+
+/**
+ * inter_module_unregister - unregister a set of inter module data.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ *
+ * Description: Check that the im_name has been registered, complain if
+ * it has not.  For existing data, remove it from the
+ * inter_module_entry list.
+ */
+void inter_module_unregister(const char *im_name)
+{
+	struct list_head *tmp;
+	struct inter_module_entry *ime;
+
+	spin_lock(&ime_lock);
+	list_for_each(tmp, &ime_list) {
+		ime = list_entry(tmp, struct inter_module_entry, list);
+		if (strcmp(ime->im_name, im_name) == 0) {
+			list_del(&(ime->list));
+			spin_unlock(&ime_lock);
+			kfree(ime);
+			return;
+		}
+	}
+	spin_unlock(&ime_lock);
+	if (kmalloc_failed) {
+		printk(KERN_ERR
+			"inter_module_unregister: no entry for '%s', "
+			"probably caused by previous kmalloc failure\n",
+			im_name);
+		return;
+	}
+	else {
+		/* Program logic error, fatal */
+		panic("inter_module_unregister: no entry for '%s'", im_name);
+	}
+}
+
+/**
+ * inter_module_get - return arbitrary userdata from another module.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ *
+ * Description: If the im_name has not been registered, return NULL.
+ * Try to increment the use count on the owning module, if that fails
+ * then return NULL.  Otherwise return the userdata.
+ */
+const void *inter_module_get(const char *im_name)
+{
+	struct list_head *tmp;
+	struct inter_module_entry *ime;
+	const void *result = NULL;
+
+	spin_lock(&ime_lock);
+	list_for_each(tmp, &ime_list) {
+		ime = list_entry(tmp, struct inter_module_entry, list);
+		if (strcmp(ime->im_name, im_name) == 0) {
+			/* This should be try_inc_use_count but that function is
+			 * not in 2.2 kernels.  I am not opening that can of worms
+			 * for 2.2.  Keith Owens
+			 */
+			__MOD_INC_USE_COUNT(ime->owner);
+			result = ime->userdata;
+			break;
+		}
+	}
+	spin_unlock(&ime_lock);
+	return(result);
+}
+
+/**
+ * inter_module_get_request - im get with automatic request_module.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ * @modname: module that is expected to register im_name
+ *
+ * Description: If inter_module_get fails, do request_module then retry.
+ */
+const void *inter_module_get_request(const char *im_name, const char *modname)
+{
+	const void *result = inter_module_get(im_name);
+	if (!result) {
+		request_module(modname);
+		result = inter_module_get(im_name);
+	}
+	return(result);
+}
+
+/**
+ * inter_module_put - release use of data from another module.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ *
+ * Description: If the im_name has not been registered, complain,
+ * otherwise decrement the use count on the owning module.
+ */
+void inter_module_put(const char *im_name)
+{
+	struct list_head *tmp;
+	struct inter_module_entry *ime;
+
+	spin_lock(&ime_lock);
+	list_for_each(tmp, &ime_list) {
+		ime = list_entry(tmp, struct inter_module_entry, list);
+		if (strcmp(ime->im_name, im_name) == 0) {
+			if (ime->owner)
+				__MOD_DEC_USE_COUNT(ime->owner);
+			spin_unlock(&ime_lock);
+			return;
+		}
+	}
+	spin_unlock(&ime_lock);
+	panic("inter_module_put: no entry for '%s'", im_name);
+}
+
+#if defined(CONFIG_MODULES)	/* The rest of the source */
 
 static long get_mod_name(const char *user_name, char **buf);
 static void put_mod_name(char *buf);
Index: 18-pre21.1/kernel/ksyms.c
--- 18-pre21.1/kernel/ksyms.c Wed, 08 Nov 2000 11:39:15 +1100 kaos (linux-2.2/h/19_ksyms.c 1.2.1.3.3.1.3.1.1.1.1.5.1.2 644)
+++ 18-pre21.1(w)/kernel/ksyms.c Mon, 13 Nov 2000 22:19:34 +1100 kaos (linux-2.2/h/19_ksyms.c 1.2.1.3.3.1.3.1.1.1.1.5.1.2 644)
@@ -82,6 +82,11 @@ EXPORT_SYMBOL(hotplug_path);
 #ifdef CONFIG_MODULES
 EXPORT_SYMBOL(get_module_symbol);
 #endif
+EXPORT_SYMBOL(inter_module_register);
+EXPORT_SYMBOL(inter_module_unregister);
+EXPORT_SYMBOL(inter_module_get);
+EXPORT_SYMBOL(inter_module_get_request);
+EXPORT_SYMBOL(inter_module_put);
 EXPORT_SYMBOL(get_options);
 
 /* process memory management */
Index: 18-pre21.1/include/linux/module.h
--- 18-pre21.1/include/linux/module.h Tue, 12 Sep 2000 13:37:17 +1100 kaos (linux-2.2/F/51_module.h 1.1.7.2 644)
+++ 18-pre21.1(w)/include/linux/module.h Tue, 14 Nov 2000 00:04:33 +1100 kaos (linux-2.2/F/51_module.h 1.1.7.2 644)
@@ -8,6 +8,7 @@
 #define _LINUX_MODULE_H
 
 #include <linux/config.h>
+#include <linux/list.h>
 
 #ifdef __GENKSYMS__
 #  define _set_ver(sym) sym
@@ -140,6 +141,35 @@ struct module_info
 
 #define __MODULE_STRING_1(x)	#x
 #define __MODULE_STRING(x)	__MODULE_STRING_1(x)
+
+/* Generic inter module communication.
+ *
+ * NOTE: This interface is intended for small amounts of data that are
+ *       passed between two objects and either or both of the objects
+ *       might be compiled as modules.  Do not over use this interface.
+ *
+ *       If more than two objects need to communicate then you probably
+ *       need a specific interface instead of abusing this generic
+ *       interface.  If both objects are *always* built into the kernel
+ *       then a global extern variable is good enough, you do not need
+ *       this interface.
+ *
+ * Keith Owens <kaos at ocs.com.au> 28 Oct 2000.
+ */
+
+#define HAVE_INTER_MODULE
+extern void inter_module_register(const char *, struct module *, const void *);
+extern void inter_module_unregister(const char *);
+extern const void *inter_module_get(const char *);
+extern const void *inter_module_get_request(const char *, const char *);
+extern void inter_module_put(const char *);
+
+struct inter_module_entry {
+       struct list_head list;
+       const char *im_name;
+       struct module *owner;
+       const void *userdata;
+};
 
 /* Find a symbol exported by the kernel or another module */
 #ifndef CONFIG_MODULES
Index: 18-pre21.1/Makefile
--- 18-pre21.1/Makefile Fri, 10 Nov 2000 22:07:33 +1100 kaos (linux-2.2/G/b/14_Makefile 1.3.2.2.1.1.1.5.1.3.6.1.5.1.1.1.1.16.1.6 644)
+++ 18-pre21.1(w)/Makefile Tue, 14 Nov 2000 00:13:18 +1100 kaos (linux-2.2/G/b/14_Makefile 1.3.2.2.1.1.1.5.1.3.6.1.5.1.1.1.1.16.1.6 644)
@@ -241,7 +241,7 @@ vmlinux: $(CONFIGURATION) init/main.o in
 		$(LIBS) \
 		--end-group \
 		-o vmlinux
-	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
+	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
 
 symlinks:
 	rm -f include/asm



To unsubscribe, send "unsubscribe mtd" to majordomo at infradead.org



More information about the linux-mtd mailing list