Hi Linus,
This patch does two things to fs/exec.c:
a) sys_uselib() doesn't need lock/unlock_kernel as it uses
sys_open() which protects the call to filp_open() via global kernel
lock. I could probably make sys_uselib() use
filp_open()/filp_close() without any need to use descriptors
internally but doing so would make it more sensitive to VFS internals
which is not a good idea.
b) binfmt_lock should be read/write lock and not a plain spinlock
because only register/unregister_binfmt need to be mutually exclusive -
the rest can happen concurrently.
Regards,
Tigran
--- linux/fs/exec.c Tue May 16 10:18:48 2000
+++ work/fs/exec.c Tue May 16 12:44:15 2000
@@ -46,7 +46,7 @@
#endif
static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
-static spinlock_t binfmt_lock = SPIN_LOCK_UNLOCKED;
+static rwlock_t binfmt_lock = RW_LOCK_UNLOCKED;
int register_binfmt(struct linux_binfmt * fmt)
{
@@ -56,17 +56,17 @@
return -EINVAL;
if (fmt->next)
return -EBUSY;
- spin_lock(&binfmt_lock);
+ write_lock(&binfmt_lock);
while (*tmp) {
if (fmt == *tmp) {
- spin_unlock(&binfmt_lock);
+ write_unlock(&binfmt_lock);
return -EBUSY;
}
tmp = &(*tmp)->next;
}
fmt->next = formats;
formats = fmt;
- spin_unlock(&binfmt_lock);
+ write_unlock(&binfmt_lock);
return 0;
}
@@ -74,16 +74,16 @@
{
struct linux_binfmt ** tmp = &formats;
- spin_lock(&binfmt_lock);
+ write_lock(&binfmt_lock);
while (*tmp) {
if (fmt == *tmp) {
*tmp = fmt->next;
- spin_unlock(&binfmt_lock);
+ write_unlock(&binfmt_lock);
return 0;
}
tmp = &(*tmp)->next;
}
- spin_unlock(&binfmt_lock);
+ write_unlock(&binfmt_lock);
return -EINVAL;
}
@@ -105,33 +105,29 @@
struct file * file;
struct linux_binfmt * fmt;
- lock_kernel();
fd = sys_open(library, 0, 0);
- retval = fd;
if (fd < 0)
- goto out;
+ return fd;
file = fget(fd);
retval = -ENOEXEC;
if (file && file->f_op && file->f_op->read) {
- spin_lock(&binfmt_lock);
+ read_lock(&binfmt_lock);
for (fmt = formats ; fmt ; fmt = fmt->next) {
if (!fmt->load_shlib)
continue;
if (!try_inc_mod_count(fmt->module))
continue;
- spin_unlock(&binfmt_lock);
+ read_unlock(&binfmt_lock);
retval = fmt->load_shlib(file);
- spin_lock(&binfmt_lock);
+ read_lock(&binfmt_lock);
put_binfmt(fmt);
if (retval != -ENOEXEC)
break;
}
- spin_unlock(&binfmt_lock);
+ read_unlock(&binfmt_lock);
}
fput(file);
sys_close(fd);
-out:
- unlock_kernel();
return retval;
}
@@ -747,14 +743,14 @@
}
#endif
for (try=0; try<2; try++) {
- spin_lock(&binfmt_lock);
+ read_lock(&binfmt_lock);
for (fmt = formats ; fmt ; fmt = fmt->next) {
int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
if (!fn)
continue;
if (!try_inc_mod_count(fmt->module))
continue;
- spin_unlock(&binfmt_lock);
+ read_unlock(&binfmt_lock);
retval = fn(bprm, regs);
if (retval >= 0) {
put_binfmt(fmt);
@@ -764,16 +760,16 @@
current->did_exec = 1;
return retval;
}
- spin_lock(&binfmt_lock);
+ read_lock(&binfmt_lock);
put_binfmt(fmt);
if (retval != -ENOEXEC)
break;
if (!bprm->file) {
- spin_unlock(&binfmt_lock);
+ read_unlock(&binfmt_lock);
return retval;
}
}
- spin_unlock(&binfmt_lock);
+ read_unlock(&binfmt_lock);
if (retval != -ENOEXEC) {
break;
#ifdef CONFIG_KMOD
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Tue May 23 2000 - 21:00:10 EST