2002-07-27 20:20:33

by Roman Zippel

[permalink] [raw]
Subject: [PATCH] automatic initcalls

Index: Makefile
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/Makefile,v
retrieving revision 1.1.1.30
diff -u -p -r1.1.1.30 Makefile
--- Makefile 27 Jul 2002 12:34:13 -0000 1.1.1.30
+++ Makefile 27 Jul 2002 13:19:29 -0000
@@ -268,6 +268,7 @@ cmd_link_vmlinux = $(LD) $(LDFLAGS) $(LD
$(DRIVERS) \
$(NETWORKS) \
--end-group \
+ init/generated-initcalls.o \
-o vmlinux

# set -e makes the rule exit immediately on error
@@ -284,9 +285,25 @@ define rule_link_vmlinux
$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
endef

-vmlinux: $(vmlinux-objs) FORCE
+init/generated-initcalls.c: .allinit.defs
+ set -e; echo '#include <linux/init.h>' > $@; \
+ sed -n < $< "s,^T ,,p" | sort > .defined.all; \
+ sed -n < $< "s,^U ,,p" | sort > .undefined.all; \
+ join -o "1.2 2.2" .defined.all .undefined.all | sort -u | tsort > .sorted.all; \
+ cut -d ' ' -f 3 < .allinit.defs | sort -u | grep -v -f .sorted.all > .other.all; \
+ cat .other.all >> .sorted.all; \
+ while read obj; do objdump -t $$obj | awk '/F \.initcall\.test/ { print "extern int " $$6 "(void);" }'; done < .other.all >> $@; \
+ echo 'initcall_t generated_initcalls[] = {' >> $@; \
+ while read obj; do objdump -t $$obj | awk '/F \.initcall\.test/ { print $$6 "," }'; done < .other.all >> $@; \
+ echo '0 };' >> $@
+
+vmlinux: $(vmlinux-objs) init/generated-initcalls.o FORCE
$(call if_changed_rule,link_vmlinux)

+.allinit.defs: $(CORE_FILES) $(LIBS) $(DRIVERS) $(NETWORKS)
+ rm -f $@; \
+ for s in $(dir $^); do ls -ld $$s; awk "{ print \$$1 \" \" \$$2 \" $$s\" \$$3 }" < $${s}.all_defs >> $@; done
+
# The actual objects are generated when descending,
# make sure no implicit rule kicks in

@@ -586,6 +603,7 @@ defconfig:

# files removed with 'make clean'
CLEAN_FILES += \
+ init/generated-initcalls.c .allinit.defs .defined.all .undefined.all .other.all .sorted.all \
include/linux/compile.h \
vmlinux System.map \
drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \
@@ -647,7 +665,7 @@ clean: archclean
@echo 'Cleaning up'
@find . -name SCCS -prune -o -name BitKeeper -prune -o \
\( -name \*.[oas] -o -name core -o -name .\*.cmd -o \
- -name .\*.tmp -o -name .\*.d \) -type f -print \
+ -name .\*.tmp -o -name .\*.d -o -name .\*[._]defs \) -type f -print \
| grep -v lxdialog/ | xargs rm -f
@rm -f $(CLEAN_FILES)
@$(MAKE) -f Documentation/DocBook/Makefile clean
Index: Rules.make
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/Rules.make,v
retrieving revision 1.1.1.17
diff -u -p -r1.1.1.17 Rules.make
--- Rules.make 6 Jul 2002 00:33:37 -0000 1.1.1.17
+++ Rules.make 27 Jul 2002 18:56:39 -0000
@@ -105,9 +105,16 @@ multi-objs-m := $(foreach m, $(multi-use
subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)))

# Replace multi-part objects by their individual parts, look at local dir only
-real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(m))) $(EXTRA_TARGETS)
+mod-objs-y := $(filter-out $(subdir-obj-y), $(obj-y))
+real-objs-y := $(foreach m, $(mod-objs-y), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(m))) $(EXTRA_TARGETS)
real-objs-m := $(foreach m, $(obj-m), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(m)))

