Proposed patch: fix Oops in wakeup_bdflush

From: Russell King (rmk@arm.linux.org.uk)
Date: Fri Jun 02 2000 - 15:42:04 EST


Hi,

It is possible with certain configurations (without any block device
drivers other than a ramdisk) to have any late 2.3 and 2.4 kernel to
fail during boot when wakeup_bdflush is called.

The problem is due to the behaviour of kernel_thread(). It doesn't
wait for the child task to initialise. Although the ability to wait
for a child to initialise is not always wanted, in the case of
bdflush it must happen, or else we run the risk of getting a
non-existant task woken and the associated NULL pointer dereference.

The exact situation is where the initcalls() are made, and there are
no reschedule calls until after we start executing the user-mode
init daemon. (Think about the diskless nfsless initrd-only situation -
there are no calls to schedule until we hit userspace and do the first
user context switch).

The following patch attempts to correct the bdflush problem in a clean
way - we use a semaphore to make the parent sleep until the important
initialisation code has been executed for the child.

I've also applied the same fix to kupdate - I don't think that there
is a problem there, but it seemed to be good to ensure that this is
also started up cleanly. If someone (Al Viro) decides this is not
needed, its relatively trivial to drop it out of this patch.

--- orig/fs/buffer.c Wed May 31 13:12:38 2000
+++ linux/fs/buffer.c Fri Jun 2 20:31:43 2000
@@ -2568,7 +2568,7 @@
  * the syscall above, but now we launch it ourselves internally with
  * kernel_thread(...) directly after the first thread in init/main.c
  */
-int bdflush(void * unused)
+int bdflush(void *sem)
 {
         struct task_struct *tsk = current;
         int flushed;
@@ -2590,6 +2590,8 @@
         recalc_sigpending(tsk);
         spin_unlock_irq(&tsk->sigmask_lock);
 
+ up((struct semaphore *)sem);
+
         for (;;) {
                 CHECK_EMERGENCY_SYNC
 
@@ -2624,7 +2626,7 @@
  * You don't need to change your userspace configuration since
  * the userspace `update` will do_exit(0) at the first sys_bdflush().
  */
-int kupdate(void * unused)
+int kupdate(void *sem)
 {
         struct task_struct * tsk = current;
         int interval;
@@ -2640,6 +2642,8 @@
         recalc_sigpending(tsk);
         spin_unlock_irq(&tsk->sigmask_lock);
 
+ up((struct semaphore *)sem);
+
         for (;;) {
                 /* update interval */
                 interval = bdf_prm.b_un.interval;
@@ -2673,8 +2677,11 @@
 
 static int __init bdflush_init(void)
 {
- kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- kernel_thread(kupdate, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ DECLARE_MUTEX_LOCKED(sem);
+ kernel_thread(bdflush, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ down(&sem);
+ kernel_thread(kupdate, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ down(&sem);
         return 0;
 }
 

   _____
  |_____| ------------------------------------------------- ---+---+-
  | | Russell King rmk@arm.linux.org.uk --- ---
  | | | | http://www.arm.linux.org.uk/~rmk/aboutme.html / / |
  | +-+-+ --- -+-
  / | THE developer of ARM Linux |+| /|\
 / | | | --- |
    +-+-+ ------------------------------------------------- /\\\ |

-
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.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Jun 07 2000 - 21:00:16 EST