Following, is my most recent patch against 2.1.115 with the
not-yet-integrated kmod fixes. The first fix is mine; it blocks the
process calling request_module from being signalled, to prevent waitpid
errors -512 (ERESTARTSYS). I've modified it so that it will not block
SIGKILL or SIGSTOP, so as not to conflict with standards (you really
shouldn't have reason to send SIGSTOP or SIGKILL to the process in this
state, though. If you have to, then something has gone horribly wrong).
I've also included a few minor code cleanups (moving a envp into being a
local variable, since there is no reason for it to be global), and some
printk updates to provide more consistent and useful information.
The second fix is by Richard Hirst, that appears to be necessary for 680x0
machines (though it may be necessary for other platforms). It appears
that the MMU ATC entries must be flushed in the kernel thread.
Admittedly, this is a band-aid, but until someone can find the "proper"
fix (probably somewhere in the MM or kernel_thread() code), it makes kmod
much more stable on some machines.
Alan, I sent this to you, as this contains some updates from the version
of this patch in your 2.1 tree. If you'd like, I can make a diff against
your tree.
Richard Henderson, I sent this to you, as you diagnosed the signal
problems before with the Alpha. I'd like to make sure that these changes
are multi-platform safe. I seem to remember older kmod code blocking
signals in the spawned kernel_thread causing the problems that you
described. Here I'm blocking signals in the request_module, which doesn't
affect the kernel_thread, but the user process that required the module.
Could you test this change on an Alpha?
Richard Gooch, I figured you would want a copy of the most recent kmod
fix, as devfs seems to very consistently cause the kmod bug.
Linus, pending confirmation from Richard as to this working on the Alpha,
can you apply this to the main kernel, or tell me if you have a
conceptual problem with the code? I consider it a rather important
bug-fix for kmod.
Linux-kernel, if there are any ALpha users with a working 2.1.115, I'd
love to hear reports of how this patch works.
Patch included after my sig.
Thank you all for your time,
Greg Zornetzer - gaz+@andrew.cmu.edu
"Light shines brightest in the darkest night"
http://www.contrib.andrew.cmu.edu/~gaz
--- linux/kernel/kmod.c.back Thu Aug 13 12:27:58 1998
+++ linux/kernel/kmod.c Thu Aug 13 12:29:51 1998
@@ -7,6 +7,14 @@
Modified to avoid chroot and file sharing problems.
Mikael Pettersson
+
+ Blocked all signals during waitpid in request_module, to prevent
+ abnormal termination of waitpid, minor fixups - Greg Zornetzer
+
+ Flush the MMU ATC entries in exec_modprobe - this clears up
+ random kmod crashes, especially on m68k - Richard Hirst
+
+
*/
#define __KERNEL_SYSCALLS__
@@ -15,14 +23,15 @@
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/smp_lock.h>
-
+#include <linux/signal.h>
+#include <linux/mm.h>
#include <asm/uaccess.h>
+#include <asm/pgtable.h>
/*
modprobe_path is set via /proc/sys.
*/
char modprobe_path[256] = "/sbin/modprobe";
-static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
/*
exec_modprobe is spawned from a kernel-mode user process,
@@ -50,6 +59,15 @@
{
char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL};
int i;
+ char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+ /* The MMU ATC entries need flushing somewhere round here. This
+ thread was created with CLONE_VM, so there was no cause to
+ flush it there. exec_mmap() called as a result of the following
+ execve() finds current->mm->count=2, so that doesn't flush the MMU
+ either. */
+
+ flush_tlb_mm(current->mm);
+
use_init_file_context();
@@ -97,6 +115,7 @@
{
int pid;
int waitpid_result;
+ sigset_t tempsig;
/* Don't allow request_module() before the root fs is mounted! */
if ( ! current->fs->root ) {
@@ -107,13 +126,31 @@
pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS);
if (pid < 0) {
- printk(KERN_ERR "kmod: fork failed, errno %d\n", -pid);
+ printk(KERN_ERR "request_module[%s]: thread failed, errno %d\n", module_name, -pid);
return pid;
}
+
+ /* Save the current sigmask, then block everything, except
+ SIGSTOP & SIGKILL */
+ spin_lock_irq(¤t->sigmask_lock);
+ memcpy(&tempsig, ¤t->blocked, sizeof(sigset_t));
+ sigfillset(¤t->blocked);
+ sigdelset(¤t->blocked, SIGSTOP);
+ sigdelset(¤t->blocked, SIGKILL);
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
waitpid_result = waitpid(pid, NULL, __WCLONE);
+
+ /* Replace the pristine sigmask */
+ spin_lock_irq(¤t->sigmask_lock);
+ memcpy(¤t->blocked, &tempsig, sizeof(sigset_t));
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
if (waitpid_result != pid) {
- printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n",
- pid, waitpid_result);
+ printk (KERN_ERR "request_module[%s]: waitpid of proc. %d failed, returning %d.\n",
+ module_name, pid, waitpid_result);
}
return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html