Proposed patch: fix Oops in wakeup_bdflush

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

  • Next message: Hans Reiser: "ReiserFS 3.6.8 is released"

    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 : Fri Jun 02 2000 - 18:29:07 EDT