Added explicit errno reporting from error() API.
[akaros.git] / kern / drivers / dev / pipe.c
index 46eaea4..495a614 100644 (file)
 #include <smp.h>
 #include <ip.h>
 
 #include <smp.h>
 #include <ip.h>
 
-typedef struct Pipe    Pipe;
-struct Pipe
+struct dev pipedevtab;
+
+static char *devname(void)
 {
 {
+       return pipedevtab.name;
+}
+
+typedef struct Pipe Pipe;
+struct Pipe {
        qlock_t qlock;
        qlock_t qlock;
-       Pipe*   next;
-       struct kref     ref;
-       uint32_t        path;
-       struct queue*   q[2];
-       int     qref[2];
-       struct dirtab   *pipedir;
-       char*   user;
+       Pipe *next;
+       struct kref ref;
+       uint32_t path;
+       struct queue *q[2];
+       int qref[2];
+       struct dirtab *pipedir;
+       char *user;
 };
 
 };
 
-static struct
-{
+static struct {
        spinlock_t lock;
        spinlock_t lock;
-       uint32_t        path;
-       int     pipeqsize;      
+       uint32_t path;
+       int pipeqsize;
 } pipealloc;
 
 } pipealloc;
 
-enum
-{
+enum {
        Qdir,
        Qdata0,
        Qdata1,
 };
 
        Qdir,
        Qdata0,
        Qdata1,
 };
 
-static 
-struct dirtab pipedir[] =
-{
-       {".",           {Qdir,0,QTDIR}, 0,              DMDIR|0500},
-       {"data",                {Qdata0},       0,                      0660},
-       {"data1",       {Qdata1},       0,                      0660},
+static
+struct dirtab pipedir[] = {
+       {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0500},
+       {"data", {Qdata0}, 0, 0660},
+       {"data1", {Qdata1}, 0, 0660},
 };
 
 };
 
