Report readablity/writablility via 9p stat
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 3 May 2016 19:46:51 +0000 (15:46 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 3 May 2016 19:46:51 +0000 (15:46 -0400)
This extends 9p to have bits for readable and writable, in the O_NONBLOCK
sense.  This is required for select().

Pipes and #ip use qio helpers to set the bit.  Other devices will need to
do something similar, if they use queues.  If not, they'll have to do
something else.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/pipe.c
kern/include/ns.h
kern/src/net/devip.c
kern/src/ns/qio.c

index fad7b22..3707768 100644 (file)
@@ -219,6 +219,7 @@ static int pipestat(struct chan *c, uint8_t * db, int n)
        Pipe *p;
        struct dir dir;
        struct dirtab *tab;
+       int perm;
 
        p = c->aux;
        tab = p->pipedir;
@@ -228,12 +229,16 @@ static int pipestat(struct chan *c, uint8_t * db, int n)
                        devdir(c, c->qid, ".", 0, eve, DMDIR | 0555, &dir);
                        break;
                case Qdata0:
-                       devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, tab[1].perm,
-                                  &dir);
+                       perm = tab[1].perm;
+                       perm |= qreadable(p->q[0]) ? DMREADABLE : 0;
+                       perm |= qwritable(p->q[0]) ? DMWRITABLE : 0;
+                       devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, perm, &dir);
                        break;
                case Qdata1:
-                       devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, tab[2].perm,
-                                  &dir);
+                       perm = tab[2].perm;
+                       perm |= qreadable(p->q[1]) ? DMREADABLE : 0;
+                       perm |= qwritable(p->q[1]) ? DMWRITABLE : 0;
+                       devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, perm, &dir);
                        break;
                default:
                        panic("pipestat");
index 4f072a5..126f335 100644 (file)
@@ -120,6 +120,8 @@ extern int parseether(uint8_t * unused_uint8_p_t, char *unused_char_p_t);
 #define DMAPPEND       0x40000000      /* mode bit for append only files */
 #define DMEXCL         0x20000000      /* mode bit for exclusive use files */
 #define DMMOUNT                0x10000000      /* mode bit for mounted channel */
+#define DMWRITABLE     0x08000000      /* non-standard, for select() */
+#define DMREADABLE     0x04000000      /* non-standard, for select() */
 #define DMSYMLINK      0x02000000      /* symlink -- from 9p2000.u */
 #define DMREAD         0x4     /* mode bit for read permission */
 #define DMWRITE                0x2     /* mode bit for write permission */
@@ -844,6 +846,8 @@ ssize_t qwrite(struct queue *, void *, int);
 ssize_t qwrite_nonblock(struct queue *, void *, int);
 typedef void (*qio_wake_cb_t)(struct queue *q, void *data, int filter);
 void qio_set_wake_cb(struct queue *q, qio_wake_cb_t func, void *data);
+bool qreadable(struct queue *q);
+bool qwritable(struct queue *q);
 
 void *realloc(void *, uint32_t);
 int readmem(unsigned long offset, char *buf, unsigned long n,
index 39430a3..2bc6160 100644 (file)
@@ -128,6 +128,7 @@ static int ip3gen(struct chan *c, int i, struct dir *dp)
        struct qid q;
        struct conv *cv;
        char *p;
+       int perm;
 
        cv = chan2conv(c);
        if (cv->owner == NULL)
@@ -141,11 +142,16 @@ static int ip3gen(struct chan *c, int i, struct dir *dp)
                        return founddevdir(c, q, "ctl", 0,
                                                   cv->owner, cv->perm, dp);
                case Qdata:
+                       perm = cv->perm;
+                       perm |= qreadable(cv->rq) ? DMREADABLE : 0;
+                       perm |= qwritable(cv->wq) ? DMWRITABLE : 0;
                        return founddevdir(c, q, "data", qlen(cv->rq),
-                                                          cv->owner, cv->perm, dp);
+                                                          cv->owner, perm, dp);
                case Qerr:
+                       perm = cv->perm;
+                       perm |= qreadable(cv->eq) ? DMREADABLE : 0;
                        return founddevdir(c, q, "err", qlen(cv->eq),
-                                                          cv->owner, cv->perm, dp);
+                                                          cv->owner, perm, dp);
                case Qlisten:
                        return founddevdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
                case Qlocal:
@@ -157,8 +163,10 @@ static int ip3gen(struct chan *c, int i, struct dir *dp)
                case Qsnoop:
                        if (strcmp(cv->p->name, "ipifc") != 0)
                                return -1;
+                       perm = 0400;
+                       perm |= qreadable(cv->sq) ? DMREADABLE : 0;
                        return founddevdir(c, q, "snoop", qlen(cv->sq),
-                                                          cv->owner, 0400, dp);
+                                                          cv->owner, perm, dp);
                case Qstatus:
                        p = "status";
                        break;
index dcfd935..69f4f5e 100644 (file)
@@ -1859,3 +1859,15 @@ void qio_set_wake_cb(struct queue *q, qio_wake_cb_t func, void *data)
        wmb();  /* if we see func, we'll also see the data for it */
        q->wake_cb = func;
 }
+
+/* Helper for detecting whether we'll block on a read at this instant. */
+bool qreadable(struct queue *q)
+{
+       return qlen(q) > 0;
+}
+
+/* Helper for detecting whether we'll block on a write at this instant. */
+bool qwritable(struct queue *q)
+{
+       return qwindow(q) > 0;
+}