Added explicit errno reporting from error() API.
[akaros.git] / kern / drivers / dev / srv.c
index fbe08bd..704b6a1 100644 (file)
 #include <ip.h>
 #include <sys/queue.h>
 
+struct dev srvdevtab;
+
+static char *devname(void)
+{
+       return srvdevtab.name;
+}
+
 #define Qtopdir                        1
 #define Qsrvfile               2
 
@@ -81,7 +88,7 @@ static void srv_release(struct kref *kref)
        if (srv->chan)
                cclose(srv->chan);
        kfree(srv);
-       atomic_dec(nr_srvs);
+       atomic_dec(&nr_srvs);
 }
 
 static int srvgen(struct chan *c, char *name, struct dirtab *tab,
@@ -93,7 +100,7 @@ static int srvgen(struct chan *c, char *name, struct dirtab *tab,
        if (s == DEVDOTDOT) {
                /* changing whatever c->aux was to be topdir */
                mkqid(&q, Qtopdir, 0, QTDIR);
-               devdir(c, q, "#s", 0, eve, 0555, dp);
+               devdir(c, q, devname(), 0, eve, 0555, dp);
                return 1;
        }
        spin_lock(&srvlock);
@@ -138,7 +145,7 @@ static struct chan *srvattach(char *spec)
 {
        /* the inferno attach was pretty complicated, but
         * we're not sure that complexity is needed. */
-       struct chan *c = devattach('s', spec);
+       struct chan *c = devattach(devname(), spec);
        mkqid(&c->qid, Qtopdir, 0, QTDIR);
        /* c->aux is an uncounted ref */
        c->aux = top_dir;
@@ -156,14 +163,34 @@ static int srvstat(struct chan *c, uint8_t * db, int n)
        return devstat(c, db, n, 0, 0, srvgen);
 }
 
+char*
+srvname(struct chan *c)
+{
+       struct srvfile *srv_i;
+       char *s;
+
+       spin_lock(&srvlock);
+       TAILQ_FOREACH(srv_i, &srvfiles, link) {
+               if(srv_i->chan == c){
+                       int len = 3 + strlen(srv_i->name) + 1;
+                       s = kzmalloc(len, 0);
+                       snprintf(s, len, "#s/%s", srv_i->name);
+                       spin_unlock(&srvlock);
+                       return s;
+               }
+       }
+       spin_unlock(&srvlock);
+       return NULL;
+}
+
 static struct chan *srvopen(struct chan *c, int omode)
 {
        ERRSTACK(1);
        struct srvfile *srv;
        openmode(omode);        /* used as an error checker in plan9, does little now */
        if (c->qid.type & QTDIR) {
-               if (!IS_RDONLY(omode))
-                       error(Eisdir);
+               if (omode & O_WRITE)
+                       error(EISDIR, NULL);
                c->mode = openmode(omode);
                c->flag |= COPEN;
                c->offset = 0;
@@ -171,7 +198,7 @@ static struct chan *srvopen(struct chan *c, int omode)
        }
        srv = c->aux;
        if (!grab_ref(srv))
-               error("Unable to open srv file, concurrent removal");
+               error(EFAIL, "Unable to open srv file, concurrent removal");
        if (waserror()) {
                kref_put(&srv->ref);
                nexterror();
@@ -181,23 +208,23 @@ static struct chan *srvopen(struct chan *c, int omode)
 #if 0
        if (omode & ORCLOSE) {
                if (strcmp(srv->user, up->env->user) != 0)
-                       error(Eperm);
+                       error(EPERM, NULL);
                else
                        srv->flags |= SORCLOSE;
        }
 #endif
        if ((srv->perm & DMEXCL) && atomic_read(&srv->opens))
-               error(Einuse);
+               error(EBUSY, NULL);
        /* srv->chan is write-once, so we don't need to sync. */
        if (!srv->chan)
-               error("srv file has no chan yet");
+               error(EFAIL, "srv file has no chan yet");
        /* this is more than just the ref - 1, since there will be refs in flight
         * as gens work their way through the list */
        atomic_inc(&srv->opens);
        /* the magic of srv: open c, get c->srv->chan back */
        cclose(c);
        c = srv->chan;
-       kref_get(&c->ref, 1);
+       chan_incref(c);
        poperror();
        kref_put(&srv->ref);
        return c;
@@ -224,7 +251,7 @@ static void srvcreate(struct chan *c, char *name, int omode, uint32_t perm)
 
 static int srvwstat(struct chan *c, uint8_t * dp, int n)
 {
-       error("srvwstat not supported yet");
+       error(ENOSYS, NULL);
        return -1;
 }
 
@@ -270,16 +297,16 @@ static long srvwrite(struct chan *c, void *va, long count, int64_t offset)
        int fd;
 
        if (c->qid.type & QTDIR)
-               error(Eperm);
+               error(EPERM, NULL);
        srv = c->aux;
        if (!grab_ref(srv))
-               error("Unable to write srv file, concurrent removal");
+               error(EFAIL, "Unable to write srv file, concurrent removal");
        if (waserror()) {
                kref_put(&srv->ref);
                nexterror();
        }
        if (srv->chan)
-               error("srv file already has a stored chan!");
+               error(EFAIL, "srv file already has a stored chan!");
        if (waserror()) {
                kfree(kbuf);
                nexterror();
@@ -290,11 +317,11 @@ static long srvwrite(struct chan *c, void *va, long count, int64_t offset)
        fd = strtoul(kbuf, 0, 10);
        /* the magic of srv: srv stores the chan corresponding to the fd.  -1 for
         * mode, so we just get the chan with no checks (RDWR would work too). */
-       new_chan = fdtochan(current->fgrp, fd, -1, FALSE, TRUE);
+       new_chan = fdtochan(&current->open_files, fd, -1, FALSE, TRUE);
        /* fdtochan already increffed for us */
        if (!__sync_bool_compare_and_swap(&srv->chan, 0, new_chan)) {
                cclose(new_chan);
-               error("srv file already has a stored chan!");
+               error(EFAIL, "srv file already has a stored chan!");
        }
        poperror();
        kfree(kbuf);
@@ -304,7 +331,6 @@ static long srvwrite(struct chan *c, void *va, long count, int64_t offset)
 }
 
 struct dev srvdevtab __devtab = {
-       's',
        "srv",
 
        devreset,