Use list_head in binfmt handling
Switch single-linked binfmt formats list to usual list_head's. This leads
to one-liners in register_binfmt() and unregister_binfmt(). The downside
is one pointer more in struct linux_binfmt. This is not a problem, since
the set of registered binfmts on typical box is very small -- (ELF +
something distro enabled for you).
Test-booted, played with executable .txt files, modprobe/rmmod binfmt_misc.
Signed-off-by: Alexey Dobriyan <adobriyan@sw.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
diff --git a/fs/exec.c b/fs/exec.c
index 073b0b8..65825bd 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -66,27 +66,15 @@
EXPORT_SYMBOL(suid_dumpable);
/* The maximal length of core_pattern is also specified in sysctl.c */
-static struct linux_binfmt *formats;
+static LIST_HEAD(formats);
static DEFINE_RWLOCK(binfmt_lock);
int register_binfmt(struct linux_binfmt * fmt)
{
- struct linux_binfmt ** tmp = &formats;
-
if (!fmt)
return -EINVAL;
- if (fmt->next)
- return -EBUSY;
write_lock(&binfmt_lock);
- while (*tmp) {
- if (fmt == *tmp) {
- write_unlock(&binfmt_lock);
- return -EBUSY;
- }
- tmp = &(*tmp)->next;
- }
- fmt->next = formats;
- formats = fmt;
+ list_add(&fmt->lh, &formats);
write_unlock(&binfmt_lock);
return 0;
}
@@ -95,20 +83,10 @@
int unregister_binfmt(struct linux_binfmt * fmt)
{
- struct linux_binfmt ** tmp = &formats;
-
write_lock(&binfmt_lock);
- while (*tmp) {
- if (fmt == *tmp) {
- *tmp = fmt->next;
- fmt->next = NULL;
- write_unlock(&binfmt_lock);
- return 0;
- }
- tmp = &(*tmp)->next;
- }
+ list_del(&fmt->lh);
write_unlock(&binfmt_lock);
- return -EINVAL;
+ return 0;
}
EXPORT_SYMBOL(unregister_binfmt);
@@ -155,7 +133,7 @@
struct linux_binfmt * fmt;
read_lock(&binfmt_lock);
- for (fmt = formats ; fmt ; fmt = fmt->next) {
+ list_for_each_entry(fmt, &formats, lh) {
if (!fmt->load_shlib)
continue;
if (!try_module_get(fmt->module))
@@ -1284,7 +1262,7 @@
retval = -ENOENT;
for (try=0; try<2; try++) {
read_lock(&binfmt_lock);
- for (fmt = formats ; fmt ; fmt = fmt->next) {
+ list_for_each_entry(fmt, &formats, lh) {
int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
if (!fn)
continue;