tty: fix O_NDELAY proposal
authorAlan Cox <alan@linux.intel.com>
Thu, 1 Oct 2015 21:19:29 +0000 (22:19 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 1 Oct 2015 21:19:29 +0000 (22:19 +0100)
Bug as noticed by Brett M Gordon

Try a different fix giving us a call that will generalize for other users
of psleep_flags who will need this eventually.

Kernel/devio.c
Kernel/include/kernel.h
Kernel/tty.c

index 5f7f792..608b1e6 100644 (file)
@@ -442,20 +442,32 @@ bool uninsq(struct s_queue *q, unsigned char *cp)
              Miscellaneous helpers
 **********************************************************************/
 
-int psleep_flags(void *p, unsigned char flags)
+int psleep_flags_io(void *p, unsigned char flags, usize_t *n)
 {
        if (flags & O_NDELAY) {
-               udata.u_error = EAGAIN;
-               return (-1);
+               if (*n) {
+                       *n = (usize_t)-1;
+                       udata.u_error = EAGAIN;
+                }
+               return -1;
        }
        psleep(p);
        if (udata.u_cursig || udata.u_ptab->p_pending) {        /* messy */
-               udata.u_error = EINTR;
-               return (-1);
+               if (*n) {
+                       *n = (usize_t)-1;
+                        udata.u_error = EINTR;
+                }
+               return -1;
        }
        return 0;
 }
 
+int psleep_flags(void *p, unsigned char flags)
+{
+        usize_t dummy = 0;
+        return psleep_flags_io(p, flags, &dummy);
+}
+
 void kputs(const char *p)
 {
        while (*p)
index 6f4180e..7fda5d0 100644 (file)
@@ -654,6 +654,7 @@ extern bool insq(struct s_queue *q, unsigned char c);
 extern bool remq(struct s_queue *q, unsigned char *cp);
 extern void clrq(struct s_queue *q);
 extern bool uninsq(struct s_queue *q, unsigned char *cp);
+extern int psleep_flags_io(void *event, unsigned char flags, usize_t *n);
 extern int psleep_flags(void *event, unsigned char flags);
 extern int nxio_open(uint8_t minor, uint16_t flag);
 extern int no_open(uint8_t minor, uint16_t flag);
index f5731af..40e298a 100644 (file)
@@ -27,7 +27,7 @@ struct tty ttydata[NUM_DEV_TTY + 1];  /* ttydata[0] is not used */
 
 int tty_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
 {
-       uint16_t nread;
+       usize_t nread;
        unsigned char c;
        struct s_queue *q;
        struct tty *t;
@@ -56,8 +56,8 @@ int tty_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
                                if (n)
                                        udata.u_ptab->p_timeout = n + 1;
                         }
-                       if (psleep_flags(q, flag))
-                               return -1;
+                       if (psleep_flags_io(q, flag, &nread))
+                               return nread;
                         /* timer expired */
                         if (udata.u_ptab->p_timeout == 1)
                                 goto out;
@@ -90,7 +90,7 @@ out:
 int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
 {
        struct tty *t;
-       int towrite;
+       usize_t written = 0;
        uint8_t c;
 
        used(rawflag);
@@ -98,8 +98,6 @@ int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
 
        t = &ttydata[minor];
 
-       towrite = udata.u_count;
-
        while (udata.u_count-- != 0) {
                for (;;) {      /* Wait on the ^S/^Q flag */
                        if (t->flag & TTYF_DEAD) {
@@ -108,8 +106,8 @@ int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
                         }
                        if (!(t->flag & TTYF_STOP))
                                break;
-                       if (psleep_flags(&t->flag, flag))
-                               return -1;
+                       if (psleep_flags_io(&t->flag, flag, &written))
+                               return written;
                }
 
                if (!(t->flag & TTYF_DISCARD)) {
@@ -127,8 +125,9 @@ int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
                        tty_putc_wait(minor, c);
                }
                ++udata.u_base;
+               ++written;
        }
-       return towrite;
+       return written;
 }
 
 int tty_open(uint8_t minor, uint16_t flag)