+modnames := $(foreach m, $(sort $(mod-objs-y) $(objs-m)), $(if $($(m:.o=-objs)),$(foreach mm,$($(m:.o=-objs)),.$(mm).$(m))))
+
+modname = $(*F)
+
+$(multi-objs-y) $(multi-objs-m) : modname = $(patsubst .$@.%,%,$(filter .$@.%,$(modnames)))
+
# Only build module versions for files which are selected to be built
export-objs := $(filter $(export-objs),$(real-objs-y) $(real-objs-m))

@@ -168,6 +175,7 @@ $(addprefix $(MODVERDIR)/,$(export-objs:
c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
$(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
-DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \
+ -DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname:.o=))) \
$(export_flags)

# Our objects only depend on modversions.h, not on the individual .ver
@@ -248,7 +256,7 @@ endif
# The echo suppresses the "Nothing to be done for first_rule"
first_rule: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \
$(if $(KBUILD_MODULES),$(obj-m)) \
- sub_dirs
+ sub_dirs .all_defs
@echo -n

# Compile C sources (.c)
@@ -269,6 +277,7 @@ $(export-objs:.o=.lst): export_flags :
c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
$(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
-DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \
+ -DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname:.o=))) \
$(export_flags)

quiet_cmd_cc_s_c = CC $(echo_target)
@@ -294,6 +303,17 @@ cmd_cc_lst_c = $(CC) $(c_flags) -g -

%.lst: %.c FORCE
$(call if_changed_dep,cc_lst_c)
+
+.%.defs: %.o
+ if [ -n "$$(objdump -h $< | egrep '^[ ]*[0-9]+ \.initcall\.test')" ]; then \
+ nm $< | sed -n "s,^[0-9a-f ]*\([TU].*\),\1 $<,p" > $@; \
+ else > $@; fi
+
+$(subdir-y:%=%/.all_defs): sub_dirs
+
+.all_defs: $(mod-objs-y:%.o=.%.defs) $(subdir-y:%=%/.all_defs)
+ cat $(mod-objs-y:%.o=.%.defs) /dev/null > $@; \
+ for s in $(subdir-y); do awk "{ print \$$1 \" \" \$$2 \" $$s/\" \$$3 }" < $$s/.all_defs; done >> $@

# Compile assembler sources (.S)
# ---------------------------------------------------------------------------
Index: drivers/ide/main.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/drivers/ide/main.c,v
retrieving revision 1.1.1.7
diff -u -p -r1.1.1.7 main.c
--- drivers/ide/main.c 27 Jul 2002 12:40:01 -0000 1.1.1.7
+++ drivers/ide/main.c 27 Jul 2002 13:19:30 -0000
@@ -1401,12 +1401,6 @@ static int __init ata_module_init(void)
/*
* Initialize all device type driver modules.
*/
-#ifdef CONFIG_BLK_DEV_IDEDISK
- idedisk_init();
-#endif
-#ifdef CONFIG_BLK_DEV_IDECD
- ide_cdrom_init();
-#endif
#ifdef CONFIG_BLK_DEV_IDETAPE
idetape_init();
#endif
Index: fs/dnotify.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/fs/dnotify.c,v
retrieving revision 1.1.1.5
diff -u -p -r1.1.1.5 dnotify.c
--- fs/dnotify.c 27 Jul 2002 12:34:15 -0000 1.1.1.5
+++ fs/dnotify.c 27 Jul 2002 13:19:30 -0000
@@ -155,4 +155,4 @@ static int __init dnotify_init(void)
return 0;
}

