lkml.org 
[lkml]   [1998]   [Jan]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectkerneld replacement
Hi,
Here is an experimental patch of mine. It is the start of
a replacement for kerneld. Instead of communicating with a userland
daemon, it execve()s modprobe directly.
It is far from complete. I'm sure there are race conditions
or deadlocks somewhere in there :) I've only tested it on my system.
I'll release much cleaner patches in the future but I thought it would
be fun to see what everyone thinks.
As far as the other features of kerneld, I think they can all
be fixed with changes to modprobe. For example, persistent driver state
can be done by having modprobe save /proc/sys/driver_name to a file when
removing a module and the reverse when loading. Of course, any driver
that wants its state saved would have to export it to /proc/sys/*,
but that is generally a desirable thing :)
Any thoughts? Any reason to keep kerneld? Is it bad to execve()
modprobe from kernel land?

--
Bye,
Kirk Petersen
http://www.muppetlabs.com/~kirk/


--- cut here ---

diff -u --recursive --new-file linux-old/arch/i386/config.in linux/arch/i386/config.in
--- linux-old/arch/i386/config.in Mon Jan 5 22:33:32 1998
+++ linux/arch/i386/config.in Thu Jan 8 18:57:02 1998
@@ -25,6 +25,7 @@
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD
+ bool 'Kernel module loader (very experimental)' CONFIG_KMOD
fi
endmenu

diff -u --recursive --new-file linux-old/include/linux/kerneld.h linux/include/linux/kerneld.h
--- linux-old/include/linux/kerneld.h Mon Jan 5 22:29:44 1998
+++ linux/include/linux/kerneld.h Thu Jan 8 22:50:21 1998
@@ -56,12 +56,16 @@
* Wait for the exit status from insmod/modprobe.
* If it fails, it fails... at least we tried...
*/
+#ifdef CONFIG_KMOD
+extern request_module(const char * name);
+#else
static inline int request_module(const char *name)
{
return kerneld_send(KERNELD_REQUEST_MODULE,
0 | KERNELD_WAIT,
strlen(name), name, NULL);
}
+#endif

/*
* Request the removal of a module, maybe don't wait for it.
diff -u --recursive --new-file linux-old/init/main.c linux/init/main.c
--- linux-old/init/main.c Mon Jan 5 22:33:50 1998
+++ linux/init/main.c Thu Jan 8 19:00:11 1998
@@ -1155,6 +1155,14 @@
}
#endif

+#ifdef CONFIG_KMOD
+ {
+ extern int kmod_init(void *);
+ kernel_thread(kmod_init, NULL, 0);
+ }
+#endif
+
+
setup(1);

if (open("/dev/console", O_RDWR, 0) < 0)
diff -u --recursive --new-file linux-old/kernel/Makefile linux/kernel/Makefile
--- linux-old/kernel/Makefile Mon Jan 5 22:33:50 1998
+++ linux/kernel/Makefile Thu Jan 8 18:58:01 1998
@@ -17,6 +17,10 @@

OX_OBJS += signal.o

+ifeq ($(CONFIG_KMOD),y)
+O_OBJS += kmod.o
+endif
+
ifeq ($(CONFIG_MODULES),y)
OX_OBJS += ksyms.o
endif
diff -u --recursive --new-file linux-old/kernel/kmod.c linux/kernel/kmod.c
--- linux-old/kernel/kmod.c Wed Dec 31 16:00:00 1969
+++ linux/kernel/kmod.c Thu Jan 8 22:53:35 1998
@@ -0,0 +1,99 @@
+/*
+ kmod loading (first cut)
+ kirk petersen
+
+ there are undoubtedly race conditions and/or deadlocks in here
+*/
+
+#define __KERNEL_SYSCALLS__
+
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/unistd.h>
+
+char modprobe_path[64] = "/sbin/modprobe";
+char module_name[64] = "";
+char * argv[] = { "modprobe", "-k", NULL, NULL, };
+char * envp[] = { "HOME=/", "TERM=linux", NULL, };
+
+struct wait_queue * kmod_queue = NULL;
+
+int kmod_init(void * data)
+{
+ int x;
+
+ /*
+ Initialize basic thread information
+ (i'm not sure what this does, entirely)
+ */
+ current->session = 1;
+ current->pgrp = 1;
+ sprintf(current->comm, "kmod");
+ sigfillset(&current->blocked);
+
+ /*
+ For now, this thread waits until someone calls
+ request_module. Then it executes modprobe with the
+ arguments request_module was given.
+ */
+
+ printk ("Starting kmod (kerneld replacement)\n");
+
+ (void)open("/dev/console", O_RDWR, 0);
+ (void)dup(0);
+ (void)dup(0);
+
+ while (1) {
+ /* wait to be signaled by a call to request_module */
+ printk("kmod: sleeping\n");
+ interruptible_sleep_on(&kmod_queue);
+
+ x = fork();
+ if (x) {
+ /* wait for the child to load the module */
+ waitpid(x, NULL, 0);
+
+ /* reset name and wake up the requesting task */
+ module_name[0] = '\0';
+ wake_up(&kmod_queue);
+ } else {
+
+ /* if no module_name, return an error */
+ if (module_name[0] == '\0') {
+ printk("kmod: no module_name given\n");
+ return -1;
+ }
+
+ /* the child execve()s modprobe */
+ argv[2] = module_name;
+ execve(modprobe_path, argv, envp);
+
+ /* only executed if execve() fails */
+ printk("kmod: failed to load module %s\n", module_name);
+ _exit(0);
+ }
+ }
+
+ return 0; /* Never reached. */
+}
+
+int request_module(const char * name)
+{
+ /*
+ first, copy the name of the module into module_name
+ */
+ printk("requesting module: %s\n", name);
+ strcpy(module_name, name);
+
+ /*
+ then wake_up() the kmod daemon
+ */
+ wake_up(&kmod_queue);
+
+ /*
+ wait for the kmod daemon to finish (it will wake us up)
+ */
+ interruptible_sleep_on(&kmod_queue);
+
+ return 0;
+}
diff -u --recursive --new-file linux-old/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-old/kernel/ksyms.c Mon Jan 5 22:33:07 1998
+++ linux/kernel/ksyms.c Thu Jan 8 22:52:10 1998
@@ -90,6 +90,10 @@
#endif


+#ifdef CONFIG_KMOD
+EXPORT_SYMBOL(request_module);
+#endif
+
#ifdef CONFIG_MODULES
EXPORT_SYMBOL(get_module_symbol);
#endif
\
 
 \ /
  Last update: 2005-03-22 13:41    [W:0.018 / U:0.976 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site