qio: remove qproduce()
[akaros.git] / kern / drivers / dev / mnt.c
index b5769cf..b9036cc 100644 (file)
@@ -1,4 +1,31 @@
-// INFERNO
+/* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+ * Portions Copyright © 1997-1999 Vita Nuova Limited
+ * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
+ *                                (www.vitanuova.com)
+ * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+ *
+ * Modified for the Akaros operating system:
+ * Copyright (c) 2013-2014 The Regents of the University of California
+ * Copyright (c) 2013-2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE. */
+
 #include <vfs.h>
 #include <kfs.h>
 #include <slab.h>
@@ -97,9 +124,6 @@ void mountrpc(struct mnt *, struct mntrpc *);
 int rpcattn(void *);
 struct chan *mntchan(void);
 
-char Esbadstat[] = "invalid directory entry received from server";
-char Enoversion[] = "version not established for mount channel";
-
 void (*mntstats) (int unused_int, struct chan *, uint64_t, uint32_t);
 
 static void mntinit(void)
@@ -145,9 +169,9 @@ long mntversion(struct chan *c, char *version, int msize, int returnlen)
 
        /* validity */
        if (msize < 0)
-               error("bad iounit in version call");
+               error(EFAIL, "bad iounit in version call");
        if (strncmp(v, VERSION9P, strlen(VERSION9P)) != 0)
-               error("bad 9P version specification");
+               error(EFAIL, "bad 9P version specification");
 
        m = c->mux;
 
@@ -155,16 +179,16 @@ long mntversion(struct chan *c, char *version, int msize, int returnlen)
                qunlock(&c->umqlock);
                poperror();
 
-               strncpy(buf, m->version, sizeof buf);
+               strlcpy(buf, m->version, sizeof(buf));
                k = strlen(buf);
                if (strncmp(buf, v, k) != 0) {
                        snprintf(buf, sizeof buf, "incompatible 9P versions %s %s",
                                         m->version, v);
-                       error(buf);
+                       error(EFAIL, buf);
                }
                if (returnlen > 0) {
                        if (returnlen < k)
-                               error(Eshort);
+                               error(ENAMETOOLONG, ERROR_FIXME);
                        memmove(version, buf, k);
                }
                return k;
@@ -183,7 +207,7 @@ long mntversion(struct chan *c, char *version, int msize, int returnlen)
        }
        k = convS2M(&f, msg, 8192 + IOHDRSZ);
        if (k == 0)
-               error("bad fversion conversion on send");
+               error(EFAIL, "bad fversion conversion on send");
 
        spin_lock(&c->lock);
        oo = c->offset;
@@ -196,13 +220,13 @@ long mntversion(struct chan *c, char *version, int msize, int returnlen)
                spin_lock(&c->lock);
                c->offset -= k - l;
                spin_unlock(&c->lock);
-               error("short write in fversion");
+               error(EFAIL, "short write in fversion");
        }
 
        /* message sent; receive and decode reply */
        k = devtab[c->type].read(c, msg, 8192 + IOHDRSZ, c->offset);
        if (k <= 0)
-               error("EOF receiving fversion reply");
+               error(EFAIL, "EOF receiving fversion reply");
 
        spin_lock(&c->lock);
        c->offset += k;
@@ -210,18 +234,18 @@ long mntversion(struct chan *c, char *version, int msize, int returnlen)
 
        l = convM2S(msg, k, &f);
        if (l != k)
-               error("bad fversion conversion on reply");
+               error(EFAIL, "bad fversion conversion on reply");
        if (f.type != Rversion) {
                if (f.type == Rerror)
-                       error(f.ename);
-               error("unexpected reply type in fversion");
+                       error(EFAIL, f.ename);
+               error(EFAIL, "unexpected reply type in fversion");
        }
        if (f.msize > msize)
-               error("server tries to increase msize in fversion");
+               error(EFAIL, "server tries to increase msize in fversion");
        if (f.msize < 256 || f.msize > 1024 * 1024)
-               error("nonsense value of msize in fversion");
+               error(EFAIL, "nonsense value of msize in fversion");
        if (strncmp(f.version, v, strlen(f.version)) != 0)