-module_init(dnotify_init)
+fs_initcall(dnotify_init);
Index: fs/fcntl.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/fs/fcntl.c,v
retrieving revision 1.1.1.8
diff -u -p -r1.1.1.8 fcntl.c
--- fs/fcntl.c 27 Jul 2002 12:34:14 -0000 1.1.1.8
+++ fs/fcntl.c 27 Jul 2002 13:19:30 -0000
@@ -568,4 +568,4 @@ static int __init fasync_init(void)
return 0;
}

-module_init(fasync_init)
+fs_initcall(fasync_init);
Index: fs/locks.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/fs/locks.c,v
retrieving revision 1.1.1.9
diff -u -p -r1.1.1.9 locks.c
--- fs/locks.c 27 Jul 2002 12:34:14 -0000 1.1.1.9
+++ fs/locks.c 27 Jul 2002 13:19:30 -0000
@@ -1936,4 +1936,4 @@ static int __init filelock_init(void)
return 0;
}

-module_init(filelock_init)
+fs_initcall(filelock_init);
Index: include/linux/init.h
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/include/linux/init.h,v
retrieving revision 1.1.1.6
diff -u -p -r1.1.1.6 init.h
--- include/linux/init.h 13 Jun 2002 00:22:57 -0000 1.1.1.6
+++ include/linux/init.h 27 Jul 2002 13:19:30 -0000
@@ -65,10 +65,16 @@ extern initcall_t __initcall_start, __in
#define arch_initcall(fn) __define_initcall("3",fn)
#define subsys_initcall(fn) __define_initcall("4",fn)
#define fs_initcall(fn) __define_initcall("5",fn)
-#define device_initcall(fn) __define_initcall("6",fn)
-#define late_initcall(fn) __define_initcall("7",fn)

-#define __initcall(fn) device_initcall(fn)
+#define device_initcall(fn) __initcall(fn)
+#define late_initcall(fn) __initcall(fn)
+
+#define __CAT3(a,b,c) a##b##c
+#define _CAT3(a,b,c) __CAT3(a,b,c)
+
+#define __initcall(fn) \
+ int __attribute__((__section__ (".initcall.test"))) _CAT3(fn,_,KBUILD_MODNAME)(void) \
+ { return fn(); }

#define __exitcall(fn) \
static exitcall_t __exitcall_##fn __exit_call = fn
Index: init/main.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/init/main.c,v
retrieving revision 1.1.1.17
diff -u -p -r1.1.1.17 main.c
--- init/main.c 27 Jul 2002 12:34:42 -0000 1.1.1.17
+++ init/main.c 27 Jul 2002 13:19:31 -0000
@@ -464,6 +464,8 @@ asmlinkage void __init start_kernel(void

struct task_struct *child_reaper = &init_task;

+extern initcall_t generated_initcalls[];
+
static void __init do_initcalls(void)
{
initcall_t *call;
@@ -473,6 +475,9 @@ static void __init do_initcalls(void)
(*call)();
call++;
} while (call < &__initcall_end);
+
+ for (call = generated_initcalls; *call; call++)
+ (*call)();

/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_tasks();
Index: kernel/sched.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/kernel/sched.c,v
retrieving revision 1.1.1.22
diff -u -p -r1.1.1.22 sched.c
--- kernel/sched.c 27 Jul 2002 12:34:42 -0000 1.1.1.22
+++ kernel/sched.c 27 Jul 2002 15:50:14 -0000
@@ -1910,7 +1910,7 @@ int __init migration_init(void)
return 0;
}

-__initcall(migration_init);
+fs_initcall(migration_init);
#endif

extern void init_timervecs(void);
Index: kernel/softirq.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/kernel/softirq.c,v
retrieving revision 1.1.1.12
diff -u -p -r1.1.1.12 softirq.c
--- kernel/softirq.c 27 Jul 2002 12:34:43 -0000 1.1.1.12
+++ kernel/softirq.c 27 Jul 2002 15:50:14 -0000
@@ -417,4 +417,4 @@ static __init int spawn_ksoftirqd(void)
return 0;
}

-__initcall(spawn_ksoftirqd);
+fs_initcall(spawn_ksoftirqd);


