qio: Use an empty string to mark a closed queue
authorBarret Rhoden <brho@cs.berkeley.edu>
Sat, 13 Feb 2016 17:48:14 +0000 (12:48 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sun, 14 Feb 2016 14:03:21 +0000 (09:03 -0500)
Instead of converting ECONNABORTED to a string and then doing a
brain-dead strcmp, we can just use an empty string.  AFAIK, qclose() or
hangups with no message are meant to be normal closes.  Reads will just
return 0 (no data, EOF, etc.), instead of throwing an error.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/ns/qio.c

index 191a420..a277cdb 100644 (file)
@@ -1298,7 +1298,7 @@ static bool qwait(struct queue *q)
                                spin_unlock_irqsave(&q->lock);
                                error(EFAIL, "multiple reads on a closed queue");
                        }
                                spin_unlock_irqsave(&q->lock);
                                error(EFAIL, "multiple reads on a closed queue");
                        }
-                       if (*q->err && strcmp(q->err, errno_to_string(ECONNABORTED)) != 0) {
+                       if (q->err[0]) {
                                spin_unlock_irqsave(&q->lock);
                                error(EFAIL, q->err);
                        }
                                spin_unlock_irqsave(&q->lock);
                                error(EFAIL, q->err);
                        }
@@ -1667,7 +1667,10 @@ long qbwrite(struct queue *q, struct block *b)
        /* give up if the queue is closed */
        if (q->state & Qclosed) {
                spin_unlock_irqsave(&q->lock);
        /* give up if the queue is closed */
        if (q->state & Qclosed) {
                spin_unlock_irqsave(&q->lock);
-               error(EFAIL, q->err);
+               if (q->err[0])
+                       error(EFAIL, q->err);
+               else
+                       error(EFAIL, "connection closed");
        }
 
        /* if nonblocking, don't queue over the limit */
        }
 
        /* if nonblocking, don't queue over the limit */
@@ -1890,7 +1893,7 @@ void qclose(struct queue *q)
        spin_lock_irqsave(&q->lock);
        q->state |= Qclosed;
        q->state &= ~(Qflow | Qstarve | Qdropoverflow | Qnonblock);
        spin_lock_irqsave(&q->lock);
        q->state |= Qclosed;
        q->state &= ~(Qflow | Qstarve | Qdropoverflow | Qnonblock);
-       strlcpy(q->err, errno_to_string(ECONNABORTED), sizeof(q->err));
+       q->err[0] = 0;
        bfirst = q->bfirst;
        q->bfirst = 0;
        q->len = 0;
        bfirst = q->bfirst;
        q->bfirst = 0;
        q->len = 0;
@@ -1906,17 +1909,19 @@ void qclose(struct queue *q)
        qwake_cb(q, FDTAP_FILT_HANGUP);
 }
 
        qwake_cb(q, FDTAP_FILT_HANGUP);
 }
 
-/*
- *  Mark a queue as closed.  Wakeup any readers.  Don't remove queued
- *  blocks.
- */
+/* Mark a queue as closed.  Wakeup any readers.  Don't remove queued blocks.
+ *
+ * msg will be the errstr received by any waiters (qread, qbread, etc).  If
+ * there is no message, which is what also happens during a natural qclose(),
+ * those waiters will simply return 0.  qwriters will always error() on a
+ * closed/hungup queue. */
 void qhangup(struct queue *q, char *msg)
 {
        /* mark it */
        spin_lock_irqsave(&q->lock);
        q->state |= Qclosed;
        if (msg == 0 || *msg == 0)
 void qhangup(struct queue *q, char *msg)
 {
        /* mark it */
        spin_lock_irqsave(&q->lock);
        q->state |= Qclosed;
        if (msg == 0 || *msg == 0)
-               strlcpy(q->err, errno_to_string(ECONNABORTED), sizeof(q->err));
+               q->err[0] = 0;
        else
                strlcpy(q->err, msg, ERRMAX);
        spin_unlock_irqsave(&q->lock);
        else
                strlcpy(q->err, msg, ERRMAX);
        spin_unlock_irqsave(&q->lock);