]> git.hungrycats.org Git - linux/commitdiff
[PATCH] hvc_console fix to prevent oops and late hangup and write operations
authorRyan S. Arnold <rsa@us.ibm.com>
Wed, 20 Oct 2004 01:36:07 +0000 (18:36 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 20 Oct 2004 01:36:07 +0000 (18:36 -0700)
This patch prevents execution of hvc_write() and hvc_hangup() after the tty
layer has executed a final hvc_close() against a device.  This patch
provides a better method than was previously used.  tty->driver_data is no
longer invalidated so we'll no longer get oopses when the tty layer allows
late hangup() and write() operations.

- Removed silly tty->driver_data = NULL; from hvc_close which prevents
  possible oops in hvc_write() and hvc_hangup() due to improperly acting
  ldisc close ordering.

- Added hp->count <= 0 check to hvc_write() and hvc_hangup() to prevent
  execution of these function after hvc_close() has been invoked by the tty
  layer.  Same tty ldisc issues as above are the reason.

- Added some comments to clarify the situation.

- Awaiting a forth coming patch from Alan Cox which should clean up the
  close ordering and prevent the late hangup and write ops from happening.

Signed-off-by: Ryan S. Arnold <rsa@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/char/hvc_console.c

index 8d569ed74bc8002dfaf6e4f9a66fb8d4145049d4..44dbc3d80e06c950259dac22fc5c2740712344e6 100644 (file)
@@ -221,6 +221,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
                spin_unlock_irqrestore(&hp->lock, flags);
                tty->driver_data = NULL;
                kobject_put(kobjp);
+               printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
        }
        /* Force wakeup of the polling thread */
        hvc_kick();
@@ -240,7 +241,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
 
        /*
         * No driver_data means that this close was issued after a failed
-        * hvcs_open by the tty layer's release_dev() function and we can just
+        * hvc_open by the tty layer's release_dev() function and we can just
         * exit cleanly because the kobject reference wasn't made.
         */
        if (!tty->driver_data)
@@ -266,13 +267,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
                 */
                tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
 
-               /*
-                * Since the line disc doesn't block writes during tty close
-                * operations we'll set driver_data to NULL and then make sure
-                * to check tty->driver_data for NULL in hvc_write().
-                */
-               tty->driver_data = NULL;
-
                if (irq != NO_IRQ)
                        free_irq(irq, hp);
 
@@ -294,7 +288,21 @@ static void hvc_hangup(struct tty_struct *tty)
        int temp_open_count;
        struct kobject *kobjp;
 
+       if (!hp)
+               return;
+
        spin_lock_irqsave(&hp->lock, flags);
+
+       /*
+        * The N_TTY line discipline has problems such that in a close vs
+        * open->hangup case this can be called after the final close so prevent
+        * that from happening for now.
+        */
+       if (hp->count <= 0) {
+               spin_unlock_irqrestore(&hp->lock, flags);
+               return;
+       }
+
        kobjp = &hp->kobj;
        temp_open_count = hp->count;
        hp->count = 0;
@@ -428,6 +436,9 @@ static int hvc_write(struct tty_struct *tty, int from_user,
        if (!hp)
                return -EPIPE;
 
+       if (hp->count <= 0)
+               return -EIO;
+
        if (from_user)
                written = __hvc_write_user(hp, buf, count);
        else