patch-2.3.99-pre1 linux/kernel/exec_domain.c

Next file: linux/kernel/exit.c
Previous file: linux/ipc/shm.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.51/linux/kernel/exec_domain.c linux/kernel/exec_domain.c
@@ -23,7 +23,7 @@
 };
 
 static struct exec_domain *exec_domains = &default_exec_domain;
-
+static spinlock_t exec_domains_lock = SPIN_LOCK_UNLOCKED;
 
 static asmlinkage void no_lcall7(int segment, struct pt_regs * regs)
 {
@@ -32,15 +32,10 @@
    * personality set incorrectly.  Check to see whether SVr4 is available,
    * and use it, otherwise give the user a SEGV.
    */
-	if (current->exec_domain && current->exec_domain->module)
-		__MOD_DEC_USE_COUNT(current->exec_domain->module);
-
+	put_exec_domain(current->exec_domain);
 	current->personality = PER_SVR4;
 	current->exec_domain = lookup_exec_domain(current->personality);
 
-	if (current->exec_domain && current->exec_domain->module)
-		__MOD_INC_USE_COUNT(current->exec_domain->module);
-
 	if (current->exec_domain && current->exec_domain->handler
 	&& current->exec_domain->handler != no_lcall7) {
 		current->exec_domain->handler(segment, regs);
@@ -55,10 +50,15 @@
 	unsigned long pers = personality & PER_MASK;
 	struct exec_domain *it;
 
+	spin_lock(&exec_domains_lock);
 	for (it=exec_domains; it; it=it->next)
-		if (pers >= it->pers_low
-		&& pers <= it->pers_high)
+		if (pers >= it->pers_low && pers <= it->pers_high) {
+			if (!try_inc_mod_count(it->module))
+				continue;
+			spin_unlock(&exec_domains_lock);
 			return it;
+		}
+	spin_unlock(&exec_domains_lock);
 
 	/* Should never get this far. */
 	printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
@@ -73,11 +73,15 @@
 		return -EINVAL;
 	if (it->next)
 		return -EBUSY;
+	spin_lock(&exec_domains_lock);
 	for (tmp=exec_domains; tmp; tmp=tmp->next)
-		if (tmp == it)
+		if (tmp == it) {
+			spin_unlock(&exec_domains_lock);
 			return -EBUSY;
+		}
 	it->next = exec_domains;
 	exec_domains = it;
+	spin_unlock(&exec_domains_lock);
 	return 0;
 }
 
@@ -86,14 +90,17 @@
 	struct exec_domain ** tmp;
 
 	tmp = &exec_domains;
+	spin_lock(&exec_domains_lock);
 	while (*tmp) {
 		if (it == *tmp) {
 			*tmp = it->next;
 			it->next = NULL;
+			spin_unlock(&exec_domains_lock);
 			return 0;
 		}
 		tmp = &(*tmp)->next;
 	}
+	spin_unlock(&exec_domains_lock);
 	return -EINVAL;
 }
 
@@ -113,12 +120,9 @@
 		goto out;
 
 	old_personality = current->personality;
-	if (current->exec_domain && current->exec_domain->module)
-		__MOD_DEC_USE_COUNT(current->exec_domain->module);
+	put_exec_domain(current->exec_domain);
 	current->personality = personality;
 	current->exec_domain = it;
-	if (current->exec_domain->module)
-		__MOD_INC_USE_COUNT(current->exec_domain->module);
 	ret = old_personality;
 out:
 	unlock_kernel();
@@ -130,9 +134,11 @@
 	int len = 0;
 	struct exec_domain * e;
 
+	spin_lock(&exec_domains_lock);
 	for (e=exec_domains; e && len < PAGE_SIZE - 80; e=e->next)
 		len += sprintf(page+len, "%d-%d\t%-16s\t[%s]\n",
 			e->pers_low, e->pers_high, e->name,
 			e->module ? e->module->name : "kernel");
+	spin_unlock(&exec_domains_lock);
 	return len;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)