Author: pho
Date: Mon Jun 18 07:34:38 2012
New Revision: 237219
URL: http://svn.freebsd.org/changeset/base/237219

Log:
  In tty_makedev() the following construction:
  
  dev = make_dev_cred();
  dev->si_drv1 = tp;
  
  leaves a small window where the newly created device may be opened
  and si_drv1 is NULL.
  
  As this is a vary rare situation, using a lock to close the window
  seems overkill. Instead just wait for the assignment of si_drv1.
  
  Suggested by: kib
  MFC after:    1 week

Modified:
  head/sys/kern/tty.c

Modified: head/sys/kern/tty.c
==============================================================================
--- head/sys/kern/tty.c Mon Jun 18 05:02:21 2012        (r237218)
+++ head/sys/kern/tty.c Mon Jun 18 07:34:38 2012        (r237219)
@@ -219,9 +219,15 @@ ttydev_leave(struct tty *tp)
 static int
 ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
 {
-       struct tty *tp = dev->si_drv1;
+       struct tty *tp;
        int error = 0;
 
+       while ((tp = dev->si_drv1) == NULL) {
+               error = tsleep(&dev->si_drv1, PCATCH, "ttdrv1", 1);
+               if (error != EWOULDBLOCK)
+                       return (error);
+       }
+
        tty_lock(tp);
        if (tty_gone(tp)) {
                /* Device is already gone. */
@@ -738,9 +744,14 @@ static struct cdevsw ttydev_cdevsw = {
 static int
 ttyil_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
 {
-       struct tty *tp = dev->si_drv1;
+       struct tty *tp;
        int error = 0;
 
+       while ((tp = dev->si_drv1) == NULL) {
+               error = tsleep(&dev->si_drv1, PCATCH, "ttdrv1", 1);
+               if (error != EWOULDBLOCK)
+                       return (error);
+       }
        tty_lock(tp);
        if (tty_gone(tp))
                error = ENODEV;
@@ -1203,6 +1214,7 @@ tty_makedev(struct tty *tp, struct ucred
        dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
            uid, gid, mode, "%s%s", prefix, name);
        dev->si_drv1 = tp;
+       wakeup(&dev->si_drv1);
        tp->t_dev = dev;
 
        /* Slave call-in devices. */
@@ -1211,12 +1223,14 @@ tty_makedev(struct tty *tp, struct ucred
                    uid, gid, mode, "%s%s.init", prefix, name);
                dev_depends(tp->t_dev, dev);
                dev->si_drv1 = tp;
+               wakeup(&dev->si_drv1);
                dev->si_drv2 = &tp->t_termios_init_in;
 
                dev = make_dev_cred(&ttyil_cdevsw, TTYUNIT_LOCK, cred,
                    uid, gid, mode, "%s%s.lock", prefix, name);
                dev_depends(tp->t_dev, dev);
                dev->si_drv1 = tp;
+               wakeup(&dev->si_drv1);
                dev->si_drv2 = &tp->t_termios_lock_in;
        }
 
@@ -1226,6 +1240,7 @@ tty_makedev(struct tty *tp, struct ucred
                    UID_UUCP, GID_DIALER, 0660, "cua%s", name);
                dev_depends(tp->t_dev, dev);
                dev->si_drv1 = tp;
+               wakeup(&dev->si_drv1);
 
                /* Slave call-out devices. */
                if (tp->t_flags & TF_INITLOCK) {
@@ -1234,6 +1249,7 @@ tty_makedev(struct tty *tp, struct ucred
                            UID_UUCP, GID_DIALER, 0660, "cua%s.init", name);
                        dev_depends(tp->t_dev, dev);
                        dev->si_drv1 = tp;
+                       wakeup(&dev->si_drv1);
                        dev->si_drv2 = &tp->t_termios_init_out;
 
                        dev = make_dev_cred(&ttyil_cdevsw,
@@ -1241,6 +1257,7 @@ tty_makedev(struct tty *tp, struct ucred
                            UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name);
                        dev_depends(tp->t_dev, dev);
                        dev->si_drv1 = tp;
+                       wakeup(&dev->si_drv1);
                        dev->si_drv2 = &tp->t_termios_lock_out;
                }
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to