Clarifies O_TRUNC warnings
[akaros.git] / kern / src / ns / sysfile.c
index 249edf4..f286fb7 100644 (file)
@@ -44,6 +44,18 @@ newfd(struct chan *c)
        struct fgrp *f = current->fgrp;
 
        spin_lock(&f->lock);
+       if (f->closed) {
+               spin_unlock(&f->lock);
+               return -1;
+       }
+       /* VFS hack */
+       /* We'd like to ask it to start at f->minfd, but that would require us to
+        * know if we closed anything.  Since we share the FD numbers with the VFS,
+        * there is no way to know that. */
+       i = get_fd(&current->open_files, 0);
+       assert(f->fd[i] == 0);
+       #if 0 // 9ns style
+       /* TODO: use a unique integer allocator */
        for(i=f->minfd; i<f->nfd; i++)
                if(f->fd[i] == 0)
                        break;
@@ -52,6 +64,7 @@ newfd(struct chan *c)
                exhausted("file descriptors");
                return -1;
        }
+       #endif
        f->minfd = i + 1;
        if(i > f->maxfd)
                f->maxfd = i;
@@ -68,6 +81,10 @@ fdtochan(struct fgrp *f, int fd, int mode, int chkmnt, int iref)
        c = 0;
 
        spin_lock(&f->lock);
+       if (f->closed) {
+               spin_unlock(&f->lock);
+               error("File group closed");
+       }
        if(fd<0 || f->maxfd<fd || (c = f->fd[fd])==0) {
                spin_unlock(&f->lock);
                error(Ebadfd);
@@ -85,13 +102,18 @@ fdtochan(struct fgrp *f, int fd, int mode, int chkmnt, int iref)
        if(mode<0 || c->mode==ORDWR)
                return c;
 
-       if((mode&OTRUNC) && c->mode==OREAD) {
+       if ((mode & OTRUNC) && IS_RDONLY(c->mode)) {
                if(iref)
                        cclose(c);
                error(Ebadusefd);
        }
 
+       /* TODO: this is probably wrong.  if you get this from a dev, in the dev's
+        * open, you are probably saving mode directly, without passing it through
+        * openmode. */
        if((mode&~OTRUNC) != c->mode) {
+               warn("Trunc mode issue: mode %o, mode minus trunc %o, chan mode %o\n",
+                    mode, mode & ~OTRUNC, c->mode);
                if(iref)
                        cclose(c);
                error(Ebadusefd);
@@ -103,18 +125,20 @@ fdtochan(struct fgrp *f, int fd, int mode, int chkmnt, int iref)
 long
 kchanio(void *vc, void *buf, int n, int mode)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        int r;
        struct chan *c;
 
        c = vc;
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
-       if(mode == OREAD)
-               r = devtab[c->type]->read(c, buf, n, c->offset);
+       if (IS_RDONLY(mode))
+               r = devtab[c->type].read(c, buf, n, c->offset);
        else
-               r = devtab[c->type]->write(c, buf, n, c->offset);
+               r = devtab[c->type].write(c, buf, n, c->offset);
 
        spin_lock(&c->lock);
        c->offset += r;
@@ -123,9 +147,14 @@ kchanio(void *vc, void *buf, int n, int mode)
        return r;
 }
 
-int
-openmode(uint32_t o)
+
+int openmode(uint32_t omode)
 {
+#if 0
+    /* this is the old plan9 style.  i think they want to turn exec into read,
+     * and strip off anything higher, and just return the RD/WR style bits.  not
+     * stuff like ORCLOSE.  the lack of OEXCL might be a bug on their part (it's
+     * the only one of their non-RW-related flags that isn't masked out) */
        if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC))
                error(Ebadarg);
        o &= ~(OTRUNC|OCEXEC|ORCLOSE);
@@ -134,6 +163,12 @@ openmode(uint32_t o)
        if(o == OEXEC)
                return OREAD;
        return o;
+#endif
+    /* no error checking (we have a shitload of flags anyway), and we return the
+     * basic access modes (RD/WR/ETC) */
+    if (omode == O_EXEC)
+        return O_RDONLY;
+    return omode & O_ACCMODE;
 }
 
 void