Attachments:
initcall.diff (9.97 kB)

2002-07-28 03:29:27

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

In message <[email protected]> you write:
> - I only look at modules which contain an initcall
> - I only order initcalls of level 6 and 7

You don't seem to handle the ordering of initcalls within a module
though: see net/ipv4/netfilter/ip_conntrack.o for an example of
multiple inits which would be much better as separate initcalls.

The more I play with these magic approaches, the more I prefer an
explicit "Must be done after this" and "must be done before this":
otherwise we're going to need to keep adding new levels as we discover
something that doesn't fit in the magic 7.

Especially since you don't cover any of the really interesting cases.
Maybe if you could slowly extend it to cover the rest? (Hah, I
know!).

> +init/generated-initcalls.c: .allinit.defs
> + set -e; echo '#include <linux/init.h>' > $@; \
> + sed -n < $< "s,^T ,,p" | sort > .defined.all; \

I think you mean something like:

sed -n "s,^T ,,p" < $<

> -__initcall(spawn_ksoftirqd);
> +fs_initcall(spawn_ksoftirqd);

See, this is exacly the kind of thing that makes me doubt that the
current "magic 7 initcall levels" are useful in the long term 8(

Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-07-28 03:48:45

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

Rusty Russell wrote:
> The more I play with these magic approaches, the more I prefer an
> explicit "Must be done after this" and "must be done before this":
> otherwise we're going to need to keep adding new levels as we discover
> something that doesn't fit in the magic 7.

I've always preferred a system where one simply lists dependencies [as
you describe above], and some program actually does the hard work of
chasing down all the initcall dependency checking and ordering.

Linus has traditionally poo-pooed this so I haven't put any work towards
it... but I still think it's a good idea, and something we will
eventually need as our system grows more complex. If someone stood up
and did the work, it should be pretty easy to generate a human-readable
list of dependencies so we can check the ordering and make sure it's
getting things right.

I wonder if there is some nifty ld feature I'm missing, that could do
this for us...

Jeff



2002-07-28 04:43:00

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls



On Sat, 27 Jul 2002, Jeff Garzik wrote:
>
> I've always preferred a system where one simply lists dependencies [as
> you describe above], and some program actually does the hard work of
> chasing down all the initcall dependency checking and ordering.
>
> Linus has traditionally poo-pooed this so I haven't put any work towards
> it...

I don't hate the notion, but at the same time every time it comes up I
feel that there are reasonably simple ways to just avoid the ordering
problems.

Rusty had a script, but somebody complained about the speed of it. I
haven't looked at it myself.

Linus

2002-07-28 08:47:02

by Keith Adamson

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

On Sun, 2002-07-28 at 00:47, Linus Torvalds wrote:
>
>
> On Sat, 27 Jul 2002, Jeff Garzik wrote:
> >
> > I've always preferred a system where one simply lists dependencies [as
> > you describe above], and some program actually does the hard work of
> > chasing down all the initcall dependency checking and ordering.
> >
> > Linus has traditionally poo-pooed this so I haven't put any work towards
> > it...
>
> I don't hate the notion, but at the same time every time it comes up I
> feel that there are reasonably simple ways to just avoid the ordering
> problems.
>
> Rusty had a script, but somebody complained about the speed of it. I
> haven't looked at it myself.
>
> Linus

There is a relatively simple and fast recursive algorithm I've used
before to generating a sequence from a dependency list.
For initcall sequence it would be something like this (bash scripts
attached);

Dependency database: dependency_list_database
Main programs: make_initcall_seqence.sh
Recursive routine: generate_initcall.sh

Output sequence: initcall_sequence

See attached files.

Normally I have error checking for bad dependencies (you can get into a
infinite recursive loop if for instance "foo1" needs "foo2" and also
"foo2" needs "foo1") ... but I didn't do it to keep the algorithm more
understandable.

Keith


