mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Re: Patch?: module-init-tools/modprobe.c - use modules.dep
@ 2002-11-25 19:16 Adam J. Richter
  2002-11-25 23:34 ` Rusty Russell
  0 siblings, 1 reply; 8+ messages in thread
From: Adam J. Richter @ 2002-11-25 19:16 UTC (permalink / raw)
  To: rusty; +Cc: dwmw2, linux-kernel

Rusty Russell wrote:
>In message <20021121073912.A15349@adam.yggdrasil.com> you [Adam Richter] write:
>> 
>> --xHFwDpU9dbj6ez1V
>> Content-Type: text/plain; charset=us-ascii
>> Content-Disposition: inline
>> 
>> 	The following patch changes modprobe in module-init-tools-0.8
>> to use modules.dep.
>> 
>> 	Benefits:
>> 
>> 	- deletes a net of 594 lines of source code
>> 
>> 	- shrinks modprobe from 14kB to 10kB (stripped, dynamically linked),
>> 	  which is useful for boot images
>> 
>> 	- should make modprobe as fast on systems with a lot of modules as
>> 	  it was with the user level module loader,
>> 
>> 	- Restores the "include" command to the aliases file, which makes
>> 	  it simpler to have separate files for automatically generated
>> 	  aliases and user customizations.
>> 
>> 	- minor: eliminates ELF dependence from modprobe user level code

>Hmm, I like it.  But I prefer to pull the depmod code into the source
>too, to keep it all under one roof.

	I have been thinking about splitting depmod into two programs:
the program as originally designed that generates modules.dep and one
that generates hardware support files.  The latter could be
distributed in the Linux kernel tree and perhaps installed in
/lib/modules/<version>/bin/ to make it easy to change support table
formats as needed.

>The ELF dependence will go back in eventually, but that's trivial.

	I'm guessing this is for symbols.  If it's for something other
reason, I'd be curious to know it.

>Hmm, Adam, do you want to reverse positions and become
>module-init-tools maintainer?  I'll send patches to you, instead of
>vice versa.  I'll release a 0.8 with the patches I have so far, then
>hand it over if you want.

>Thoughts?
>Rusty.

	I'm honored by the offer, but I have not seen any convincing
accounting of real benefits and costs that shows that it is a win to
have the module loader in kernel memory.  I might be interested in
maintaining a small modutils that could be compiled to support either
the in-kernel module load or a user level method (or both) so as to
avoid unnecessary differences between the user level and in-kernel
methods, given that the code that is specific to the kernel module
loader would be small.

Adam J. Richter     __     ______________   575 Oroville Road
adam@yggdrasil.com     \ /                  Milpitas, California 95035
+1 408 309-6081         | g g d r a s i l   United States of America
                         "Free Software For The Rest Of Us."

^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: Patch?: module-init-tools/modprobe.c - use modules.dep
@ 2002-11-26 19:02 Adam J. Richter
  2002-11-27  5:02 ` Rusty Russell
  0 siblings, 1 reply; 8+ messages in thread
From: Adam J. Richter @ 2002-11-26 19:02 UTC (permalink / raw)
  To: rusty; +Cc: dwmw2, linux-kernel

On Tue, 26 Nov 2002 10:34:30 +1100, Rusty Russell wrote:
>In message <200211251916.LAA01830@baldur.yggdrasil.com> you write:
[...]
>> >The ELF dependence will go back in eventually, but that's trivial.
>> 
>> 	I'm guessing this is for symbols.  If it's for something other
>> reason, I'd be curious to know it.
>
>--name support.  It's a hack, but it's 20 lines in total.

	Why not derive the default name from the file name?

	By the way, I have sometimes wanted to be able to load
multiple copies of the same module with different names, usually
little debugging helpers with different command line options.


>> 	[...] I have not seen any convincing
>> accounting of real benefits and costs that shows that it is a win to
>> have the module loader in kernel memory.
>
>Well, the linecount comes out as a wash (it's slightly bigger because
>of the hoops I jump through to avoid a spinlock on module refcount
>acquisition, but that's orthogonal).  Some archs lose 100 lines, some
>gain 400 lines.  The win comes from the cleanliness of two syscalls:
>one to add, one to remove.  For userspace loading you have one to
>allocate, one to insert, one to query so you know how to link.  Turns
>out to be more complicated than just doing the damn linking yourself.

	Sometimes a larger total code size to achieve smaller kernel
code size is a worthwhile trade-off because the userland code is not
always present, is swappable, is more customizable without rebooting
the system, etc.  Whether that is the case with the module loader
is the question that I'm trying to analyze.


>Frankly, linking just *isn't* that hard, especially when you're doing
>it on your own architecture (vs. 32-bit userspace handling both 32-bit
>and 64-bit kernelspaces).

	I think that Roman's approach of having a module-init.o
to initialize the struct module would reduce or eliminate this.

>With RTH's "make it a shared object" patch,
>it becomes even more trivial.

	rth's patch prevents allocating sections separately, so you
won't be able to kmalloc them as much, using TLB entries unnecessarily,
and using memory less efficiently in the case where the non-init
sections would fit in a single area small enough to be kmalloc'ed.
It's a modest cost, but it's something for the score card.



>But the flexibility!  By having a real interface, insmod doesn't need
>to know anything about the module (modprobe still does, but even that
>is very limited).

	Roman's module-init.o reduces or eliminates this difference.

>Shrinking insmod to 20 lines and putting it in
>busybox is nice, but being able to change the way parameters are
>parsed,

	I think the module parameters should be passed as an
argument to the init_module/insmod system call in either case.

>being able to switch reference count schemes, alter
>initialization or shutdown methods, rewrite module versioning to be
>sane, and otherwise tweak the kernel internals without breaking
>userspace is a huge win.

	For some changes, yes, but for some many other changes, a
scheme that uses Roman's module-init.o might not need any insmod
changes.  And, for an insmod as simple as Roman's mini-loader,
we could ship it with the kernel tree and install it in
/lib/modules/<version>/bin/.


>But let's ignore my ideas, and look at three things which have been
>suggested to me by other people since this patch went in.  Ted Ts'o's
>digital signatures on modules.  Obviously much simpler in kernelspace.

	No.  You're much more likely to have random crypto software in
user land.  User level authentication code can allocate memory more
freely, lookup up supporting certificates in external files, do
more elaborate more elaborate error handling like popping up a
dialog to say "The certificate for this module has expired.
Install it anyway?", or attempt to log the problem in
detail to a security server.

>The second is Keith Owens' NUMA text replication.  Now such a change
>is entirely up to the architecture (no modutils upgrade, sure, it will
>almost certainly break oprofile on them though for kernel hackers).

	Yes.  By the way, I assume that we're talking about the
read-only sections of a module being mapped to different physical
pages but having the same virtual addresses across all processors, by
the way.  User level insmod would need to be changed to load the
read-only sections separately.


>The third is David Woodhouse's "multiple init for modules".  There are
>some fundamental questions (each initfn must have a matching exitfn in
>case a later one fails), but this change wouldn't break userspace
>either.

	With something like module-{init,end}.o, this should not
require a further change to insmod.

	There are also a variety of changes which are easier with the
module loader in user land (saving ~100kB of unswappable space by
kicking the symbols out of the kernel, being able to load modules with
dependency loops).  Also, it's a small incremental difference, but
lowering the minimum resource costs of CONFIG_MODULES means that a
standard binary Linux kernel link kit may be a slightly more appealing
option to gadget makers in comparison to Vxworks, Windows NTE, CE, in
terms of engineering risk (e.g., what if the one kernel person who is
working on someone's digital music player quits).

	Anyhow, thank you very much for taking the time to explain
your case for kernel module loading.  I'm still thinking about it.


Regarding module loading tools that could support both user level
and kernel module loading:

>Sure: it'd definitely be worth distributing them together rather than
>the horrible install hack at the moment (there's a RPM which already
>does this).

	Good.

>I'd prefer a static parser which turns modules.conf into modprobe.conf
>rather than reimplementing modules.conf (config files which are so
>complex they need a "hobbled mode" in case they are called from
>untrusted context are in trouble already).

	Could we just use modules.conf and not support certain
commands?

>My plans were:
>
>1) Extend alias to be:
>
>	alias foo bar [and|or baz]...
>
>  Aliases would continue to insist that they resolve where defined (to
>  avoid loops).

	As we discussed, I suspect that we can insist that the names on
the right hand size must be actual module names, not aliases, at least
until someone complains and identifies a real use for aliases to
aliases.

>2) Implement "options" of course, which would stack (in case you
>   attach modules to an alias), and

	There are usually a small number of "options" lines that