@@ -143,6 +178,10 @@ fdclose(struct fgrp *f, int fd)
        struct chan *c;
 
        spin_lock(&f->lock);
+       if (f->closed) {
+               spin_unlock(&f->lock);
+               return;
+       }
        c = f->fd[fd];
        if(c == 0){
                /* can happen for users with shared fd tables */
@@ -155,6 +194,8 @@ fdclose(struct fgrp *f, int fd)
                        f->maxfd = i;
        if(fd < f->minfd)
                f->minfd = fd;
+       /* VFS hack: give the FD back to VFS */
+       put_fd(&current->open_files, fd);
        spin_unlock(&f->lock);
        cclose(c);
 }
@@ -162,12 +203,14 @@ fdclose(struct fgrp *f, int fd)
 int
 syschdir(char *path)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        struct chan *c;
        struct pgrp *pg;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        c = namec(path, Atodir, 0, 0);
        pg = current->pgrp;
@@ -180,9 +223,11 @@ syschdir(char *path)
 int
 fgrpclose(struct fgrp *f, int fd)
 {
-       ERRSTACK(2);
-       if(waserror())
+       ERRSTACK(1);
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        /*
         * Take no reference on the chan because we don't really need the
@@ -208,8 +253,10 @@ syscreate(char *path, int mode, uint32_t perm)
        int fd;
        struct chan *c;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        openmode(mode&~OEXCL);  /* error check only; OEXCL okay here */
        c = namec(path, Acreate, mode, perm);
@@ -234,15 +281,23 @@ sysdup(int old, int new)
        struct chan *c, *oc;
        struct fgrp *f = current->fgrp;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        c = fdtochan(current->fgrp, old, -1, 0, 1);
        if(c->qid.type & QTAUTH)
                error(Eperm);
        fd = new;
        if(fd != -1){
+               /* ideally we'll be done with the VFS before we fix this */
+               panic("Need to sync with the VFS");
                spin_lock(&f->lock);
+               if (f->closed) {
+                       spin_unlock(&f->lock);
+                       return -1;
+               }
                if(fd<0 || growfd(f, fd) < 0) {
                        spin_unlock(&f->lock);
                        cclose(c);
@@ -274,33 +329,39 @@ sysfstat(int fd, uint8_t *buf, int n)
 {
        ERRSTACK(2);
        struct chan *c;
+       struct dir dir9ns;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        c = fdtochan(current->fgrp, fd, -1, 0, 1);
        if(waserror()) {
                cclose(c);
                nexterror();
        }
-       devtab[c->type]->stat(c, buf, n);
+       devtab[c->type].stat(c, (void*)&dir9ns, sizeof(struct dir));
 
        poperror();
        cclose(c);
 
        poperror();
+       convM2kstat((void*)&dir9ns, sizeof(struct dir), (struct kstat*)buf);
        return n;
 }
 
 char*
 sysfd2path(int fd)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        struct chan *c;
        char *s;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return NULL;
+       }
        c = fdtochan(current->fgrp, fd, -1, 0, 1);
        s = NULL;
        if(c->name != NULL){
@@ -322,8 +383,10 @@ sysfauth(int fd, char *aname)
        ERRSTACK(2);
        struct chan *c, *ac;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        validname(aname, 0);
        c = fdtochan(current->fgrp, fd, ORDWR, 0, 1);
@@ -360,8 +423,10 @@ sysfversion(int fd, unsigned int msize, char *vers, unsigned int arglen)
        int m;
        struct chan *c;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        /* check there's a NUL in the version string */
        if(arglen==0 || memchr(vers, 0, arglen)==0)
@@ -385,7 +450,7 @@ sysfversion(int fd, unsigned int msize, char *vers, unsigned int arglen)
 int
 syspipe(int fd[2])
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        struct dev *d;
        struct fgrp *f;
        struct chan *c[2];
@@ -393,7 +458,7 @@ syspipe(int fd[2])
 
        f = current->fgrp;
 
-       d = devtab[devno('|', 0)];
+       d = &devtab[devno('|', 0)];
        c[0] = namec("#|", Atodir, 0, 0);
        c[1] = 0;
        fd[0] = -1;
@@ -403,10 +468,17 @@ syspipe(int fd[2])
                        cclose(c[0]);
                if(c[1] != 0)
                        cclose(c[1]);
-               if(fd[0] >= 0)
+               if(fd[0] >= 0) {
+                       /* VFS hack */
+                       put_fd(&current->open_files, fd[0]);
                        f->fd[fd[0]]=0;
-               if(fd[1] >= 0)
+               }
+               if(fd[1] >= 0) {
+                       /* VFS hack */
+                       put_fd(&current->open_files, fd[1]);
                        f->fd[fd[1]]=0;
+               }
+               poperror();
                return -1;
        }
        c[1] = cclone(c[0]);
@@ -432,8 +504,10 @@ sysfwstat(int fd, uint8_t *buf, int n)
        ERRSTACK(2);
        struct chan *c;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        validstat(buf, n);
        c = fdtochan(current->fgrp, fd, -1, 1, 1);
@@ -441,7 +515,7 @@ sysfwstat(int fd, uint8_t *buf, int n)
                cclose(c);
                nexterror();
        }
-       n = devtab[c->type]->wstat(c, buf, n);
+       n = devtab[c->type].wstat(c, buf, n);
        poperror();
        cclose(c);
 
@@ -452,7 +526,7 @@ sysfwstat(int fd, uint8_t *buf, int n)
 long
 bindmount(struct chan *c, char *old, int flag, char *spec)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        int ret;
        struct chan *c1;
 
@@ -478,8 +552,10 @@ sysbind(char *new, char *old, int flags)
        long r;
        struct chan *c0;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        c0 = namec(new, Abind, 0, 0);
        if(waserror()) {
@@ -497,7 +573,7 @@ sysbind(char *new, char *old, int flags)
 int
 sysmount(int fd, int afd, char *old, int flags, char *spec)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        long r;
        volatile struct { struct chan *c; } c0;
        volatile struct { struct chan *c; } bc;
@@ -511,6 +587,7 @@ sysmount(int fd, int afd, char *old, int flags, char *spec)
                cclose(ac.c);
                cclose(bc.c);
                cclose(c0.c);
+               poperror();
                return -1;
        }
        bc.c = fdtochan(current->fgrp, fd, ORDWR, 0, 1);
@@ -520,7 +597,7 @@ sysmount(int fd, int afd, char *old, int flags, char *spec)
        mntparam.authchan = ac.c;
        mntparam.spec = spec;
        mntparam.flags = flags;
-       c0.c = devtab[devno('M', 0)]->attach(( char *)&mntparam);
+       c0.c = devtab[devno('M', 0)].attach(( char *)&mntparam);
 
        r = bindmount(c0.c, old, flags, spec);
        poperror();
@@ -534,7 +611,7 @@ sysmount(int fd, int afd, char *old, int flags, char *spec)
 int
 sysunmount(char *old, char *new)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        volatile struct { struct chan *c; } cmount;
        volatile struct { struct chan *c; } cmounted;
 
@@ -543,6 +620,7 @@ sysunmount(char *old, char *new)
        if(waserror()) {
                cclose(cmount.c);
                cclose(cmounted.c);
+               poperror();
                return -1;
        }
 
@@ -565,17 +643,19 @@ sysunmount(char *old, char *new)
 }
 
 int