Attachments:
make_initcall_seqence.sh (598.00 B)
generate_initcall.sh (1.30 kB)
dependency_list_database (66.00 B)
Download all attachments

2002-07-28 12:15:54

by Roman Zippel

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

Hi,

On Sun, 28 Jul 2002, Rusty Russell wrote:

> > - I only look at modules which contain an initcall
> > - I only order initcalls of level 6 and 7
>
> You don't seem to handle the ordering of initcalls within a module
> though: see net/ipv4/netfilter/ip_conntrack.o for an example of
> multiple inits which would be much better as separate initcalls.

Actually I'm most interested in ordering "module_init()" and you can have
only one of them per module or how do you want to implement multiple
initcalls per module?

> Especially since you don't cover any of the really interesting cases.
> Maybe if you could slowly extend it to cover the rest? (Hah, I
> know!).

I wouldn't mind if the remaining initcalls are converted to explicit
dependencies, but it's possible to sort automatically everything that can
be built as modules.

> > +init/generated-initcalls.c: .allinit.defs
> > + set -e; echo '#include <linux/init.h>' > $@; \
> > + sed -n < $< "s,^T ,,p" | sort > .defined.all; \
>
> I think you mean something like:
>
> sed -n "s,^T ,,p" < $<

Isn't that the same?

bye, Roman

2002-07-28 18:56:29

by Oliver Xymoron

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

On Sat, 27 Jul 2002, Linus Torvalds wrote:

> On Sat, 27 Jul 2002, Jeff Garzik wrote:
> >
> > I've always preferred a system where one simply lists dependencies [as
> > you describe above], and some program actually does the hard work of
> > chasing down all the initcall dependency checking and ordering.
> >
> > Linus has traditionally poo-pooed this so I haven't put any work towards
> > it...
>
> I don't hate the notion, but at the same time every time it comes up I
> feel that there are reasonably simple ways to just avoid the ordering
> problems.

The 'simple ways' are only simpler because they're taking advantage of
pre-existing (and undocumented) implicit ordering. The explicit
dependencies are probably less complex on the whole as it lets you take
out a ton of per-subsystem conditional cruft and replace it with a couple
lines of dependency info.

Given that sizeof(dependency info)==sizeof(missing documentation of
dependencies), it's clear that sizeof(dependency info + support + script)
< sizeof(current ordering code + conditional cruft + missing
documentation).

--
"Love the dolphins," she advised him. "Write by W.A.S.T.E.."

2002-07-28 21:55:59

by Kai Germaschewski

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

On Sun, 28 Jul 2002, Rusty Russell wrote:

> In message <[email protected]> you write:
> > - I only look at modules which contain an initcall
> > - I only order initcalls of level 6 and 7
>
> You don't seem to handle the ordering of initcalls within a module
> though: see net/ipv4/netfilter/ip_conntrack.o for an example of
> multiple inits which would be much better as separate initcalls.

I'm not at all familiar with this code, but traditionally there is only
one initcall per module - extending this to multiple initcalls with
automated unwinding if one of those fails may be something to look into,
but I don't think it has much to do with the current discussion (I doubt
your patch does the unwinding, does it?)

> The more I play with these magic approaches, the more I prefer an
> explicit "Must be done after this" and "must be done before this":
> otherwise we're going to need to keep adding new levels as we discover
> something that doesn't fit in the magic 7.
>
> Especially since you don't cover any of the really interesting cases.
> Maybe if you could slowly extend it to cover the rest? (Hah, I
> know!).

I think when I commented on your initial patch, I said that I would make
sense to use the existing ordering information where available, but it
surely doesn't solve all the world's problems, so your patch would help a
lot in cleaning up the ordering of the early initcalls of not modularized
parts of the kernel.

For modules, it's obvious that we cannot insmod a module unless it's
unresolved symbols can be resolved, i.e. the code which provides them has
to be compiled-in or a module providing them has been loaded before. This
is also the only way to determine the order of loading modules we have, so
we guarantee that once all unresolved symbols are made available, all
necessary initializations have run - most people probably don't think of
it this way, because it comes natural anyway.