people want to add, and I think that external packages that install
kernel module might want to install and remove those lines, so it
might be better to use the filesystem as the database for this, by
having small files like /etc/modules/args/ipsec_tunnel.


>3) Implement "install" (to allow arbitrary stuff like pre and post,
>   weirdass conditional stuff, etc).

	Then why not just run the existing modutils version of
modprobe?

	I've been thinking that perhaps we should eliminate
request_module() from the kernel and instead generate a "want"
hotplug event ("hotplug filesystem want ext3",
"hotplug devfs want /dev/discs/disc0/part3",  "hotplug soundcore want oss")
and move some of this complexity from modprobe to hotplug.  My
reason are:

	1. While we usually want to load a module in response to
	   these events, we might not always want to, and but we still
	   might want the "pre and post, weirdass conditional stuff, etc."
	   For example "hotplug devfs want /dev/discs/disc0/part3" may
	   just invoke "partx -a /dev/discs/disc0/disc".

	2. Walking a tree and loading a kernel module are probably best
	   done in C, while most of this other customization is
	   probably best done from shell scripts.

	3. There is a known security issue that users might
	   be able to cause a "dangerous" module to be loaded by
	   doing things like "ifconfig name-of-a-dangerous-module".

	4. Conceivably, we may want software packages that load a
	   set of hotplug functionality based on bus type, so it
	   would be helpful to use an interface that has the extra
	   argument for bus type as hotplug does.

	Maybe enough as been broken already, and this idea could be
pursued incrementally later if it's worth it.  Any comments would
be welcome.

	Also, thanks again for explaining your case for kernel module
loading.


Adam J. Richter     __     ______________   575 Oroville Road
adam@yggdrasil.com     \ /                  Milpitas, California 95035
+1 408 309-6081         | g g d r a s i l   United States of America
                         "Free Software For The Rest Of Us."