-               error("bad 9P version returned from server");
+               error(EFAIL, "bad 9P version returned from server");
 
        /* now build Mnt associated with this connection */
        spin_lock(&mntalloc.l);
@@ -261,7 +285,7 @@ long mntversion(struct chan *c, char *version, int msize, int returnlen)
        k = strlen(f.version);
        if (returnlen > 0) {
                if (returnlen < k)
-                       error(Eshort);
+                       error(ENAMETOOLONG, ERROR_FIXME);
                memmove(version, f.version, k);
        }
 
@@ -280,7 +304,7 @@ struct chan *mntauth(struct chan *c, char *spec)
                mntversion(c, VERSION9P, MAXRPC, 0);
                m = c->mux;
                if (m == NULL)
-                       error(Enoversion);
+                       error(EINVAL, ERROR_FIXME);
        }
 
        c = mntchan();
@@ -342,7 +366,7 @@ static struct chan *mntattach(char *muxattach)
                mntversion(c, NULL, 0, 0);
                m = c->mux;
                if (m == NULL)
-                       error(Enoversion);
+                       error(EINVAL, ERROR_FIXME);
        }
 
        c = mntchan();
@@ -413,10 +437,10 @@ static struct walkqid *mntwalk(struct chan *c, struct chan *nc, char **name,
        if (nc != NULL)
                printd("mntwalk: nc != NULL\n");
        if (nname > MAXWELEM)
-               error("devmnt: too many name elements");
+               error(EFAIL, "devmnt: too many name elements");
        alloc = 0;
        wq = kzmalloc(sizeof(struct walkqid) + nname * sizeof(struct qid),
-                                 KMALLOC_WAIT);
+                                 MEM_WAIT);
        if (waserror()) {
                if (alloc && wq->clone != NULL)
                        cclose(wq->clone);
@@ -451,7 +475,7 @@ static struct walkqid *mntwalk(struct chan *c, struct chan *nc, char **name,
        mountrpc(m, r);
 
        if (r->reply.nwqid > nname)
-               error("too many QIDs returned by walk");
+               error(EFAIL, "too many QIDs returned by walk");
        if (r->reply.nwqid < nname) {
                if (alloc)
                        cclose(nc);
@@ -491,7 +515,7 @@ static int mntstat(struct chan *c, uint8_t * dp, int n)
        struct mntrpc *r;
 
        if (n < BIT16SZ)
-               error(Eshortstat);
+               error(EINVAL, ERROR_FIXME);
        m = mntchk(c);
        r = mntralloc(c, m->msize);
        if (waserror()) {
@@ -794,13 +818,14 @@ void mountrpc(struct mnt *m, struct mntrpc *r)
                                isxdigit(e[1]) &&
                                isxdigit(e[2]) &&
                                isxdigit(e[3])) {
+
                                int errno = strtoul(e, NULL, 16);
-                               set_errno(errno);
-                               error(&r->reply.ename[5]);
+
+                               error(errno, &r->reply.ename[5]);
                        } else
-                               error(r->reply.ename);
+                               error(EFAIL, r->reply.ename);
                case Rflush:
-                       error(Eintr);
+                       error(EINTR, ERROR_FIXME);
                default:
                        if (t == r->request.type + 1)
                                break;
@@ -814,7 +839,7 @@ void mountrpc(struct mnt *m, struct mntrpc *r)
                                ("mnt: proc %s %lu: mismatch from %s %s rep 0x%p tag %d fid %d T%d R%d rp %d\n",
                                 "current->text", "current->pid", sn, cn, r, r->request.tag,
                                 r->request.fid, r->request.type, r->reply.type, r->reply.tag);
-                       error(Emountrpc);
+                       error(EPROTO, ERROR_FIXME);
        }
 }
 
@@ -830,8 +855,7 @@ void mountio(struct mnt *m, struct mntrpc *r)
                 * the old request to a flsh (mntflushalloc) and try again.  We'll
                 * always try to flush, and you can't get out until the flush either
                 * succeeds or errors out with a non-abort/Eintr error. */
-               if (strcmp(current_errstr(), "syscall aborted") &&
-                   strcmp(current_errstr(), Eintr)) {
+               if (get_errno() != EINTR) {
                        /* all other errors (not abort or Eintr) */
                        mntflushfree(m, r);
                        nexterror();
@@ -854,7 +878,7 @@ void mountio(struct mnt *m, struct mntrpc *r)
        if (n < 0)
                panic("bad message type in mountio");
        if (devtab[m->c->type].write(m->c, r->rpc, n, 0) != n)
-               error(Emountrpc);
+               error(EIO, ERROR_FIXME);
 /*     r->stime = fastticks(NULL); */
        r->reqlen = n;
 
@@ -875,7 +899,7 @@ void mountio(struct mnt *m, struct mntrpc *r)
        spin_unlock(&m->lock);
        while (r->done == 0) {
                if (mntrpcread(m, r) < 0)
-                       error(Emountrpc);
+                       error(EIO, ERROR_FIXME);
                mountmux(m, r);
        }
        mntgate(m);
@@ -960,7 +984,7 @@ int mntrpcread(struct mnt *m, struct mntrpc *r)
                        l = &(b->next);
                } else {
                        /* split block and put unused bit back */
-                       nb = allocb(i - len);
+                       nb = block_alloc(i - len, MEM_WAIT);
                        memmove(nb->wp, b->rp + len, i - len);
                        b->wp = b->rp + len;
                        nb->wp += i - len;
@@ -1097,7 +1121,7 @@ struct mntrpc *mntralloc(struct chan *c, uint32_t msize)
                 * The header is split from the data buffer as
                 * mountmux may swap the buffer with another header.
                 */
-               new->rpc = kzmalloc(msize, KMALLOC_WAIT);
+               new->rpc = kzmalloc(msize, MEM_WAIT);
                if (new->rpc == NULL) {
                        kfree(new);
                        spin_unlock(&mntalloc.l);
@@ -1115,7 +1139,7 @@ struct mntrpc *mntralloc(struct chan *c, uint32_t msize)
                mntalloc.nrpcfree--;
                if (new->rpclen < msize) {
                        kfree(new->rpc);
-                       new->rpc = kzmalloc(msize, KMALLOC_WAIT);
+                       new->rpc = kzmalloc(msize, MEM_WAIT);
                        if (new->rpc == NULL) {
                                kfree(new);
                                mntalloc.nrpcused--;
@@ -1201,11 +1225,13 @@ struct mnt *mntchk(struct chan *c)
  */
 void mntdirfix(uint8_t * dirbuf, struct chan *c)
 {
-       unsigned int r;
-
-       r = devtab[c->type].dc;
+       /* TODO: We used to use the device's char (dc), instead of the type.  not
+        * sure about the effects one way or the other.  This might be the type[2]
+        * and dev[4] in a D (struct dir, see 9p's stat
+        * (http://man.cat-v.org/plan_9/5/stat).  In which case, those should be for
+        * the kernel's use.  Hopefully our kernel. */
        dirbuf += BIT16SZ;      /* skip count */
-       PBIT16(dirbuf, r);
+       PBIT16(dirbuf, c->type);
        dirbuf += BIT16SZ;
        PBIT32(dirbuf, c->dev);
 }
@@ -1219,24 +1245,23 @@ int rpcattn(void *v)
 }
 
 struct dev mntdevtab __devtab = {
-       'M',
-       "mnt",
-
-       devreset,
-       mntinit,
-       devshutdown,
-       mntattach,
-       mntwalk,
-       mntstat,
-       mntopen,
-       mntcreate,
-       mntclose,
-       mntread,
-       devbread,
-       mntwrite,
-       devbwrite,
-       mntremove,
-       mntwstat,
-       devpower,
-       devchaninfo,
+       .name = "mnt",
+
+       .reset = devreset,
+       .init = mntinit,
+       .shutdown = devshutdown,
+       .attach = mntattach,
+       .walk = mntwalk,
+       .stat = mntstat,
+       .open = mntopen,
+       .create = mntcreate,
+       .close = mntclose,
+       .read = mntread,
+       .bread = devbread,
+       .write = mntwrite,
+       .bwrite = devbwrite,
+       .remove = mntremove,
+       .wstat = mntwstat,
+       .power = devpower,
+       .chaninfo = devchaninfo,
 };