My point was that I don't think it's necessarily a good idea to duplicate
this info - hisax.o (an ISDN hardware driver) needs "register_isdn()",
which is provided by isdn.o. Insmoding isdn.o will of course also run the
necessary initializations for making register_isdn() ready to be called
from driver modules. It has to remain this way, since otherwise insmoding
modules in the wrong order would crash the kernel. Now, in your scheme you
would add an dependency like
__initcall(hisax_init, initcall_after(isdn_init))
which duplicates this info. Which, as all duplicated info is redundant and
has the potential for getting out of sync, different behavior for built-in
vs. modular, etc.

On the other hand, we have complicated ordering during init, like
(probably wrong as I put it, but you get the picture):

pci_driver_init()
pci_pcibios_init()
pci_direct_init()
pci_legacy_init()
acpi_pci_init()
pci_init()

These parts are not modularized, so the argument above doesn't help. Here,
I think it would be a great improvement to be able to give dependencies on
what has to be run when explicitly.

So the ideal solution would, IMO, look like:

Replace the __initcall levels by two constructs:
o __initcall(foo_init, init_after/...)
o module_init()

The __initcalls are called first, in the order explicitly given. Only
then, the functions declared as module_init() would get called, in an
order determined by the dependencies on exported symbols - i.e. that would
be comparable with compiling them as modules and insmoding them in just
this order.

I didn't have the time to look at the patches in depth yet, but it looks
like we've got the two pieces and just have to put them together.

--Kai




2002-07-29 09:54:25

by Ingo Oeser

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

On Sat, Jul 27, 2002 at 11:51:32PM -0400, Jeff Garzik wrote:
> I've always preferred a system where one simply lists dependencies [as
> you describe above], and some program actually does the hard work of
> chasing down all the initcall dependency checking and ordering.

So we just need to build a directed graph, detect edges without
existing nodes (someone changed the initcall, we depend on) and
cycles (someone messed up the ordering) as errors, sort the
resulting graph toplogically and dump it as a sequence.

This is no rocket science and we have two tools, which does this
all for us (make and tsort, which create a warning for both cases).

The hard part is to CREATE all the dependencies and check and
double check them with the maintainers.

Regards

Ingo Oeser
--
Science is what we can tell a computer. Art is everything else. --- D.E.Knuth

2002-07-29 18:52:53

by Patrick Mochel

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls


> > -__initcall(spawn_ksoftirqd);
> > +fs_initcall(spawn_ksoftirqd);
>
> See, this is exacly the kind of thing that makes me doubt that the
> current "magic 7 initcall levels" are useful in the long term 8(

I agree that that is abusing the interface. WTF does spawn_ksoftirqd have
to do with filesystems?

The purpose of the initcall levels in the first place was to start
removing the ugly conditional calls in init/main.c I looked at what was
being called, and came up with names to describe what was being done at
each phase. There happened to be seven of them.

I knew from the start that people would feel that they were more important
that others, and leapfrog their initcalls before everyone else. We're
egotistical; that's what we do. But remember, just because it's there,
doesn't mean you have to use it.

That said, it's been a while since I've really looked at it. I favor a
mechanism for getting the ordering right. I don't really like having to
specify the dependencies in the definitions; I think it's kinda ugly and
wonder if there is an automatic way to resolve them. I don't have any
ideas, nor the time to play with it, so it remains still just a pipe
dream...

-pat

2002-07-29 20:11:57

by Roman Zippel

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

Hi,

On Mon, 29 Jul 2002, Patrick Mochel wrote:

> > > -__initcall(spawn_ksoftirqd);
> > > +fs_initcall(spawn_ksoftirqd);
> >
> > See, this is exacly the kind of thing that makes me doubt that the
> > current "magic 7 initcall levels" are useful in the long term 8(
>
> I agree that that is abusing the interface. WTF does spawn_ksoftirqd have
> to do with filesystems?

Above is just a hack to get it working, I only moved it one level up,
instead of spending too much time on figuring out the complete
dependencies.

> The purpose of the initcall levels in the first place was to start
> removing the ugly conditional calls in init/main.c I looked at what was
> being called, and came up with names to describe what was being done at
> each phase. There happened to be seven of them.

I think we should separate module initialization from this, as these can
be automatically ordered, what the posted patch demonstrates.
The initcall mechanism would then only be needed to initialize core kernel
services, which can't be build as module.
I'm only interrested to get the module initialization right, because
otherwise I get problems with the new module interface. I want to avoid
to include an explicit ordering, but currently some modules make use of
that *_initcall is mapped to module_init if compiled as module (e.g. usb
or pcmcia).

bye, Roman

2002-07-29 23:53:07

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

In message <[email protected]> you wri
te:
>
>
> On Sat, 27 Jul 2002, Jeff Garzik wrote:
> >
> > I've always preferred a system where one simply lists dependencies [as
> > you describe above], and some program actually does the hard work of
> > chasing down all the initcall dependency checking and ordering.
> >
> > Linus has traditionally poo-pooed this so I haven't put any work towards
> > it...
>
> I don't hate the notion, but at the same time every time it comes up I
> feel that there are reasonably simple ways to just avoid the ordering
> problems.

I think that the best hope is a combination of Roman's module depends
work (based on Kai's "everything which is a module is trivial", and
Stephen and my first depends hack) and explicit depends.

Linkage ordering doesn't work in general, for things like "I want to
be initialized before the non-boot cpus have come up", but for
non-core code it's simple.

> Rusty had a script, but somebody complained about the speed of it. I
> haven't looked at it myself.

Yes, it'll slow the build by a few seconds: but if the linker ever
decides not to preserve ordering, we'll need it. My original shell
script is suboptimal but we *don't* want the kernel build relying on
libbfd.

Roman and I will come up with something and send it to you later this
week.

Thanks!
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-07-29 23:53:04

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

In message <Pine.LNX.4.44.0207281358070.28515-100000@serv> you write:
> Hi,
>
> On Sun, 28 Jul 2002, Rusty Russell wrote:
>
> > > - I only look at modules which contain an initcall
> > > - I only order initcalls of level 6 and 7
> >
> > You don't seem to handle the ordering of initcalls within a module
> > though: see net/ipv4/netfilter/ip_conntrack.o for an example of
> > multiple inits which would be much better as separate initcalls.
>
> Actually I'm most interested in ordering "module_init()" and you can have
> only one of them per module or how do you want to implement multiple
> initcalls per module?

Sorry, you are right. That was a brain fart.

> > Especially since you don't cover any of the really interesting cases.
> > Maybe if you could slowly extend it to cover the rest? (Hah, I
> > know!).
>
> I wouldn't mind if the remaining initcalls are converted to explicit
> dependencies, but it's possible to sort automatically everything that can
> be built as modules.

Yes, I think we should do this: merge the two together. You seem to
be in a coding frenzy: want to do the first cut?

I'll probably change my initdepends section format to make it shorter
and easier to parse. But that change should be independent.

> > > +init/generated-initcalls.c: .allinit.defs
> > > + set -e; echo '#include <linux/init.h>' > $@; \
> > > + sed -n < $< "s,^T ,,p" | sort > .defined.all; \
> >
> > I think you mean something like:
> >
> > sed -n "s,^T ,,p" < $<
>
> Isn't that the same?

Argh, not my day, clearly. Let's pretend I didn't send that mail,
shall we?

Cheers,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-07-30 02:44:49

by Keith Adamson

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

On Mon, 2002-07-29 at 04:39, Ingo Oeser wrote:
> On Sat, Jul 27, 2002 at 11:51:32PM -0400, Jeff Garzik wrote:
> > I've always preferred a system where one simply lists dependencies [as
> > you describe above], and some program actually does the hard work of
> > chasing down all the initcall dependency checking and ordering.
>
> So we just need to build a directed graph, detect edges without
> existing nodes (someone changed the initcall, we depend on) and
> cycles (someone messed up the ordering) as errors, sort the
> resulting graph toplogically and dump it as a sequence.
>
> This is no rocket science and we have two tools, which does this
> all for us (make and tsort, which create a warning for both cases).
>
> The hard part is to CREATE all the dependencies and check and
> double check them with the maintainers.
>