^ permalink raw reply	[flat|nested] 8+ messages in thread
[parent not found: <200211252254.OAA04288@freya.yggdrasil.com>]
* Patch?: module-init-tools/modprobe.c - use modules.dep
@ 2002-11-21 15:39 Adam J. Richter
  2002-11-25  5:47 ` Rusty Russell
  0 siblings, 1 reply; 8+ messages in thread
From: Adam J. Richter @ 2002-11-21 15:39 UTC (permalink / raw)
  To: rusty; +Cc: dwmw2, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2514 bytes --]

	The following patch changes modprobe in module-init-tools-0.8
to use modules.dep.

	Benefits:

	- deletes a net of 594 lines of source code

	- shrinks modprobe from 14kB to 10kB (stripped, dynamically linked),
	  which is useful for boot images

	- should make modprobe as fast on systems with a lot of modules as
	  it was with the user level module loader,

	- Restores the "include" command to the aliases file, which makes
	  it simpler to have separate files for automatically generated
	  aliases and user customizations.

	- minor: eliminates ELF dependence from modprobe user level code


	Drawbacks:

	- It makes modprobe require that depmod had been run at some
	  point (although it isn't necessary to put depmod on a boot
	  image to use modprobe; you just need it when you want to add
	  a module that you want modprobe to know about).  The current
	  depmod implementation is bigger than 594 lines of code, but
	  also generates hardware device tables, so systems that do
	  hardware autoconfiguration this way currently need depmod anyhow.

	- I have not tested these changes much, because the in-kernel
	  module loader reports "memory allocation failure" for many
	  modules that I try to load.  This does not appear to be
	  related to my changes.

	- I do not currently see a positive balance of real benefits
	  to putting the module linker in unswappable kernel memory.
	  If you're running a system with a user level module loader,
	  you are probably better off staying with that.

	Note to lmkl readers: this patch is again
module-init-tools-0.8.dwmw2, which is a modification done by David
Woodhouse of module-init-tools-0.7.  It is not an official release,
and it requires a kernel patch which changes the system call interface
for loading modules (to pass the module name).  I am posting a patch
against it instead of 0.7 because I don't want people applying this
patch and then breaking their systems due to the interface change.  I
am also attaching David's patches to this message (after checking with
him by email), but please do not refer to David's changes or mine as
releases of module-init-tools, as they both depend on David's kernel
changes, which may or may not be integrated into Linus's future
releases.

-- 
Adam J. Richter     __     ______________   575 Oroville Road
adam@yggdrasil.com     \ /                  Milpitas, California 95035
+1 408 309-6081         | g g d r a s i l   United States of America
                         "Free Software For The Rest Of Us."

[-- Attachment #2: mod-init-tools.diff --]
[-- Type: text/plain, Size: 31288 bytes --]

diff -u -r --new-file module-init-tools-0.8/Makefile.in module-init-tools-0.9.ajr/Makefile.in
--- module-init-tools-0.8/Makefile.in	2002-11-13 18:09:56.000000000 -0800
+++ module-init-tools-0.9.ajr/Makefile.in	2002-11-21 05:55:06.000000000 -0800
@@ -5,8 +5,8 @@
 
 default: insmod rmmod lsmod modprobe
 
-insmod.o rmmod.o lsmod.o: backwards_compat.c
-modprobe.o: backwards_compat.c mod32.c mod64.c mod_types.h
+insmod.o rmmod.o lsmod.o: backwards_compat.c mod_types.h
+modprobe.o: backwards_compat.c mod_types.h
 
 # Moving a link lsmod -> insmod requires two moves.
 %.old:
diff -u -r --new-file module-init-tools-0.8/mod32.c module-init-tools-0.9.ajr/mod32.c
--- module-init-tools-0.8/mod32.c	2002-11-13 18:15:24.000000000 -0800
+++ module-init-tools-0.9.ajr/mod32.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,158 +0,0 @@
-static void *load_section32(int fd, unsigned long shdroff,
-			    unsigned int num_secs,
-			    unsigned int secnamesec,
-			    const char *secname,
-			    unsigned long *size)
-{
-	Elf32_Shdr sechdrs[num_secs];
-	unsigned int i;
-	char *secnames;
-
-	/* Grab headers. */
-	lseek(fd, shdroff, SEEK_SET);
-	if (read(fd, sechdrs, sizeof(sechdrs)) != sizeof(sechdrs))
-		return (void*)-1;
-
-	/* Grab strings so we can tell who is who */
-	secnames = malloc(sechdrs[secnamesec].sh_size);
-	lseek(fd, sechdrs[secnamesec].sh_offset, SEEK_SET);
-	if (read(fd, secnames, sechdrs[secnamesec].sh_size)
-	    != sechdrs[secnamesec].sh_size) {
-		free(secnames);
-		return (void*)-1;
-	}
-
-
-	/* Find the section they want */
-	for (i = 1; i < num_secs; i++) {
-		if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
-			void *buf;
-
-			free(secnames);
-			*size = sechdrs[i].sh_size;
-			buf = malloc(*size);
-			if (lseek(fd, sechdrs[i].sh_offset, SEEK_SET) == -1
-			    || read(fd, buf, *size) != *size) {
-				free(buf);
-				return (void *)-1;
-			}
-			return buf;
-		}
-	}
-	free(secnames);
-	return NULL;
-}
-
-static void *map_exports32(int fd,
-			   unsigned long shdroff,
-			   unsigned int num_secs,
-			   unsigned int secnamesec,
-			   const char *name,
-			   unsigned int *num_exports)
-{
-	struct kernel_symbol32 *syms;
-	unsigned long size;
-
-	syms = load_section32(fd, shdroff, num_secs, secnamesec, "__ksymtab",
-			      &size);
-	*num_exports = 0;
-	if (syms == (void*)-1) {
-		warn("Error finding exports for module %s\n", name);
-		syms = NULL;
-	} else if (syms)
-		*num_exports = size / sizeof(struct kernel_symbol32);
-	return syms;
-}
-
-static int export_name_cmp32(struct module *m, int index, const char *name)
-{
-	return strcmp(m->u.exports32[index].name, name);
-}
-
-static struct module *add_module32(int fd, struct module *new,
-				   struct module *last,
-				   struct alias **aliases)
-{
-	Elf32_Ehdr hdr;
-
-	if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
-		warn("Error reading module %s\n", new->name);
-		free(new);
-		close(fd);
-		return last;
-	}
-
-	/* Map the section table */
-	new->u.ptr = mops->map_exports(fd, hdr.e_shoff, hdr.e_shnum,
-				       hdr.e_shstrndx, new->name,
-				       &new->num_exports);
-
-	/* Add in any aliases */
-	*aliases = add_aliases(fd, hdr.e_shoff, hdr.e_shnum,
-			       hdr.e_shstrndx, new, *aliases);
-
-	close(fd);
-	return new;
-}
-
-/* Analyse this module to see if it needs others. */
-static int get_deps32(unsigned int order,
-		      const char *dirname,
-		      const char *modname,
-		      struct module *modules,
-		      int verbose)
-{
-	unsigned int i;
-	unsigned long size;
-	Elf32_Ehdr hdr;
-	int fd;
-	char *strings;
-	Elf32_Sym *syms;
-	int needed = 0;
-	char modpath[strlen(dirname) + strlen(modname)
-		    + sizeof(MODULE_EXTENSION)];
-
-	sprintf(modpath, "%s%s%s", dirname, modname, MODULE_EXTENSION);
-	fd = open(modpath, O_RDONLY);
-	if (fd < 0)
-		fatal("Can't open module %s: %s\n", modpath, strerror(errno));
-
-	if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
-		fatal("Error reading module %s\n", modpath);
-
-	strings = mops->load_section(fd, hdr.e_shoff, hdr.e_shnum,
-				     hdr.e_shstrndx, ".strtab", &size);
-	syms = mops->load_section(fd, hdr.e_shoff, hdr.e_shnum,
-				  hdr.e_shstrndx, ".symtab", &size);
-	if (!strings || strings == (void *)-1
-	    || !syms || syms == (void *)-1) {
-		fatal("Could not load strings and symbol table from %s\n",
-		      modpath);
-	}
-
-	/* Now establish which modules we need */
-	for (i = 0; i < size / sizeof(syms[0]); i++) {
-		if (syms[i].st_shndx == SHN_UNDEF) {
-			/* Look for symbol */
-			const char *name = strings + syms[i].st_name;
-
-			if (strcmp(name, "") == 0)
-				continue;
-
-			/* Did this pull in a new module? */
-			if (need_symbol(order, name, modules,
-					verbose ? modpath : NULL))
-				needed = 1;
-		}
-	}
-	close(fd);
-	return needed;
-}
-
-static struct mod_ops mod32_ops = {
-	.load_section		=	load_section32,
-	.map_exports		=	map_exports32,
-	.export_name_cmp	=	export_name_cmp32,
-	.add_module		=	add_module32,
-	.get_deps		=	get_deps32,
-};
diff -u -r --new-file module-init-tools-0.8/mod64.c module-init-tools-0.9.ajr/mod64.c
--- module-init-tools-0.8/mod64.c	2002-11-13 18:15:57.000000000 -0800
+++ module-init-tools-0.9.ajr/mod64.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,158 +0,0 @@
-static void *load_section64(int fd, unsigned long shdroff,
-			    unsigned int num_secs,
-			    unsigned int secnamesec,
-			    const char *secname,
-			    unsigned long *size)
-{
-	Elf64_Shdr sechdrs[num_secs];
-	unsigned int i;
-	char *secnames;
-
-	/* Grab headers. */
-	lseek(fd, shdroff, SEEK_SET);
-	if (read(fd, sechdrs, sizeof(sechdrs)) != sizeof(sechdrs))
-		return (void*)-1;
-
-	/* Grab strings so we can tell who is who */
-	secnames = malloc(sechdrs[secnamesec].sh_size);
-	lseek(fd, sechdrs[secnamesec].sh_offset, SEEK_SET);
-	if (read(fd, secnames, sechdrs[secnamesec].sh_size)
-	    != sechdrs[secnamesec].sh_size) {
-		free(secnames);
-		return (void*)-1;
-	}
-
-
-	/* Find the section they want */
-	for (i = 1; i < num_secs; i++) {
-		if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
-			void *buf;
-
-			free(secnames);
-			*size = sechdrs[i].sh_size;
-			buf = malloc(*size);
-			if (lseek(fd, sechdrs[i].sh_offset, SEEK_SET) == -1
-			    || read(fd, buf, *size) != *size) {
-				free(buf);
-				return (void *)-1;
-			}
-			return buf;
-		}
-	}
-	free(secnames);
-	return NULL;
-}
-
-static void *map_exports64(int fd,
-			   unsigned long shdroff,
-			   unsigned int num_secs,
-			   unsigned int secnamesec,
-			   const char *name,
-			   unsigned int *num_exports)
-{
-	struct kernel_symbol64 *syms;
-	unsigned long size;
-
-	syms = load_section64(fd, shdroff, num_secs, secnamesec, "__ksymtab",
-			      &size);
-	*num_exports = 0;
-	if (syms == (void*)-1) {
-		warn("Error finding exports for module %s\n", name);
-		syms = NULL;
-	} else if (syms)
-		*num_exports = size / sizeof(struct kernel_symbol64);
-	return syms;
-}
-
-static int export_name_cmp64(struct module *m, int index, const char *name)
-{
-	return strcmp(m->u.exports64[index].name, name);
-}
-
-static struct module *add_module64(int fd, struct module *new,
-				   struct module *last,
-				   struct alias **aliases)
-{
-	Elf64_Ehdr hdr;
-
-	if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
-		warn("Error reading module %s\n", new->name);
-		free(new);
-		close(fd);
-		return last;
-	}
-
-	/* Map the section table */
-	new->u.ptr = mops->map_exports(fd, hdr.e_shoff, hdr.e_shnum,
-				       hdr.e_shstrndx, new->name,
-				       &new->num_exports);
-	/* Add in any aliases */
-	*aliases = add_aliases(fd, hdr.e_shoff, hdr.e_shnum,
-			       hdr.e_shstrndx, new, *aliases);
-
-	close(fd);
-	return new;
-}
-
-/* Analyse this module to see if it needs others. */
-static int get_deps64(unsigned int order,
-		      const char *dirname,
-		      const char *modname,
-		      struct module *modules,
-		      int verbose)
-{
-	unsigned int i;
-	unsigned long size;
-	Elf64_Ehdr hdr;
-	int fd;
-	char *strings;
-	Elf64_Sym *syms;
-	int needed = 0;
-	char modpath[strlen(dirname) + strlen(modname)
-		    + sizeof(MODULE_EXTENSION)];
-
-	sprintf(modpath, "%s%s%s", dirname, modname, MODULE_EXTENSION);
-
-	fd = open(modpath, O_RDONLY);
-	if (fd < 0)
-		fatal("Can't open module %s: %s\n", modpath, strerror(errno));
-
-	if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
-		fatal("Error reading module %s\n", modpath);
-
-	strings = mops->load_section(fd, hdr.e_shoff, hdr.e_shnum,
-				     hdr.e_shstrndx, ".strtab", &size);
-	syms = mops->load_section(fd, hdr.e_shoff, hdr.e_shnum,
-				  hdr.e_shstrndx, ".symtab", &size);
-	if (!strings || strings == (void *)-1
-	    || !syms || syms == (void *)-1) {
-		fatal("Could not load strings and symbol table from %s\n",
-		      modpath);
-	}
-
-	/* Now establish which modules we need */
-	for (i = 0; i < size / sizeof(syms[0]); i++) {
-		if (syms[i].st_shndx == SHN_UNDEF) {
-			/* Look for symbol */
-			const char *name = strings + syms[i].st_name;
-
-			if (strcmp(name, "") == 0)
-				continue;
-
-			/* Did this pull in a new module? */
-			if (need_symbol(order, name, modules,
-					verbose ? modpath : NULL))
-				needed = 1;
-		}
-	}
-	close(fd);
-	return needed;
-}
-
-static struct mod_ops mod64_ops = {
-	.load_section		=	load_section64,
-	.map_exports		=	map_exports64,
-	.export_name_cmp	=	export_name_cmp64,
-	.add_module		=	add_module64,
-	.get_deps		=	get_deps64,
-};
diff -u -r --new-file module-init-tools-0.8/mod_types.h module-init-tools-0.9.ajr/mod_types.h
--- module-init-tools-0.8/mod_types.h	2002-11-13 18:14:41.000000000 -0800
+++ module-init-tools-0.9.ajr/mod_types.h	2002-11-21 05:13:16.000000000 -0800
@@ -1,65 +1 @@
-struct kernel_symbol32 {
-	char value[4];
-	char name[64 - 4];
-};
-
-struct kernel_symbol64 {
-	char value[8];
-	char name[64 - 8];
-};
-
-/* All the modules kept in this list */
-struct module
-{
-	struct module *next;
-
-	/* mmaped export symbols area */
-	unsigned int num_exports;
-	union {
-		struct kernel_symbol32 *exports32;
-		struct kernel_symbol64 *exports64;
-		void *ptr;
-	} u;
-
-	/* What order it has to be loaded (0 = never). */
-	unsigned int order;
-
-	/* full path name */
-	char name[0];
-};
-
-struct alias
-{
-	struct alias *next;
-	/* One of these two is set. */
-	struct module *module;
-	struct alias *alias;
-	/* Line in config where this was defined */
-	int config_line;
-	char name[0];
-};
-
-struct mod_ops {
-	struct module *(*add_module)(int fd, struct module *new,
-				     struct module *last,
-				     struct alias **aliases);
-	void *(*load_section)(int fd, unsigned long shdroff,
-			      unsigned int num_secs,
-			      unsigned int secnamesec,
-			      const char *secname,
-			      unsigned long *size);
-	void *(*map_exports)(int fd,
-			     unsigned long shdroff,
-			     unsigned int num_secs,
-			     unsigned int secnamesec,
-			     const char *name,
-			     unsigned int *num_exports);
-	int (*export_name_cmp)(struct module *m, int index, const char *name);
-	int (*get_deps)(unsigned int order,
-			const char *dirname,
-			const char *modname,
-			struct module *modules,
-			int verbose);
-};
-
 #define MODULE_EXTENSION ".o"
diff -u -r --new-file module-init-tools-0.8/modprobe.c module-init-tools-0.9.ajr/modprobe.c
--- module-init-tools-0.8/modprobe.c	2002-11-20 14:30:32.000000000 -0800
+++ module-init-tools-0.9.ajr/modprobe.c	2002-11-21 05:37:16.000000000 -0800
@@ -39,11 +39,21 @@
 
 #include "mod_types.h"
 
-#define MODULE_DIR "/lib/modules/%s/kernel/"
+struct module_list;
 
-/* We decide when we hit the first module whether we are 32 or 64-bit,
-   and set this. */
-static struct mod_ops *mops;
+struct module {
+	struct module		*next;
+	struct module_list	*dependencies;
+	enum { NOT_LOADED = 0, BEING_LOADED, LOADED } state;
+	char			filename[0];
+};
+
+struct module_list {
+	struct module		*module;
+	struct module_list	*next;
+};
+
+#define MODULE_DIR "/lib/modules"
 
 static void fatal(const char *fmt, ...)
 __attribute__ ((noreturn, format (printf, 1, 2)));
@@ -75,20 +85,16 @@
 	va_end(arglist);
 }
 
-static struct alias *add_aliases(int fd,
-				 unsigned long shdroff,
-				 unsigned int num_secs,
-				 unsigned int secnamesec,
-				 struct module *mod,
-				 struct alias *last);
-
-static int need_symbol(unsigned int order,
-		       const char *name,
-		       struct module *modules,
-		       const char *modname);
+static void *do_nofail(void *ptr, const char *file, int line, const char *expr)
+{
+	if (!ptr) {
+		fatal("Memory allocation failure %s line %d: %s.\n",
+		      file, line, expr);
+	}
+	return ptr;
+}
 
-#include "mod32.c"
-#include "mod64.c"
+#define NOFAIL(ptr)	do_nofail((ptr), __FILE__, __LINE__, #ptr)
 
 static void print_usage(const char *progname)
 {
@@ -98,185 +104,122 @@
 	exit(1);
 }
 
-static int ends_in(const char *name, const char *ext)
+static int fgetc_wrapped(FILE *file)
 {
-	unsigned int namelen, extlen, i;
-
-	/* Grab lengths */
-	namelen = strlen(name);
-	extlen = strlen(ext);
-
-	if (namelen < extlen) return 0;
-
-	/* Look backwards */
-	for (i = 0; i < extlen; i++)
-		if (name[namelen - i] != ext[extlen - i]) return 0;
-
-	return 1;
+	for (;;) {
+	  	int ch = fgetc(file);
+		if (ch != '\\')
+			return ch;
+		ch = fgetc(file);
+		if (ch != '\n')
+			return ch;
+	}
 }
 
-/* FIXME: Loop detect. */
-static struct alias *find_alias(const char *name, struct alias *aliases)
-{
-	struct alias *i;
-
-	for (i = aliases; i; i = i->next)
-		if (fnmatch(i->name, name, 0) == 0) {
-			/* Chase down alias to aliases */
-			while (i->alias)
-				i = i->alias;
-			return i;
+static char *getline_wrapped(FILE *file)
+{
+	int size = 1024;
+	int i = 0;
+	char *buf = NOFAIL(malloc(size));
+	for(;;) {
+		int ch = fgetc_wrapped(file);
+		if (i == size) {
+			size *= 2;
+			buf = NOFAIL(realloc(buf, size));
 		}
-
-	return NULL;
+		if (ch < 0 || ch == '\n') {
+			if (ch < 0 && i == 0) {
+				free(buf);
+				return NULL;
+			}
+			buf[i] = '\0';
+			return NOFAIL(realloc(buf, i+1));
+		}
+		buf[i++] = ch;
+	}
 }
 
-static struct alias *add_alias(struct alias *last,
-			       const char *aliasname,
-			       struct module *mod,
-			       struct alias *alias,
-			       int linenum)
-{
-	struct alias *newalias;
-
-	newalias = malloc(sizeof *newalias + strlen(aliasname) + 1);
-	strcpy(newalias->name, aliasname);
-	newalias->config_line = linenum;
-	newalias->module = mod;
-	newalias->alias = alias;
+struct module *modules;		/* = NULL */
 
-	newalias->next = last;
-	return newalias;
-}
-
-static struct alias *add_aliases(int fd,
-				 unsigned long shdroff,
-				 unsigned int num_secs,
-				 unsigned int secnamesec,
-				 struct module *mod,
-				 struct alias *last)
+struct module *get_module(char *filename, int namelen)
 {
-	char *aliases;
-	unsigned long size, i;
-
-	aliases = mops->load_section(fd, shdroff, num_secs, secnamesec,
-				     ".modalias",  &size);
-	if (aliases == (void *)-1) {
-		warn("Error loading aliases from module %s\n", mod->name);
-		return last;
+	struct module *mod;
+	for (mod = modules; mod; mod = mod->next) {
+		if (strlen(mod->filename) == namelen &&
+		    memcmp(mod->filename, filename, namelen) == 0)
+			return mod;
 	}
 
-	if (aliases) {
-		for (i = 0; i < size; i += strlen(aliases+i)+1)
-			last = add_alias(last, aliases+i, mod, NULL, 0);
-		free(aliases);
-	}
-	return last;
+	/* No match.  Make a new module. */
+	mod = NOFAIL(malloc(sizeof(struct module) + namelen + 1));
+	memset(mod, 0, sizeof(struct module));
+	memcpy(mod->filename, filename, namelen);
+	mod->filename[namelen] = '\0';
+	mod->next = modules;
+	modules = mod;
+	return mod;
 }
 
-static struct module *add_module(const char *dirname, const char *entry,
-				 struct module *last, struct alias **aliases)
+static void add_modules_dep_line(char *line, const char *start_name,
+				 struct module **start)
 {
-	int fd;
-	struct module *new;
-	char pathname[strlen(dirname) + strlen(entry) + 1];
+	struct module_list *dep;
+	char *dep_start;
+	struct module *mod, *dep_mod;
+	char *ptr;
+	int len;
+	char *modname;
 
-	new = malloc(sizeof(*new) + strlen(entry) + 1);
-	strcpy(new->name, entry);
-	/* Truncate extension */
-	new->name[strlen(new->name) - strlen(MODULE_EXTENSION)] = '\0';
-	new->order = 0;
-	new->next = last;
+	ptr = index(line, ':');
+	if (ptr == NULL || line[0] == '#')
+		return;
 
-	sprintf(pathname, "%s%s", dirname, entry);
-	fd = open(pathname, O_RDONLY);
-	if (fd < 0) {
-		warn("Can't read module %s: %s\n", pathname, strerror(errno));
-		free(new);
-		return last;
-	}
+	mod = get_module(line, ptr - line);
 
-	/* First call initializes this. */
-	if (!mops) {
-		/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
-		char ident[EI_NIDENT];
+	modname = rindex(mod->filename, '/') + 1;
+	len = strlen(modname) - sizeof(MODULE_EXTENSION) + 1;
 
-		if (read(fd, ident, EI_NIDENT) != EI_NIDENT) {
-			warn("Can't read module %s elf identifier: %s\n",
-			     pathname, strerror(errno));
-			free(new);
-			return last;
-		}
-		switch (ident[EI_CLASS]) {
-		case ELFCLASS32:
-			mops = &mod32_ops;
-			break;
-		case ELFCLASS64:
-			mops = &mod64_ops;
+	if (len == strlen(start_name) && !strncmp(modname, start_name, len))
+		*start = mod;
+
+	ptr++;
+	for(;;) {
+		ptr += strspn(ptr, " \t");
+		if (*ptr == '\0')
 			break;
-		default:
-			warn("Module %s has elf unknown identifier %i\n",
-			     pathname, ident[EI_CLASS]);
-			free(new);
-			return last;
-		}
-		lseek(fd, 0, SEEK_SET);
+		dep_start = ptr;
+		ptr += strcspn(ptr, " \t");
+		dep_mod = get_module(dep_start, ptr - dep_start);
+		fflush(stdout);
+		dep = NOFAIL(malloc(sizeof(*dep)));
+		dep->module = dep_mod;
+		dep->next = mod->dependencies;
+		mod->dependencies = dep;
 	}
-
-	return mops->add_module(fd, new, last, aliases);
 }
 
-static struct module *load_all_modules(const char *dirname,
-				       struct alias **aliases)
+static void load_all_modules(const char *dirname,
+			     const char *start_name,
+			     struct module **start)
 {
-	struct module *mods = NULL;
-	struct dirent *dirent;
-	DIR *dir;
+	char modules_dep_name[strlen(dirname) + sizeof("modules.dep") + 1];
+	char *line;
+	FILE *modules_dep;
 
-	dir = opendir(dirname);
-	if (dir) {
-		while ((dirent = readdir(dir)) != NULL) {
-			/* Is it a .o file? */
-			if (ends_in(dirent->d_name, MODULE_EXTENSION))
-				mods = add_module(dirname, dirent->d_name,
-						  mods, aliases);
-		}
-		closedir(dir);
+	*start = NULL;
+	sprintf(modules_dep_name, "%s/%s", dirname, "modules.dep");
+	modules_dep = fopen(modules_dep_name, "r");
+	if (!modules_dep) {
+		perror(modules_dep_name);
+		exit(1);
 	}
-	return mods;
-}
 
-static int need_symbol(unsigned int order,
-		       const char *name,
-		       struct module *modules,
-		       const char *modname)
-{
-	struct module *m;
-	struct module *found = NULL;
-
-	for (m = modules; m; m = m->next) {
-		unsigned int i;
-		for (i = 0; i < m->num_exports; i++) {
-			if (mops->export_name_cmp(m, i, name) == 0) {
-				if (found) {
-					warn("%s supplied by %s and %s:"
-					     " picking neither\n",
-					     name, m->name, found->name);
-					/* Noone chosen */
-					return 0;
-				}
-				if (modname)
-					printf("%s needs %s: found in %s\n",
-					       modname, name, m->name);
-				found = m;
-				/* If we didn't need to load it
-                                   already, we do now. */
-				found->order = order;
-			}
-		}
+	while((line = getline_wrapped(modules_dep)) != NULL) {
+		add_modules_dep_line(line, start_name, start);
+		free(line);
 	}
-	if (found) return 1;
-	else return 0;
+
+	fclose(modules_dep);
 }
 
 /* We use error numbers in a loose translation... */
@@ -292,308 +235,150 @@
 	}
 }
 
+static int
+module_in_kernel(const char *modname)
+{
+	FILE *proc_modules;
+	char *line;
+	const int modname_len = strlen(modname);
+	
+	proc_modules = fopen("/proc/modules", "r");
+	if (proc_modules == NULL)
+		fatal("Error reading /proc/modules: %s\n", strerror(errno));
+
+	while ((line = getline_wrapped(proc_modules)) != NULL) {
+		if (strncmp(line, modname, modname_len) == 0 &&
+		    isspace(line[modname_len])) {
+			free(line);
+			fclose(proc_modules);
+			return 1;
+		}
+		free(line);
+	}
+	fclose(proc_modules);
+	return 0;
+}
+
 /* Actually do the insert. */
-static void insmod(const char *dirname,
-		   const char *filename,
-		   const char *options,
-		   int dont_fail)
+static void insmod(struct module *mod, const char *options, int dont_fail,
+		   struct module_list *caller)
 {
 	int fd, ret;
 	struct stat st;
 	unsigned long len;
 	void *map;
-	char modpath[strlen(dirname) + strlen(filename)
-		    + sizeof(MODULE_EXTENSION)];
+	struct module_list *dep;
+	unsigned int i;
+	char modname[strlen(strrchr(mod->filename, '/'))];
+	struct module_list call_history, *modlist;
+
+	if (mod->state == LOADED)
+		return;
+
+	call_history.next = caller;
+	call_history.module = mod;
+
+	if (mod->state == BEING_LOADED) {
+		fprintf (stderr, "FATAL: recursive dependency loop:\n");
+		modlist = &call_history;
+		do {
+			fprintf(stderr, "\t%s\n", modlist->module->filename);
+			modlist = modlist->next;
+		} while (modlist != NULL);
+		exit(1);
+	}
 
-	/* FIXME: Look in module for name. --RR */
-	sprintf(modpath, "%s%s%s", dirname, filename, MODULE_EXTENSION);
+	mod->state = BEING_LOADED;
+
+	for(dep = mod->dependencies; dep != NULL; dep = dep->next)
+		insmod(dep->module, options, 0, &call_history);
+
+	/* If we fail to load after this piont, we abort the whole program. */
+	mod->state = LOADED;
 
 	/* Now, it may already be loaded: check /proc/modules */
-	fd = open("/proc/modules", O_RDONLY);
-	if (fd < 0) {
-		warn("Cannot open /proc/modules:"
-		     " assuming no modules loaded.\n");
-	} else {
-		char *buf;
-		unsigned int fill, size = 1024;
-
-		buf = malloc(size+1);
-		buf[0] = '\n';
-		fill = 1;
 
-		while ((ret = read(fd, buf+fill, size - fill)) > 0) {
-			size *= 2;
-			buf = realloc(buf, size+1);
-			fill += ret;
-		}
-		if (ret < 0)
-			fatal("Error reading /proc/modules: %s\n",
-			      strerror(errno));
-		else {
-			char *ptr;
-			unsigned int i;
-			char name_with_ret[strlen(strrchr(modpath, '/')) + 2];
-
-			buf[fill+1] = '\0';
-			/* Must appear at start of line. */
-			name_with_ret[0] = '\n';
-			strcpy(name_with_ret + 1, strrchr(modpath, '/') + 1);
+	strcpy(modname, strrchr(mod->filename, '/') + 1);
 			
-			/* Convert to underscores */
-			for (i = 0; name_with_ret[i]; i++)
-				if (name_with_ret[i] == '-')
-					name_with_ret[i] = '_';
-
-			for (ptr = buf;
-			     (ptr = strstr(ptr, name_with_ret)) != NULL;
-			     ptr++) {
-				if (!isspace(ptr[strlen(name_with_ret)]))
-					continue;
-				/* Found: don't try to load again */
-				if (dont_fail)
-					fatal("Module %s already loaded\n",
-					      name_with_ret+1);
-				close(fd);
-				free(buf);
-				return;
-			}
-		}
-		close(fd);
-		free(buf);
-	}
-	close(fd);
+	/* Convert to underscores */
+	for (i = 0; modname[i]; i++)
+		if (modname[i] == '-')
+			modname[i] = '_';
+
+	modname[strlen(modname) - sizeof(MODULE_EXTENSION) + 1] = '\0';
+	if (module_in_kernel(modname))
+		return;
 
-	fd = open(modpath, O_RDONLY);
+	fd = open(mod->filename, O_RDONLY);
 	if (fd < 0)
-		fatal("Could not open `%s': %s\n", modpath, strerror(errno));
+		fatal("Could not open `%s': %s\n", mod->filename, strerror(errno));
 
 	fstat(fd, &st);
 	len = st.st_size;
 	map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
 	if (map == MAP_FAILED)
