Re: [PATCH] Make agpsupport work with modversions

From: David Woodhouse (dwmw2@infradead.org)
Date: Thu Oct 19 2000 - 03:25:09 EST


alan@lxorguk.ukuu.org.uk said:
> You need it to dynamically bind to another module if its loaded and
> still be loadable if that module/facility is not present. Its dynamic
> linking for kernel modules

However, in order for get_module_symbol() to be safe, it needs to
increase the use count of the module in which it finds the symbol, and the
corresponding put_module_symbol() function has to be provided. This was
done in 2.4 a while ago. Patch for 2.2 attached.

Index: kernel/ksyms.c
===================================================================
RCS file: /inst/cvs/linux/kernel/ksyms.c,v
retrieving revision 1.13
diff -u -r1.13 ksyms.c
--- kernel/ksyms.c 2000/10/16 09:43:22 1.13
+++ kernel/ksyms.c 2000/10/19 08:18:08
@@ -81,6 +81,7 @@
 
 #ifdef CONFIG_MODULES
 EXPORT_SYMBOL(get_module_symbol);
+EXPORT_SYMBOL(put_module_symbol);
 #endif
 EXPORT_SYMBOL(get_options);
 
Index: kernel/module.c
===================================================================
RCS file: /inst/cvs/linux/kernel/module.c,v
retrieving revision 1.2
diff -u -r1.2 module.c
--- kernel/module.c 2000/06/07 10:00:30 1.2
+++ kernel/module.c 2000/10/19 08:18:08
@@ -952,7 +952,9 @@
  * Gets the address for a symbol in the given module. If modname is
  * NULL, it looks for the name in any registered symbol table. If the
  * modname is an empty string, it looks for the symbol in kernel exported
- * symbol tables.
+ * symbol tables. Increase the usage count of the module in which the
+ * symbol was found - it's the only way we can guarantee that it's still
+ * there by the time our caller actually uses it.
  */
 unsigned long
 get_module_symbol(char *modname, char *symname)
@@ -969,12 +971,29 @@
                                 i > 0; --i, ++sym) {
 
                                 if (strcmp(sym->name, symname) == 0) {
+ __MOD_INC_USE_COUNT(mp);
                                         return sym->value;
                                 }
                         }
                 }
         }
         return 0;
+}
+
+/* Decrease the use count of the module containing a symbol with the
+ * address passed.
+ */
+void put_module_symbol(unsigned long addr)
+{
+ struct module *mp;
+
+ for (mp = module_list; mp; mp = mp->next) {
+ if (addr >= (unsigned long)mp &&
+ addr < (unsigned long)mp + mp->size) {
+ __MOD_DEC_USE_COUNT(mp);
+ return;
+ }
+ }
 }
 
 #else /* CONFIG_MODULES */
Index: include/linux/module.h
===================================================================
RCS file: /inst/cvs/linux/include/linux/module.h,v
retrieving revision 1.3
diff -u -r1.3 module.h
--- include/linux/module.h 2000/09/11 08:34:17 1.3
+++ include/linux/module.h 2000/10/19 08:19:48
@@ -144,8 +144,10 @@
 /* Find a symbol exported by the kernel or another module */
 #ifndef CONFIG_MODULES
 static inline unsigned long get_module_symbol(char *A, char *B) { return 0; };
+static inline void put_module_symbol(unsigned long A) { };
 #else
 extern unsigned long get_module_symbol(char *, char *);
+extern void put_module_symbol(unsigned long);
 #endif
 #if defined(MODULE) && !defined(__GENKSYMS__)
 

--
dwmw2

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Oct 23 2000 - 21:00:14 EST