I definitely agree the easy part is the algorithm and the hard part is
creating the dependency list. For instance, attached is a small
algorithm that does the initcall sequencing at run time.

The API is is simple, you just register your initcall with a list of
critical initcalls you need to be run before yours (not all, just the
ones you definitely need to be run first). Then the ordering of the all
the initcalls are sequenced at run time. This way you don't have to
worry about link ordering or code ordering of your initcalls during
make/compile/link. All initcall ordering is done during boot.

This really frees you from module inter-dependencies because is doesn't
mater in what order you register you initcalls. You only need register
them with a list the critical modules that need to be initialized before
yours.

The API also provides that you can register more than one initcall for
your module with a different set of critical modules that must be run
first.

This should be relative easy to add to the kernel, as you don't have to
modify any of the existing initcalls. You do need to remove all
existing calls to them and register them instead with the new API.

Untar and "cd init; cc *.c; ./a.out"

Four example modules register their initcalls, "foo1, foo2, foo3, foo4",
and then the main routine sequences them at run time.

Regards, Keith



2002-07-30 02:46:40

by Keith Adamson

[permalink] [raw]
Subject: Re: [PATCH] automatic initcalls

On Mon, 2002-07-29 at 22:49, Keith Adamson wrote:
> On Mon, 2002-07-29 at 04:39, Ingo Oeser wrote:
> > On Sat, Jul 27, 2002 at 11:51:32PM -0400, Jeff Garzik wrote:
> > > I've always preferred a system where one simply lists dependencies [as
> > > you describe above], and some program actually does the hard work of
> > > chasing down all the initcall dependency checking and ordering.
> >
> > So we just need to build a directed graph, detect edges without
> > existing nodes (someone changed the initcall, we depend on) and
> > cycles (someone messed up the ordering) as errors, sort the
> > resulting graph toplogically and dump it as a sequence.
> >
> > This is no rocket science and we have two tools, which does this
> > all for us (make and tsort, which create a warning for both cases).
> >
> > The hard part is to CREATE all the dependencies and check and
> > double check them with the maintainers.
> >
>
> I definitely agree the easy part is the algorithm and the hard part is
> creating the dependency list. For instance, attached is a small
> algorithm that does the initcall sequencing at run time.
>
> The API is is simple, you just register your initcall with a list of
> critical initcalls you need to be run before yours (not all, just the
> ones you definitely need to be run first). Then the ordering of the all
> the initcalls are sequenced at run time. This way you don't have to
> worry about link ordering or code ordering of your initcalls during
> make/compile/link. All initcall ordering is done during boot.
>
> This really frees you from module inter-dependencies because is doesn't
> mater in what order you register you initcalls. You only need register
> them with a list the critical modules that need to be initialized before
> yours.
>
> The API also provides that you can register more than one initcall for
> your module with a different set of critical modules that must be run
> first.
>
> This should be relative easy to add to the kernel, as you don't have to
> modify any of the existing initcalls. You do need to remove all
> existing calls to them and register them instead with the new API.
>
> Untar and "cd init; cc *.c; ./a.out"
>
> Four example modules register their initcalls, "foo1, foo2, foo3, foo4",
> and then the main routine sequences them at run time.
>
> Regards, Keith
>
>
Forgot the attachment :)




Attachments:
init_020729.tar (10.00 kB)