-		fatal("Can't map `%s': %s\n", modpath, strerror(errno));
+		fatal("Can't map `%s': %s\n", mod->filename, strerror(errno));
 
-	ret = syscall(__NR_init_module, filename, map, len, options);
+	ret = syscall(__NR_init_module, modname, map, len, options);
 	if (ret != 0) {
 		if (dont_fail)
-			fatal("Error inserting %s: %s\n",
-			      modpath, moderror(errno));
+			fatal("Error inserting %s (%s): %s\n",
+			      modname, mod->filename, moderror(errno));
 		else
-			warn("Error inserting %s: %s\n",
-			     modpath, moderror(errno));
+			warn("Error inserting %s (%s): %s\n",
+			     modname, mod->filename, moderror(errno));
 	}
 	close(fd);
 }
 
-/* Read one line into the buffer */
-static char *read_line(FILE *f)
-{
-	int size = 80;
-	char *result = malloc(size);
-
-	result[0] = '\0';
-	while (fgets(result + strlen(result), size - strlen(result), f)) {
-		char *nl = strchr(result, '\n');
-		if (nl) {
-			*nl = '\0';
-			return result;
-		}
-		size *= 2;
-		result = realloc(result, size);
-	}
-	if (strlen(result)) {
-		warn("Unexpected error reading config file: %s\n",
-		     strerror(errno));
-		return result;
-	}
-	free(result);
-	return NULL;
-}
-
-static struct module *find_module(const char *name, struct module *modules)
-{
-	struct module *m;
-
-	for (m = modules; m; m = m->next)
-		if (strcmp(name, m->name) == 0)
-			return m;
-	return NULL;
-}
-
-static char *get_word(const char **line)
+static char *strsep_skipspace(char **string, char *delim)
 {
-	size_t len;
-	char *word = NULL;
-
-	*line += strspn(*line, "\t ");
-	len = strcspn(*line, "\t ");
-	if (**line) {
-		word = strdup(*line);
-		word[len] = '\0';
-	}
-	*line += len;
-
-	return word;
-}
-
-/* alias newname oldname */
-static struct alias *parse_alias(struct alias *last, const char *line,
-				 int linenum,
-				 struct module *modules)
-{
-	char *newname, *oldname;
-	struct alias *aliasto;
-	struct module *moduleto = NULL;
-
-	newname = get_word(&line);
-	if (!newname) {
-		warn("Config line %i missing first arg\n", linenum);
-		return last;
-	}
-	oldname = get_word(&line);
-	if (!oldname) {
-		warn("Config line %i missing second arg\n", linenum);
-		free(newname);
-		return last;
-	}
-
-	aliasto = find_alias(oldname, last);
-	if (aliasto || (moduleto = find_module(oldname, modules)))
-		last = add_alias(last, newname, moduleto, aliasto, linenum);
-	else
-		warn("Config line %i aliases to unknown module %s\n",
-		     linenum, oldname);
-
-	free(oldname);
-	free(newname);
-	return last;
-}
-
-static int keyword(const char *line, const char *keyword)
-{
-	size_t len = strcspn(line, "\t ");
-
-	if (len == strlen(keyword)
-	    && memcmp(line, keyword, len) == 0)
-		return 1;
-	return 0;
+	*string += strspn(*string, delim);
+	return strsep(string, delim);
 }
 
 /* Simple format, ignore lines starting with #, one command per line */
