patch-pre2.0.5 linux/kernel/module.c

Next file: linux/mm/filemap.c
Previous file: linux/init/main.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file pre2.0.4/linux/kernel/module.c linux/kernel/module.c
@@ -55,8 +55,6 @@
 static int get_mod_name( char *user_name, char *buf);
 static int free_modules( void);
 
-static int module_init_flag = 0; /* Hmm... */
-
 extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
 
 /*
@@ -147,7 +145,7 @@
 	/* A little bit of protection... we "know" where the user stack is... */
 
 	if (symtab && ((unsigned long)symtab > 0xb0000000)) {
-		printk("warning: you are using an old insmod, no symbols will be inserted!\n");
+		printk(KERN_WARNING "warning: you are using an old insmod, no symbols will be inserted!\n");
 		symtab = NULL;
 	}
 #endif
@@ -211,7 +209,7 @@
 			newtab->n_refs * sizeof(struct module_ref);
 
 		if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
-			printk("Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
+			printk(KERN_WARNING "Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
 			       newtab->n_symbols, newtab->n_refs);
 			kfree_s(newtab, size);
 			return -EINVAL;
@@ -220,7 +218,7 @@
 		/* relocate name pointers, index referred from start of table */
 		for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
 			if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
-				printk("Rejecting illegal symbol table\n");
+				printk(KERN_WARNING "Rejecting illegal symbol table\n");
 				kfree_s(newtab, size);
 				return -EINVAL;
 			}
@@ -246,7 +244,7 @@
 				link = link->next;
 
 			if (link == (struct module *)0) {
-				printk("Non-module reference! Rejected!\n");
+				printk(KERN_WARNING "Non-module reference! Rejected!\n");
 				return -EINVAL;
 			}
 
@@ -256,12 +254,12 @@
 		}
 	}
 
-	module_init_flag = 1; /* Hmm... */
+	GET_USE_COUNT(mp) += 1;
 	if ((*rt.init)() != 0) {
-		module_init_flag = 0; /* Hmm... */
+		GET_USE_COUNT(mp) = 0;
 		return -EBUSY;
 	}
-	module_init_flag = 0; /* Hmm... */
+	GET_USE_COUNT(mp) -= 1;
 	mp->state = MOD_RUNNING;
 
 	return 0;
@@ -282,9 +280,10 @@
 			return error;
 		if ((mp = find_module(name)) == NULL)
 			return -ENOENT;
-		if ((mp->ref != NULL) || ((GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN) != 0))
+		if ((mp->ref != NULL) ||
+		    ((GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED)) != 0))
 			return -EBUSY;
-		GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
+		GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
 		if (mp->state == MOD_RUNNING)
 			(*mp->cleanup)();
 		mp->state = MOD_DELETED;
@@ -293,11 +292,17 @@
 	/* for automatic reaping */
 	else {
 		for (mp = module_list; mp != &kernel_module; mp = mp->next) {
-			if ((mp->ref == NULL) && (GET_USE_COUNT(mp) == MOD_AUTOCLEAN) &&
-			    (mp->state == MOD_RUNNING)) {
-				GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
-				(*mp->cleanup)();
-				mp->state = MOD_DELETED;
+			if ((mp->ref == NULL) && (mp->state == MOD_RUNNING) &&
+			    ((GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED)) == 0)) {
+			    	if ((GET_USE_COUNT(mp) & MOD_VISITED)) {
+					/* Don't reap until one "cycle" after last _use_ */
+			   		GET_USE_COUNT(mp) &= ~MOD_VISITED;
+				}
+				else {
+					GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
+					(*mp->cleanup)();
+					mp->state = MOD_DELETED;
+				}
 			}
 		}
 		free_modules();
@@ -534,7 +539,7 @@
 		}
 		if (mp->state == MOD_RUNNING) {
 			sprintf(size,"\t%ld%s",
-				GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN,
+				GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED),
 				((GET_USE_COUNT(mp) & MOD_AUTOCLEAN)?
 					" (autoclean)":""));
 			q = size;
@@ -639,11 +644,17 @@
 			intab->n_symbols +=1;
 	}
 
-#if 1
-	if (module_init_flag == 0) { /* Hmm... */
-#else
-	if (module_list == &kernel_module) {
-#endif
+	for (mp = module_list; intab && mp != &kernel_module; mp = mp->next) {
+		/*
+		 * New table stored within memory belonging to a module?
+		 * (Always true for a module)
+		 */
+		if (((unsigned long)(mp->addr) < (unsigned long)intab) &&
+		    ((unsigned long)intab < ((unsigned long)(mp->addr) + mp->size * PAGE_SIZE)))
+			break;
+	}
+
+	if (mp == &kernel_module) {
 		/* Aha! Called from an "internal" module */
 		if (!intab)
 			return 0; /* or -ESILLY_PROGRAMMER :-) */
@@ -651,7 +662,7 @@
 		/* create a pseudo module! */
 		if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
 			/* panic time! */
-			printk("Out of memory for new symbol table!\n");
+			printk(KERN_ERR "Out of memory for new symbol table!\n");
 			return -ENOMEM;
 		}
 		/* else  OK */
@@ -674,7 +685,6 @@
 	 * call to  init_module  i.e. when loading the module!!
 	 * Or else...
 	 */
-	mp = module_list; /* true when doing init_module! */
 
 	/* Any table there before? */
 	if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
@@ -684,12 +694,6 @@
 	}
 
 	/* else  ****** we have to replace the module symbol table ******/
-#if 0
-	if (oldtab->n_symbols > 0) {
-		/* Oh dear, I have to drop the old ones... */
-		printk("Warning, dropping old symbols\n");
-	}
-#endif
 
 	if (oldtab->n_refs == 0) { /* no problems! */
 		mp->symtab = intab;
@@ -714,7 +718,7 @@
 			oldtab->n_refs * REFSIZ,
 		GFP_KERNEL))) {
 		/* panic time! */
-		printk("Out of memory for new symbol table!\n");
+		printk(KERN_ERR "Out of memory for new symbol table!\n");
 		return -ENOMEM;
 	}
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this