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/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]