-static void load_config_file(const char *filename, int mustload,
-			     struct module *modules,
-			     struct alias **aliases)
+static char *get_alias(const char *filename, int mustload, char *name)
 {
 	FILE *cfile;
 	char *line;
-	int linenum = 1;
+	char *result = NULL;
 
 	cfile = fopen(filename, "r");
 	if (!cfile) {
 		if (mustload)
 			fatal("Failed to open config file %s: %s\n",
 			      filename, strerror(errno));
-		return;
-	}
-
-	while ((line = read_line(cfile)) != NULL) {
-		size_t len;
-		len = strspn(line, "\t ");
-		/* Comment or blank? */
-		if (line[len] == '#' || line[len] == '\0')
-			goto next;
-		else if (keyword(line+len, "alias"))
-			*aliases = parse_alias(*aliases, line+len+strlen("alias"),
-					       linenum, modules);
-		else
-			fatal("Unknown line %s in config file\n", line);
-	next:
-		free(line);
-		linenum++;
+		return NOFAIL(strdup(name));
 	}
-}
 
-static char *resolve_alias(const char *name,
-			   struct module *modules,
-			   struct alias *aliases)
-{
-	struct module *m;
-	struct alias *a;
+	while ((line = getline_wrapped(cfile)) != NULL) {
+		char *ptr = line;
+		char *cmd = strsep_skipspace(&ptr, "\t ");
 
-	a = find_alias(name, aliases);
-	if (a)
-		return a->module->name;
+		if (cmd == NULL)
+			continue;
 
-	m = find_module(name, modules);
-	if (m)
-		return m->name;
+		if (strcmp(cmd, "alias") == 0) {
+			char *fakename = strsep_skipspace(&ptr, "\t ");
+			char *realname = strsep_skipspace(&ptr, "\t ");
 
-	fatal("Could not find a module or alias named %s\n",
-	      name);
-}
-
-static void load_symbol(const char *dirname,
-			const char *symname,
-			struct module *modules,
-			const char *options,
-			int verbose)
-{
-	struct module *i;
-
-	if (!need_symbol(1, symname, modules, verbose?"symbol request":NULL))
-		fatal("Could not find module with symbol %s\n", symname);
-
-	for (i = modules; i; i = i->next) {
-		if (i->order) {
-			if (verbose) printf("Loading %s\n", i->name);
-			insmod(dirname, i->name, options, 1);
-		}
-	}
-}
-
-static void load(const char *dirname, const char *modname,
-		 struct module *modules,
-		 struct alias *aliases,
-		 const char *options,
-		 int verbose)
-{
-	unsigned int order;
-	struct module *i;
-	char *realname;
-
-	realname = resolve_alias(modname, modules, aliases);
-
-	order = 1;
-	if (mops->get_deps(order, dirname, realname, modules, verbose)) {
-		/* We need some other modules. */
-		int more_needed;
-
-		do {
-			more_needed = 0;
-			for (i = modules; i; i = i->next) {
-				if (i->order == order) {
-					if (mops->get_deps(order + 1, dirname,
-							   i->name,
-							   modules, verbose))
-						more_needed = 1;
-				}
-			}
-			order++;
-		} while (more_needed);
-	}
-
-	/* Now, walk back through orders, loading */
-	for (; order > 0; order--) {
-		for (i = modules; i; i = i->next) {
-			if (i->order == order) {
-				if (verbose) printf("Loading %s\n", i->name);
-				insmod(dirname, i->name, "", 0);
+			if (fakename && realname && !strcmp(fakename, name)) {
+				result = NOFAIL(strdup(realname));
+				free(line);
+				break;
 			}
 		}
+		else if (strcmp(cmd, "include") == 0) {
+			filename = strsep(&ptr, "\t ");
+			result = get_alias(filename, 0, name);
+			if (result)
+				break;
+		}
+		free(line);
 	}
-	if (verbose)
-		printf("Loading %s%s%s\n", dirname, realname,MODULE_EXTENSION);
-	insmod(dirname, realname, options, 1);
+	fclose(cfile);
+	return result;
 }
 
 static struct option options[] = { { "verbose", 0, NULL, 'v' },
@@ -608,10 +393,10 @@
 	struct utsname buf;
 	int opt;
 	int verbose = 0;
-	struct alias *aliases = NULL;
-	struct module *modules;
 	const char *config = NULL;
-	char *dirname, *optstring = strdup("");
+	char *dirname, *optstring = NOFAIL(strdup(""));
+	char *modname;
+	struct module *start;
 
 	try_old_version("modprobe", argv);
 
@@ -651,22 +436,23 @@
 	}
 
 	uname(&buf);
-	dirname = malloc(strlen(buf.release) + sizeof(MODULE_DIR));
-	sprintf(dirname, MODULE_DIR, buf.release);
+	dirname = malloc(strlen(buf.release) + sizeof(MODULE_DIR) + 1);
+	sprintf(dirname, "%s/%s", MODULE_DIR, buf.release);
 
-	/* Suck up the modules */
-	modules = load_all_modules(dirname, &aliases);
+	modname = get_alias(config ?: DEFAULT_CONFIG, config ? 1 : 0,
+			    argv[optind]);
 
-	/* No config file specified?  Don't worry if it doesn't exist. */
-	load_config_file(config ?: DEFAULT_CONFIG, config ? 1 : 0,
-			 modules, &aliases);
-
-	/* Special case for "symbol:" */
-	if (strncmp(argv[optind], "symbol:", strlen("symbol:")) == 0)
-		load_symbol(dirname, argv[optind] + strlen("symbol:"), 
-			    modules, optstring, verbose);
-	else
-		load(dirname, argv[optind], modules, aliases, optstring,
-		     verbose);
-	exit(0);
+	if (modname == NULL)
+		modname = argv[optind];
+
+	load_all_modules(dirname, modname, &start);
+	if (start == NULL) {
+		fprintf (stderr, "Module %s not found.\n", modname);
+		exit(1);
+	}
+
+	insmod(start, optstring, 1, NULL);
+
+	/* free(modname);	-- Comment out.  We're just going to exit. */
+	return 0;
 }

[-- Attachment #3: dwmw2-module-init-tools.patch --]
[-- Type: text/plain, Size: 2292 bytes --]

diff -ur module-init-tools-0.7/CHANGES module-init-tools-0.8/CHANGES
--- module-init-tools-0.7/CHANGES	Thu Nov 14 02:09:28 2002
+++ module-init-tools-0.8/CHANGES	Wed Nov 20 13:32:39 2002
@@ -1,3 +1,4 @@
+o Add module name argument to sys_init_module()
 o 64/32 bit autodetection thanks to Dave Miller
 o Preliminary alias support.
 o Very primitive /etc/modprobe.conf support
diff -ur module-init-tools-0.7/insmod.c module-init-tools-0.8/insmod.c
--- module-init-tools-0.7/insmod.c	Wed Nov 13 22:33:32 2002
+++ module-init-tools-0.8/insmod.c	Wed Nov 20 13:32:05 2002
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <asm/unistd.h>
 
+#include "mod_types.h"
 #include "backwards_compat.c"
 
 static void print_usage(const char *progname)
@@ -62,15 +63,22 @@
 	unsigned long len;
 	void *map;
 	char *filename, *options = strdup("");
+	char *modname = NULL;
 
 	try_old_version("insmod", argv);
 
-	filename = argv[1];
+	i = 1;
+	if (argc > 3 && !strcmp(argv[1], "-o")) {
+		modname = argv[2];
+		i = 3;
+	}
+	
+	filename = argv[i++];
 	if (!filename)
 		print_usage(argv[0]);
 
 	/* Rest is options */
-	for (i = 2; i < argc; i++) {
+	for ( ; i < argc; i++) {
 		options = realloc(options,
 				  strlen(options) + 2 + strlen(argv[i]) + 2);
 		/* Spaces handled by "" pairs, but no way of escaping
@@ -99,7 +107,20 @@
 		exit(1);
 	}
 
-	ret = syscall(__NR_init_module, map, len, options);
+	if (!modname) {
+		char *ext;
+		modname = strrchr(filename, '/');
+		if (modname)
+			modname++;
+		else
+			modname = filename;
+
+		ext = strrchr(modname, '.');
+		if (ext && !strcmp(ext, MODULE_EXTENSION))
+			*ext = 0;
+	}
+		
+	ret = syscall(__NR_init_module, modname, map, len, options);
 	if (ret != 0) {
 		fprintf(stderr, "Error inserting `%s': %li %s\n",
 			filename, ret, moderror(errno));
diff -ur module-init-tools-0.7/modprobe.c module-init-tools-0.8/modprobe.c
--- module-init-tools-0.7/modprobe.c	Thu Nov 14 02:29:24 2002
+++ module-init-tools-0.8/modprobe.c	Wed Nov 20 13:32:00 2002
@@ -373,7 +373,7 @@
 	if (map == MAP_FAILED)
 		fatal("Can't map `%s': %s\n", modpath, strerror(errno));
 
-	ret = syscall(__NR_init_module, map, len, options);
+	ret = syscall(__NR_init_module, filename, map, len, options);
 	if (ret != 0) {
 		if (dont_fail)
 			fatal("Error inserting %s: %s\n",


[-- Attachment #4: dwmw2-kernel.patch --]
[-- Type: text/plain, Size: 5448 bytes --]

--- 1.17/include/linux/init.h	Sat Nov  9 04:08:33 2002
+++ edited/include/linux/init.h	Wed Nov 20 10:48:28 2002
@@ -125,14 +125,6 @@
  */
 #define module_exit(x)	__exitcall(x);
 
-/**
- * no_module_init - code needs no initialization.
- *
- * The equivalent of declaring an empty init function which returns 0.
- * Every module must have exactly one module_init() or no_module_init
- * invocation.  */
-#define no_module_init
-
 #else /* MODULE */
 
 /* Don't use these in modules, but some people do... */
@@ -144,10 +136,6 @@
 #define device_initcall(fn)		module_init(fn)
 #define late_initcall(fn)		module_init(fn)
 
-/* Each module knows its own name. */
-#define __DEFINE_MODULE_NAME						\
-	char __module_name[] __attribute__((section(".modulename"))) =	\
-	__stringify(KBUILD_MODNAME)
 
 /* These macros create a dummy inline: gcc 2.9x does not count alias
  as usage, hence the `unused function' warning when __init functions
@@ -155,14 +143,11 @@
  both to kill the warning and check the type of the init/cleanup
  function. */
 
-/* Each module must use one module_init(), or one no_module_init */
+/* Each module must use no more than one module_init() */
 #define module_init(initfn)					\
-	__DEFINE_MODULE_NAME;					\
 	static inline initcall_t __inittest(void)		\
 	{ return initfn; }					\
 	int __initfn(void) __attribute__((alias(#initfn)));
-
-#define no_module_init __DEFINE_MODULE_NAME
 
 /* This is only required if you want to be unloadable. */
 #define module_exit(exitfn)					\
===== include/linux/module.h 1.25 vs edited =====
--- 1.25/include/linux/module.h	Tue Nov 19 04:51:14 2002
+++ edited/include/linux/module.h	Wed Nov 20 10:08:30 2002
@@ -297,8 +297,6 @@
 /* Used as "int init_module(void) { ... }".  Get funky to insert modname. */
 #define init_module(voidarg)						\
 	__initfn(void);							\
-	char __module_name[] __attribute__((section(".modulename"))) =	\
-	__stringify(KBUILD_MODNAME);					\
 	int __initfn(void)
 #define cleanup_module(voidarg) __exitfn(void)
 #endif
===== kernel/module.c 1.25 vs edited =====
--- 1.25/kernel/module.c	Tue Nov 19 04:51:14 2002
+++ edited/kernel/module.c	Wed Nov 20 10:54:47 2002
@@ -800,15 +800,15 @@
 }
 
 /* Allocate and load the module */
-static struct module *load_module(void *umod,
+static struct module *load_module(const char *modname,
+				  void *umod,
 				  unsigned long len,
 				  const char *uargs)
 {
 	Elf_Ehdr *hdr;
 	Elf_Shdr *sechdrs;
 	char *secstrings;
-	unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
-		modnameindex;
+	unsigned int i, symindex, exportindex, strindex, setupindex, exindex;
 	long arglen;
 	unsigned long common_length;
 	struct sizes sizes, used;
@@ -816,8 +816,8 @@
 	long err = 0;
 	void *ptr = NULL; /* Stops spurious gcc uninitialized warning */
 
-	DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
-	       umod, len, uargs);
+	DEBUGP("load_module: modname=%p, umod=%p, len=%lu, uargs=%p\n",
+	       modname, umod, len, uargs);
 	if (len < sizeof(*hdr))
 		return ERR_PTR(-ENOEXEC);
 
@@ -849,7 +849,7 @@
 	exportindex = setupindex = 0;
 
 	/* And these should exist, but gcc whinges if we don't init them */
-	symindex = strindex = exindex = modnameindex = 0;
+	symindex = strindex = exindex = 0;
 
 	/* Find where important sections are */
 	for (i = 1; i < hdr->e_shnum; i++) {
@@ -857,11 +857,6 @@
 			/* Internal symbols */
 			DEBUGP("Symbol table in section %u\n", i);
 			symindex = i;
-		} else if (strcmp(secstrings+sechdrs[i].sh_name, ".modulename")
-			   == 0) {
-			/* This module's name */
-			DEBUGP("Module name in section %u\n", i);
-			modnameindex = i;
 		} else if (strcmp(secstrings+sechdrs[i].sh_name, "__ksymtab")
 			   == 0) {
 			/* Exported symbols. */
@@ -895,12 +890,6 @@
 #endif
 	}
 
-	if (!modnameindex) {
-		DEBUGP("Module has no name!\n");
-		err = -ENOEXEC;
-		goto free_hdr;
-	}
-
 	/* Now allocate space for the module proper, and copy name and args. */
 	err = strlen_user(uargs);
 	if (err < 0)
@@ -917,8 +906,9 @@
 		err = -EFAULT;
 		goto free_mod;
 	}
-	strncpy(mod->name, (char *)hdr + sechdrs[modnameindex].sh_offset,
-		sizeof(mod->name)-1);
+	strncpy_from_user(mod->name, modname, sizeof(mod->name)-1);
+	/* strncpy doesn't NUL-terminate when it runs out of space */
+	mod->name[sizeof(mod->name)-1] = 0;
 
 	if (find_module(mod->name)) {
 		err = -EEXIST;
@@ -1058,7 +1048,8 @@
 
 /* This is where the real work happens */
 asmlinkage long
-sys_init_module(void *umod,
+sys_init_module(const char *modname,
+		void *umod,
 		unsigned long len,
 		const char *uargs)
 {
@@ -1074,7 +1065,7 @@
 		return -EINTR;
 
 	/* Do all the hard work */
-	mod = load_module(umod, len, uargs);
+	mod = load_module(modname, umod, len, uargs);
 	if (IS_ERR(mod)) {
 		up(&module_mutex);
 		return PTR_ERR(mod);
===== lib/zlib_deflate/deflate_syms.c 1.2 vs edited =====
--- 1.2/lib/zlib_deflate/deflate_syms.c	Sat Nov  9 04:08:33 2002
+++ edited/lib/zlib_deflate/deflate_syms.c	Wed Nov 20 10:45:43 2002
@@ -19,5 +19,3 @@
 EXPORT_SYMBOL(zlib_deflateCopy);
 EXPORT_SYMBOL(zlib_deflateParams);
 MODULE_LICENSE("GPL");
-
-no_module_init;
===== lib/zlib_inflate/inflate_syms.c 1.3 vs edited =====
--- 1.3/lib/zlib_inflate/inflate_syms.c	Sat Nov  9 04:08:33 2002
+++ edited/lib/zlib_inflate/inflate_syms.c	Wed Nov 20 10:51:40 2002
@@ -20,5 +20,3 @@
 EXPORT_SYMBOL(zlib_inflateSyncPoint);
 EXPORT_SYMBOL(zlib_inflateIncomp); 
 MODULE_LICENSE("GPL");
-
-no_module_init;





^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2002-11-27 23:09 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-11-25 19:16 Patch?: module-init-tools/modprobe.c - use modules.dep Adam J. Richter
2002-11-25 23:34 ` Rusty Russell
  -- strict thread matches above, loose matches on Subject: below --
2002-11-26 19:02 Adam J. Richter
2002-11-27  5:02 ` Rusty Russell
2002-11-27 23:17   ` Keith Owens
     [not found] <200211252254.OAA04288@freya.yggdrasil.com>
2002-11-26  0:45 ` Rusty Russell
2002-11-21 15:39 Adam J. Richter
2002-11-25  5:47 ` Rusty Russell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®