-static void
-freepipe(Pipe *p)
+static void freepipe(Pipe * p)
 {
 {
-       if(p != NULL){
+       if (p != NULL) {
                kfree(p->user);
                kfree(p->q[0]);
                kfree(p->q[1]);
                kfree(p->user);
                kfree(p->q[0]);
                kfree(p->q[1]);
@@ -63,55 +65,52 @@ freepipe(Pipe *p)
 static void pipe_release(struct kref *kref)
 {
        Pipe *pipe = container_of(kref, Pipe, ref);
 static void pipe_release(struct kref *kref)
 {
        Pipe *pipe = container_of(kref, Pipe, ref);
-       qunlock(&pipe->qlock);
        freepipe(pipe);
 }
 
        freepipe(pipe);
 }
 
-static void
-pipeinit(void)
+static void pipeinit(void)
 {
 {
-       pipealloc.pipeqsize = 32*1024;
+       pipealloc.pipeqsize = 32 * 1024;
 }
 
 /*
  *  create a pipe, no streams are created until an open
  */
 }
 
 /*
  *  create a pipe, no streams are created until an open
  */
-static struct chan*
-pipeattach(char *spec)
+static struct chan *pipeattach(char *spec)
 {
        ERRSTACK(2);
        Pipe *p;
        struct chan *c;
 
 {
        ERRSTACK(2);
        Pipe *p;
        struct chan *c;
 
-       c = devattach('|', spec);
+       c = devattach(devname(), spec);
        p = kzmalloc(sizeof(Pipe), 0);
        p = kzmalloc(sizeof(Pipe), 0);
-       if(p == 0)
-               error(Enomem);
-       if(waserror()){
+       if (p == 0)
+               error(ENOMEM, NULL);
+       if (waserror()) {
                freepipe(p);
                nexterror();
        }
        p->pipedir = kzmalloc(sizeof(pipedir), 0);
        if (p->pipedir == 0)
                freepipe(p);
                nexterror();
        }
        p->pipedir = kzmalloc(sizeof(pipedir), 0);
        if (p->pipedir == 0)
-               error(Enomem);
+               error(ENOMEM, NULL);
        memmove(p->pipedir, pipedir, sizeof(pipedir));
        kstrdup(&p->user, current->user);
        kref_init(&p->ref, pipe_release, 1);
        qlock_init(&p->qlock);
 
        memmove(p->pipedir, pipedir, sizeof(pipedir));
        kstrdup(&p->user, current->user);
        kref_init(&p->ref, pipe_release, 1);
        qlock_init(&p->qlock);
 
-       p->q[0] = qopen(pipealloc.pipeqsize, 0, 0, 0);
-       if(p->q[0] == 0)
-               error(Enomem);
-       p->q[1] = qopen(pipealloc.pipeqsize, 0, 0, 0);
-       if(p->q[1] == 0)
-               error(Enomem);
+       p->q[0] = qopen(pipealloc.pipeqsize, Qcoalesce, 0, 0);
+       if (p->q[0] == 0)
+               error(ENOMEM, NULL);
+       p->q[1] = qopen(pipealloc.pipeqsize, Qcoalesce, 0, 0);
+       if (p->q[1] == 0)
+               error(ENOMEM, NULL);
        poperror();
 
        spin_lock(&(&pipealloc)->lock);
        p->path = ++pipealloc.path;
        spin_unlock(&(&pipealloc)->lock);
 
        poperror();
 
        spin_lock(&(&pipealloc)->lock);
        p->path = ++pipealloc.path;
        spin_unlock(&(&pipealloc)->lock);
 
-       c->qid.path = NETQID(2*p->path, Qdir);
+       c->qid.path = NETQID(2 * p->path, Qdir);
        c->qid.vers = 0;
        c->qid.type = QTDIR;
        c->aux = p;
        c->qid.vers = 0;
        c->qid.type = QTDIR;
        c->aux = p;
@@ -121,32 +120,31 @@ pipeattach(char *spec)
 
 static int
 pipegen(struct chan *c, char *unused,
 
 static int
 pipegen(struct chan *c, char *unused,
-       struct dirtab *tab, int ntab, int i,
-       struct dir *dp)
+               struct dirtab *tab, int ntab, int i, struct dir *dp)
 {
        int id, len;
        struct qid qid;
        Pipe *p;
 
 {
        int id, len;
        struct qid qid;
        Pipe *p;
 
-       if(i == DEVDOTDOT){
-               devdir(c, c->qid, "#|", 0, eve, 0555, dp);
+       if (i == DEVDOTDOT) {
+               devdir(c, c->qid, devname(), 0, eve, 0555, dp);
                return 1;
        }
        i++;    /* skip . */
                return 1;
        }
        i++;    /* skip . */
-       if(tab==0 || i>=ntab)
+       if (tab == 0 || i >= ntab)
                return -1;
        tab += i;
        p = c->aux;
                return -1;
        tab += i;
        p = c->aux;
-       switch(NETTYPE(tab->qid.path)){
-       case Qdata0:
-               len = qlen(p->q[0]);
-               break;
-       case Qdata1:
-               len = qlen(p->q[1]);
-               break;
-       default:
-               len = tab->length;
-               break;
+       switch (NETTYPE(tab->qid.path)) {
+               case Qdata0:
+                       len = qlen(p->q[0]);
+                       break;
+               case Qdata1:
+                       len = qlen(p->q[1]);
+                       break;
+               default:
+                       len = tab->length;
+                       break;
        }
        id = NETID(c->qid.path);
        qid.path = NETQID(id, tab->qid.path);
        }
        id = NETID(c->qid.path);
        qid.path = NETQID(id, tab->qid.path);
@@ -156,26 +154,25 @@ pipegen(struct chan *c, char *unused,
        return 1;
 }
 
        return 1;
 }
 
-
-static struct walkqid*
-pipewalk(struct chan *c, struct chan *nc, char **name, int nname)
+static struct walkqid *pipewalk(struct chan *c, struct chan *nc, char **name,
+                                                               int nname)
 {
        struct walkqid *wq;
        Pipe *p;
 
        p = c->aux;
        wq = devwalk(c, nc, name, nname, p->pipedir, ARRAY_SIZE(pipedir), pipegen);
 {
        struct walkqid *wq;
        Pipe *p;
 
        p = c->aux;
        wq = devwalk(c, nc, name, nname, p->pipedir, ARRAY_SIZE(pipedir), pipegen);
-       if(wq != NULL && wq->clone != NULL && wq->clone != c){
+       if (wq != NULL && wq->clone != NULL && wq->clone != c) {
                qlock(&p->qlock);
                kref_get(&p->ref, 1);
                qlock(&p->qlock);
                kref_get(&p->ref, 1);
-               if(c->flag & COPEN){
-                       switch(NETTYPE(c->qid.path)){
-                       case Qdata0:
-                               p->qref[0]++;
-                               break;
-                       case Qdata1:
-                               p->qref[1]++;
-                               break;
+               if (c->flag & COPEN) {
+                       switch (NETTYPE(c->qid.path)) {
+                               case Qdata0:
+                                       p->qref[0]++;
+                                       break;
+                               case Qdata1:
+                                       p->qref[1]++;
+                                       break;
                        }
                }
                qunlock(&p->qlock);
                        }
                }
                qunlock(&p->qlock);
@@ -183,8 +180,7 @@ pipewalk(struct chan *c, struct chan *nc, char **name, int nname)
        return wq;
 }
 
        return wq;
 }
 
-static int
-pipestat(struct chan *c, uint8_t *db, int n)
+static int pipestat(struct chan *c, uint8_t * db, int n)
 {
        Pipe *p;
        struct dir dir;
 {
        Pipe *p;
        struct dir dir;
@@ -193,37 +189,38 @@ pipestat(struct chan *c, uint8_t *db, int n)
        p = c->aux;
        tab = p->pipedir;
 
        p = c->aux;
        tab = p->pipedir;
 
-       switch(NETTYPE(c->qid.path)){
-       case Qdir:
-               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);
-               break;
-       case Qdata1:
-               devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, tab[2].perm, &dir);
-               break;
-       default:
-               panic("pipestat");
+       switch (NETTYPE(c->qid.path)) {
+               case Qdir:
+                       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);
+                       break;
+               case Qdata1:
+                       devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, tab[2].perm,
+                                  &dir);
+                       break;
+               default:
+                       panic("pipestat");
        }
        n = convD2M(&dir, db, n);
        }
        n = convD2M(&dir, db, n);
-       if(n < BIT16SZ)
-               error(Eshortstat);
+       if (n < BIT16SZ)
+               error(ENODATA, NULL);
        return n;
 }
 
 /*
  *  if the stream doesn't exist, create it
  */
        return n;
 }
 
 /*
  *  if the stream doesn't exist, create it
  */
-static struct chan*
-pipeopen(struct chan *c, int omode)
+static struct chan *pipeopen(struct chan *c, int omode)
 {
        ERRSTACK(2);
        Pipe *p;
 
 {
        ERRSTACK(2);
        Pipe *p;
 
-       if(c->qid.type & QTDIR){
-               if (!IS_RDONLY(omode))
-                       error("Can only open directories OREAD, mode is %o oct", omode);
+       if (c->qid.type & QTDIR) {
+               if (omode & O_WRITE)
+                       error(EFAIL, "Can only open directories O_READ, mode is %o oct", omode);
                c->mode = openmode(omode);
                c->flag |= COPEN;
                c->offset = 0;
                c->mode = openmode(omode);
                c->flag |= COPEN;
                c->offset = 0;
@@ -234,19 +231,19 @@ pipeopen(struct chan *c, int omode)
 
        p = c->aux;
        qlock(&p->qlock);
 
        p = c->aux;
        qlock(&p->qlock);
-       if(waserror()){
+       if (waserror()) {
                qunlock(&p->qlock);
                nexterror();
        }
                qunlock(&p->qlock);
                nexterror();
        }
-       switch(NETTYPE(c->qid.path)){
-       case Qdata0:
-               devpermcheck(p->user, p->pipedir[1].perm, omode);
-               p->qref[0]++;
-               break;
-       case Qdata1:
-               devpermcheck(p->user, p->pipedir[2].perm, omode);
-               p->qref[1]++;
-               break;
+       switch (NETTYPE(c->qid.path)) {
+               case Qdata0:
+                       devpermcheck(p->user, p->pipedir[1].perm, omode);
+                       p->qref[0]++;
+                       break;
+               case Qdata1:
+                       devpermcheck(p->user, p->pipedir[2].perm, omode);
+                       p->qref[1]++;
+                       break;
        }
        poperror();
        qunlock(&p->qlock);
        }
        poperror();
        qunlock(&p->qlock);
@@ -258,84 +255,81 @@ pipeopen(struct chan *c, int omode)
        return c;
 }
 
        return c;
 }
 
-static void
-pipeclose(struct chan *c)
+static void pipeclose(struct chan *c)
 {
        Pipe *p;
 
        p = c->aux;
        qlock(&p->qlock);
 
 {
        Pipe *p;
 
        p = c->aux;
        qlock(&p->qlock);
 
-       if(c->flag & COPEN){
+       if (c->flag & COPEN) {
                /*
                 *  closing either side hangs up the stream
                 */
                /*
                 *  closing either side hangs up the stream
                 */
-               switch(NETTYPE(c->qid.path)){
-               case Qdata0:
-                       p->qref[0]--;
-                       if(p->qref[0] == 0){
-                               qhangup(p->q[1], 0);
-                               qclose(p->q[0]);
-                       }
-                       break;
-               case Qdata1:
-                       p->qref[1]--;
-                       if(p->qref[1] == 0){
-                               qhangup(p->q[0], 0);
-                               qclose(p->q[1]);
-                       }
-                       break;
+               switch (NETTYPE(c->qid.path)) {
+                       case Qdata0:
+                               p->qref[0]--;
+                               if (p->qref[0] == 0) {
+                                       qhangup(p->q[1], 0);
+                                       qclose(p->q[0]);
+                               }
+                               break;
+                       case Qdata1:
+                               p->qref[1]--;
+                               if (p->qref[1] == 0) {
+                                       qhangup(p->q[0], 0);
+                                       qclose(p->q[1]);
+                               }
+                               break;
                }
        }
 
                }
        }
 
-       
        /*
         *  if both sides are closed, they are reusable
         */
        /*
         *  if both sides are closed, they are reusable
         */
-       if(p->qref[0] == 0 && p->qref[1] == 0){
+       if (p->qref[0] == 0 && p->qref[1] == 0) {
                qreopen(p->q[0]);
                qreopen(p->q[1]);
        }
 
                qreopen(p->q[0]);
                qreopen(p->q[1]);
        }
 
+       qunlock(&p->qlock);
        /*
         *  free the structure on last close
         */
        kref_put(&p->ref);
        /*
         *  free the structure on last close
         */
        kref_put(&p->ref);
-       qunlock(&p->qlock);
 }
 
 }
 
-static long
-piperead(struct chan *c, void *va, long n, int64_t ignored)
+static long piperead(struct chan *c, void *va, long n, int64_t ignored)
 {
        Pipe *p;
 
        p = c->aux;
 
 {
        Pipe *p;
 
        p = c->aux;
 
-       switch(NETTYPE(c->qid.path)){
-       case Qdir:
-               return devdirread(c, va, n, p->pipedir, ARRAY_SIZE(pipedir), pipegen);
-       case Qdata0:
-               return qread(p->q[0], va, n);
-       case Qdata1:
-               return qread(p->q[1], va, n);
-       default:
-               panic("piperead");
+       switch (NETTYPE(c->qid.path)) {
+               case Qdir:
+                       return devdirread(c, va, n, p->pipedir, ARRAY_SIZE(pipedir),
+                                                         pipegen);
+               case Qdata0:
+                       return qread(p->q[0], va, n);
+               case Qdata1:
+                       return qread(p->q[1], va, n);
+               default:
+                       panic("piperead");
        }
        return -1;      /* not reached */
 }
 
        }
        return -1;      /* not reached */
 }
 
-static struct block*
-pipebread(struct chan *c, long n, uint32_t offset)
+static struct block *pipebread(struct chan *c, long n, uint32_t offset)
 {
        Pipe *p;
 
        p = c->aux;
 
 {
        Pipe *p;
 
        p = c->aux;
 
-       switch(NETTYPE(c->qid.path)){
-       case Qdata0:
-               return qbread(p->q[0], n);
-       case Qdata1:
-               return qbread(p->q[1], n);
+       switch (NETTYPE(c->qid.path)) {
+               case Qdata0:
+                       return qbread(p->q[0], n);
+               case Qdata1:
+                       return qbread(p->q[1], n);
        }
 
        return devbread(c, n, offset);
        }
 
        return devbread(c, n, offset);
@@ -345,16 +339,15 @@ pipebread(struct chan *c, long n, uint32_t offset)
  *  a write to a closed pipe causes an exception to be sent to
  *  the prog.
  */
  *  a write to a closed pipe causes an exception to be sent to
  *  the prog.
  */
-static long
-pipewrite(struct chan *c, void *va, long n, int64_t ignored)
+static long pipewrite(struct chan *c, void *va, long n, int64_t ignored)
 {
        ERRSTACK(2);
        Pipe *p;
        //Prog *r;
 
 {
        ERRSTACK(2);
        Pipe *p;
        //Prog *r;
 
-       if(waserror()) {
+       if (waserror()) {
                /* avoid exceptions when pipe is a mounted queue */
                /* avoid exceptions when pipe is a mounted queue */
-               if((c->flag & CMSG) == 0) {
+               if ((c->flag & CMSG) == 0) {
 /*
                        r = up->iprog;
                        if(r != NULL && r->kill == NULL)
 /*
                        r = up->iprog;
                        if(r != NULL && r->kill == NULL)
@@ -366,32 +359,31 @@ pipewrite(struct chan *c, void *va, long n, int64_t ignored)
 
        p = c->aux;
 
 
        p = c->aux;
 
-       switch(NETTYPE(c->qid.path)){
-       case Qdata0:
-               n = qwrite(p->q[1], va, n);
-               break;
+       switch (NETTYPE(c->qid.path)) {
+               case Qdata0:
+                       n = qwrite(p->q[1], va, n);
+                       break;
 
 
-       case Qdata1:
-               n = qwrite(p->q[0], va, n);
-               break;
+               case Qdata1:
+                       n = qwrite(p->q[0], va, n);
+                       break;
 
 
-       default:
-               panic("pipewrite");
+               default:
+                       panic("pipewrite");
        }
 
        poperror();
        return n;
 }
 
        }
 
        poperror();
        return n;
 }
 
-static long
-pipebwrite(struct chan *c, struct block *bp, uint32_t junk)
+static long pipebwrite(struct chan *c, struct block *bp, uint32_t junk)
 {
        ERRSTACK(2);
        long n;
        Pipe *p;
        //Prog *r;
 
 {
        ERRSTACK(2);
        long n;
        Pipe *p;
        //Prog *r;
 
-       if(waserror()) {
+       if (waserror()) {
                /* avoid exceptions when pipe is a mounted queue */
 /*
                if((c->flag & CMSG) == 0) {
                /* avoid exceptions when pipe is a mounted queue */
 /*
                if((c->flag & CMSG) == 0) {
@@ -404,55 +396,55 @@ pipebwrite(struct chan *c, struct block *bp, uint32_t junk)
        }
 
        p = c->aux;
        }
 
        p = c->aux;
-       switch(NETTYPE(c->qid.path)){
-       case Qdata0:
-               n = qbwrite(p->q[1], bp);
-               break;
-
-       case Qdata1:
-               n = qbwrite(p->q[0], bp);
-               break;
-
-       default:
-               n = 0;
-               panic("pipebwrite");
+       switch (NETTYPE(c->qid.path)) {
+               case Qdata0:
+                       n = qbwrite(p->q[1], bp);
+                       break;
+
+               case Qdata1:
+                       n = qbwrite(p->q[0], bp);
+                       break;
+
+               default:
+                       n = 0;
+                       panic("pipebwrite");
        }
 
        poperror();
        return n;
 }
 
        }
 
        poperror();
        return n;
 }
 
-static int
-pipewstat(struct chan *c, uint8_t *dp, int n)
+static int pipewstat(struct chan *c, uint8_t * dp, int n)
 {
        ERRSTACK(2);
        struct dir *d;
        Pipe *p;
        int d1;
 
 {
        ERRSTACK(2);
        struct dir *d;
        Pipe *p;
        int d1;
 
-       if (c->qid.type&QTDIR)
-               error(Eperm);
+       if (c->qid.type & QTDIR)
+               error(EPERM, NULL);
        p = c->aux;
        p = c->aux;
-       if(strcmp(current->user, p->user) != 0)
-               error(Eperm);
+       if (strcmp(current->user, p->user) != 0)
+               error(EPERM, NULL);
        d = kzmalloc(sizeof(*d) + n, 0);
        d = kzmalloc(sizeof(*d) + n, 0);
-       if(waserror()){
+       if (waserror()) {
                kfree(d);
                nexterror();
        }
                kfree(d);
                nexterror();
        }
-       n = convM2D(dp, n, d, ( char *)&d[1]);
-       if(n == 0)
-               error(Eshortstat);
+       n = convM2D(dp, n, d, (char *)&d[1]);
+       if (n == 0)
+               error(ENODATA, NULL);
        d1 = NETTYPE(c->qid.path) == Qdata1;
        d1 = NETTYPE(c->qid.path) == Qdata1;
-       if(!emptystr(d->name)){
+       if (!emptystr(d->name)) {
                validwstatname(d->name);
                validwstatname(d->name);
-               if(strlen(d->name) >= KNAMELEN)
-                       error(Efilename);
-               if(strcmp(p->pipedir[1+!d1].name, d->name) == 0)
-                       error(Eexist);
-               strncpy(p->pipedir[1+d1].name, d->name,  MIN(KNAMELEN, sizeof(p->pipedir[1+d1].name, d->name)));
+               if (strlen(d->name) >= KNAMELEN)
+                       error(ENAMETOOLONG, NULL);
+               if (strcmp(p->pipedir[1 + !d1].name, d->name) == 0)
+                       error(EEXIST, NULL);
+               strncpy(p->pipedir[1 + d1].name, d->name,
+                               MIN(KNAMELEN, sizeof(p->pipedir[1 + d1].name, d->name)));
        }
        }
-       if(d->mode != ~0UL)
+       if (d->mode != ~0UL)
                p->pipedir[d1 + 1].perm = d->mode & 0777;
        poperror();
        kfree(d);
                p->pipedir[d1 + 1].perm = d->mode & 0777;
        poperror();
        kfree(d);
@@ -460,7 +452,6 @@ pipewstat(struct chan *c, uint8_t *dp, int n)
 }
 
 struct dev pipedevtab __devtab = {
 }
 
 struct dev pipedevtab __devtab = {
-       '|',
        "pipe",
 
        devreset,
        "pipe",
 
        devreset,