I don't know how to test this patch, the ack/nack from maintainer is wanted.
flush_scheduled_work() is evil and should be avoided. Change tty_set_ldisc() and release_dev() to use cancel_delayed_work_sync/cancel_work_sync. I am not sure we really need to call do_tty_hangup() when cancel_work_sync() returns true, but this matches the current behaviour. Also, some whitespace fixes. Signed-off-by: Oleg Nesterov <[EMAIL PROTECTED]> --- t/drivers/char/tty_io.c~ 2007-07-01 18:00:10.000000000 +0400 +++ t/drivers/char/tty_io.c 2007-07-01 19:22:25.000000000 +0400 @@ -162,6 +162,8 @@ static void release_tty(struct tty_struc static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); +static void do_tty_hangup(struct work_struct *work); + /** * alloc_tty_struct - allocate a tty object * @@ -1038,12 +1040,10 @@ restart: * we say so later on. */ - work = cancel_delayed_work(&tty->buf.work); - /* - * Wait for ->hangup_work and ->buf.work handlers to terminate - */ - - flush_scheduled_work(); + work = cancel_delayed_work_sync(&tty->buf.work); + if (cancel_work_sync(&tty->hangup_work)) + do_tty_hangup(&tty->hangup_work); + /* Shutdown the current discipline. */ if (tty->ldisc.close) (tty->ldisc.close)(tty); @@ -1074,23 +1074,22 @@ restart: } } /* At this point we hold a reference to the new ldisc and a - a reference to the old ldisc. If we ended up flipping back - to the existing ldisc we have two references to it */ - + * a reference to the old ldisc. If we ended up flipping back + * to the existing ldisc we have two references to it + */ if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc) tty->driver->set_ldisc(tty); - + tty_ldisc_put(o_ldisc.num); - + /* * Allow ldisc referencing to occur as soon as the driver * ldisc callback completes. */ - tty_ldisc_enable(tty); if (o_tty) tty_ldisc_enable(o_tty); - + /* Restart it in case no characters kick it off. Safe if already running */ if (work) @@ -2457,7 +2456,7 @@ static void release_dev(struct file * fi /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) return; - + #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "freeing tty structure..."); #endif @@ -2467,15 +2466,11 @@ static void release_dev(struct file * fi * race with the set_ldisc code path. */ clear_bit(TTY_LDISC, &tty->flags); - cancel_delayed_work(&tty->buf.work); + cancel_delayed_work_sync(&tty->buf.work); + if (cancel_work_sync(&tty->hangup_work)) + do_tty_hangup(&tty->hangup_work); /* - * Wait for ->hangup_work and ->buf.work handlers to terminate - */ - - flush_scheduled_work(); - - /* * Wait for any short term users (we know they are just driver * side waiters as the file is closing so user count on the file * side is zero. @@ -2497,7 +2492,7 @@ static void release_dev(struct file * fi if (tty->ldisc.close) (tty->ldisc.close)(tty); tty_ldisc_put(tty->ldisc.num); - + /* * Switch the line discipline back */ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/