-sysopen(char *path, int mode)
+sysopen(char *path, int vfs_flags)
 {
        ERRSTACK(2);
        int fd;
        struct chan *c;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
-       openmode(mode);                         /* error check only */
-       c = namec(path, Aopen, mode, 0);
+       openmode(vfs_flags);                         /* error check only */
+       c = namec(path, Aopen, vfs_flags, 0);
        if(waserror()){
                cclose(c);
                nexterror();
@@ -592,7 +672,7 @@ sysopen(char *path, int mode)
 long
 unionread(struct chan *c, void *va, long n)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        int i;
        long nr;
        struct mhead *m;
@@ -609,17 +689,19 @@ unionread(struct chan *c, void *va, long n)
        nr = 0;
        while(mount != NULL) {
                /* Error causes component of union to be skipped */
-               if(mount->to && !waserror()) {
-                       if(c->umc == NULL){
-                               c->umc = cclone(mount->to);
-                               c->umc = devtab[c->umc->type]->open(c->umc, OREAD);
-                       }
+               if(mount->to) {
+                       if (!waserror()) { /* discard style */
+                               if(c->umc == NULL){
+                                       c->umc = cclone(mount->to);
+                                       c->umc = devtab[c->umc->type].open(c->umc, OREAD);
+                               }
        
-                       nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset);
-                       if(nr < 0)
-                               nr = 0; /* dev.c can return -1 */
-                       c->umc->offset += nr;
-                       poperror();
+                               nr = devtab[c->umc->type].read(c->umc, va, n, c->umc->offset);
+                               if(nr < 0)
+                                       nr = 0; /* dev.c can return -1 */
+                               c->umc->offset += nr;
+                       }
+                       poperror(); /* pop regardless */
                }
                if(nr > 0)
                        break;
@@ -657,8 +739,16 @@ rread(int fd, void *va, long n, int64_t *offp)
        struct chan *c;
        int64_t off;
 
-       if(waserror())
+       /* dirty dirent hack */
+       void *real_va = va;
+       void *buf_for_M = 0;
+       long real_n = n;
+
+       if (waserror()) {
+               kfree(buf_for_M);
+               poperror();
                return -1;
+       }
 
        c = fdtochan(current->fgrp, fd, OREAD, 1, 1);
        if(waserror()) {
@@ -670,6 +760,25 @@ rread(int fd, void *va, long n, int64_t *offp)
                error(Etoosmall);
 
        dir = c->qid.type & QTDIR;
+
+       /* dirty kdirent hack: userspace is expecting kdirents, but all of 9ns
+        * produces Ms.  i'm assuming we're only being asked to read a single
+        * dirent, which is usually the case for calls like readdir() (which just
+        * calls read for a single dirent).
+        *
+        * another thing: the chan's offset moves forward by an amount such that a
+        * future read of the chan will give the next dirent.  we also return n,
+        * the amount of reading from the 9ns system.  this is fine, since it is
+        * where we'll pick up next time (off += n, from userspace).  we might need
+        * to put that info in d_off, but it seems to work (and no one wants to
+        * mess with glibc code) */
+       if (dir) {
+               assert(n >= sizeof(struct kdirent));
+               buf_for_M = kmalloc(sizeof(struct dir), KMALLOC_WAIT);
+               va = buf_for_M;
+               n = sizeof(struct dir);
+       }
+
        if(dir && c->umh)
                n = unionread(c, va, n);
        else{
@@ -690,12 +799,18 @@ rread(int fd, void *va, long n, int64_t *offp)
                        }
                        unionrewind(c);
                }
-               n = devtab[c->type]->read(c, va, n, off);
+               n = devtab[c->type].read(c, va, n, off);
                spin_lock(&c->lock);
                c->offset += n;
                spin_unlock(&c->lock);
        }
 
+       /* dirty kdirent hack */
+       if (dir) {
+               convM2kdirent(buf_for_M, sizeof(struct dir), real_va, 0);
+               kfree(buf_for_M);
+       }
+
        poperror();
        cclose(c);
 
@@ -721,8 +836,10 @@ sysremove(char *path)
        ERRSTACK(2);
        struct chan *c;
 
-       if(waserror())
-               return -1;
+       if (waserror()) {
+               poperror();
+               return -1; 
+       }
 
        c = namec(path, Aremove, 0, 0);
        if(waserror()) {
@@ -730,7 +847,7 @@ sysremove(char *path)
                cclose(c);
                nexterror();
        }
-       devtab[c->type]->remove(c);
+       devtab[c->type].remove(c);
        /*
         * Remove clunks the fid, but we need to recover the Chan
         * so fake it up.  rootclose() is known to be a nop.
@@ -750,8 +867,10 @@ sysseek(int fd, int64_t off, int whence)
        struct dir *dir;
        struct chan *c;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        c = fdtochan(current->fgrp, fd, -1, 1, 1);
        if(waserror()) {
@@ -759,7 +878,7 @@ sysseek(int fd, int64_t off, int whence)
                nexterror();
        }
 
-       if(devtab[c->type]->dc == '|')
+       if(devtab[c->type].dc == '|')
                error(Eisstream);
 
        switch(whence) {
@@ -846,33 +965,39 @@ sysstat(char *path, uint8_t *buf, int n)
 {
        ERRSTACK(2);
        struct chan *c;
+       struct dir dir9ns;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        c = namec(path, Aaccess, 0, 0);
        if(waserror()){
                cclose(c);
                nexterror();
        }
-       devtab[c->type]->stat(c, buf, n);
+       devtab[c->type].stat(c, (void*)&dir9ns, sizeof(struct dir));
        poperror();
        cclose(c);
 
        poperror();
+       convM2kstat((void*)&dir9ns, sizeof(struct dir), (struct kstat*)buf);
        return 0;
 }
 
 static long
 rwrite(int fd, void *va, long n, int64_t *offp)
 {
-       ERRSTACK(2);
+       ERRSTACK(3);
        struct chan *c;
        int64_t off;
        long m;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
        c = fdtochan(current->fgrp, fd, OWRITE, 1, 1);
        if(waserror()) {
                cclose(c);
@@ -902,7 +1027,7 @@ rwrite(int fd, void *va, long n, int64_t *offp)
        }
        if(off < 0)
                error(Enegoff);
-       m = devtab[c->type]->write(c, va, n, off);
+       m = devtab[c->type].write(c, va, n, off);
        poperror();
 
        if(offp == NULL && m < n){
@@ -936,8 +1061,10 @@ syswstat(char *path, uint8_t *buf, int n)
        ERRSTACK(2);
        struct chan *c;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
 
        validstat(buf, n);
        c = namec(path, Aaccess, 0, 0);
@@ -945,7 +1072,7 @@ syswstat(char *path, uint8_t *buf, int n)
                cclose(c);
                nexterror();
        }
-       n = devtab[c->type]->wstat(c, buf, n);
+       n = devtab[c->type].wstat(c, buf, n);
        poperror();
        cclose(c);
 
@@ -962,7 +1089,7 @@ enum
 struct dir*
 chandirstat(struct chan *c)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        struct dir *d;
        uint8_t *buf;
        int n, nd, i;
@@ -973,9 +1100,10 @@ chandirstat(struct chan *c)
                buf = ( uint8_t *)&d[1];
                if(waserror()){
                        kfree(d);
+                       poperror();
                        return NULL;
                }
-               n = devtab[c->type]->stat(c, buf, nd);
+               n = devtab[c->type].stat(c, buf, nd);
                poperror();
                if(n < BIT16SZ){
                        kfree(d);
@@ -1000,8 +1128,10 @@ sysdirstat(char *name)
        struct chan *c;
        struct dir *d;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return NULL;
+       }
 
        c = namec(name, Aaccess, 0, 0);
        if(waserror()){
@@ -1023,8 +1153,10 @@ sysdirfstat(int fd)
        struct chan *c;
        struct dir *d;
 
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return NULL;
+       }
 
        c = fdtochan(current->fgrp, fd, -1, 0, 1);
        if(waserror()) {
@@ -1068,10 +1200,10 @@ sysdirfwstat(int fd, struct dir *dir)
 }
 
 static long
-dirpackage(uint8_t *buf, long ts, struct dir **d)
+dirpackage(uint8_t *buf, long ts, struct kdirent **d)
 {
        char *s;
-       long ss, i, n, nn, m;
+       long ss, i, n, nn, m = 0;
 
        *d = NULL;
        if(ts <= 0)
@@ -1093,18 +1225,18 @@ dirpackage(uint8_t *buf, long ts, struct dir **d)
        if(i != ts)
                error("bad directory format");
 
-       *d = kzmalloc(n * sizeof(struct dir) + ss, 0);
+       *d = kzmalloc(n * sizeof(**d) + ss, 0);
        if(*d == NULL)
                error(Enomem);
 
        /*
         * then convert all buffers
         */
-       s = ( char *)*d + n * sizeof(struct dir);
+       s = ( char *)*d + n * sizeof(**d);
        nn = 0;
        for(i = 0; i < ts; i += m){
                m = BIT16SZ + GBIT16(( uint8_t *)&buf[i]);
-               if(nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){
+               if(nn >= n || /*convM2D*/convM2kdirent(&buf[i], m, *d + nn, s) != m){
                        kfree(*d);
                        *d = NULL;
                        error("bad directory entry");
@@ -1117,15 +1249,17 @@ dirpackage(uint8_t *buf, long ts, struct dir **d)
 }
 
 long
-sysdirread(int fd, struct dir **d)
+sysdirread(int fd, struct kdirent **d)
 {
        ERRSTACK(2);
        uint8_t *buf;
        long ts;
 
        *d = NULL;
-       if(waserror())
+       if (waserror()) {
+               poperror();
                return -1;
+       }
        buf = kzmalloc(DIRREADLIM, 0);
        if(buf == NULL)
                error(Enomem);
@@ -1145,13 +1279,14 @@ sysdirread(int fd, struct dir **d)
 int
 sysiounit(int fd)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        struct chan *c;
        int n;
 
        c = fdtochan(current->fgrp, fd, -1, 0, 1);
        if(waserror()){
                cclose(c);
+               poperror();
                return 0;       /* n.b. */
        }
        n = c->iounit;
@@ -1196,18 +1331,19 @@ void close_9ns_files(struct proc *p, bool only_cloexec)
        }
 }
 
-void print_chaninfo(struct chan *ch)
+void print_chaninfo(struct chan *c)
 {
        char buf[64] = {0};
-#if 0
-FIXME
+       bool has_dev = c->type != -1;
        printk("Chan pathname: %s, Dev: %s, Devinfo: %s\n",
-              "ch->path ? ch->path->s : \"no path",
-              ch->dev ? ch->dev->name: "no dev",
-                  ch->dev ? ch->dev->chaninfo(ch, buf, sizeof(buf)) : "no info");
-       if (!ch->dev)
-               printk("No dev: intermediate chan? qid.path: %p\n", ch->qid.path);
-#endif
+              c->name ? c->name->s : "no cname",
+              has_dev ? devtab[c->type].name : "no dev",
+                  /* TODO: chaninfo op */
+              //has_dev ? devtab[c->type].chaninfo(c, buf, sizeof(buf)) :
+                              "no info");
+       if (!has_dev)
+               printk("No dev: intermediate chan? qid.path: %p\n", c->qid.path);
+       printk("\n");
 }
 
 void print_9ns_files(struct proc *p)
@@ -1233,7 +1369,7 @@ int plan9setup(struct proc *new_proc, struct proc *parent)
        struct kref *new_dot_ref;
        ERRSTACK(1);
        if (waserror()) {
-               printd("plan9setup failed\n");
+               printk("plan9setup failed, %s\n", current_errstr());
                poperror();
                return -1;
        }
@@ -1244,14 +1380,16 @@ int plan9setup(struct proc *new_proc, struct proc *parent)
                 * TODO: One problem is namec wants a current set for things like
                 * genbuf.  So we'll use new_proc for this bootstrapping.  Note
                 * switch_to() also loads the cr3. */
-               new_proc->fgrp = dupfgrp(NULL);
+               new_proc->fgrp = newfgrp();
                new_proc->pgrp = newpgrp();
                old_current = switch_to(new_proc);
                new_proc->slash = namec("#r", Atodir, 0, 0);
+               if (!new_proc->slash)
+                       panic("no root device");
                switch_back(new_proc, old_current);
                /* Want the name to be "/" instead of "#r" */
-               pathclose(new_proc->slash->path);
-               new_proc->slash->path = newpath("/");
+               cnameclose(new_proc->slash->name);
+               new_proc->slash->name = newcname("/");
                new_proc->dot = cclone(new_proc->slash);
                poperror();
                return 0;