Implement 9ns FD functions with fd tables
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 24 Jul 2015 15:55:43 +0000 (11:55 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 28 Jul 2015 23:57:18 +0000 (19:57 -0400)
Now the 9ns and VFS share the FD table, instead of using separate tables
(e.g. the fgrp).

kern/src/ns/sysfile.c
kern/src/process.c
kern/src/syscall.c
kern/src/vfs.c

index 05e4aa1..7e27cd9 100644 (file)
@@ -55,61 +55,26 @@ static int growfd(struct fgrp *f, int fd)
 
 int newfd(struct chan *c, int oflags)
 {
-       int i;
-       struct fgrp *f = current->open_files.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. */
-#if 1  // VFS hack
-       i = get_fd(&current->open_files, 0, oflags & O_CLOEXEC);
-#else  // 9ns style
-       /* TODO: use a unique integer allocator */
-       for (i = f->minfd; i < f->nfd; i++)
-               if (f->fd[i] == 0)
-                       break;
-#endif
-       if (growfd(f, i) < 0) {
-               spin_unlock(&f->lock);
-               return -1;
-       }
-       assert(f->fd[i] == 0);
-       f->minfd = i + 1;
-       if (i > f->maxfd)
-               f->maxfd = i;
-       f->fd[i] = c;
-       spin_unlock(&f->lock);
-       return i;
+       int ret = insert_obj_fdt(&current->open_files, c, 0,
+                                oflags & O_CLOEXEC ? FD_CLOEXEC : 0,
+                                FALSE, FALSE);
+       if (ret >= 0)
+               cclose(c);
+       return ret;
 }
 
 struct chan *fdtochan(struct fd_table *fdt, int fd, int mode, int chkmnt,
                       int iref)
 {
-       struct fgrp *f = fdt->fgrp;
-       
        struct chan *c;
 
-       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);
+       c = lookup_fd(fdt, fd, iref, FALSE);
+       if (!c) {
+               /* We lost the info about why there was a problem (we used to track file
+                * group closed too, can add that in later). */
                set_errno(EBADF);
                error("Bad FD %d\n", fd);
        }
-       if (iref)
-               chan_incref(c);
-       spin_unlock(&f->lock);
 
        if (chkmnt && (c->flag & CMSG)) {
                if (iref)
@@ -193,32 +158,7 @@ int openmode(uint32_t omode)
 
 void fdclose(struct fd_table *fdt, int fd)
 {
-       struct fgrp *f = fdt->fgrp;
-       
-       int i;
-       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 */
-               spin_unlock(&f->lock);
-               return;
-       }
-       f->fd[fd] = 0;
-       if (fd == f->maxfd)
-               for (i = fd; --i >= 0 && f->fd[i] == 0;)
-                       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);
+       close_fd(fdt, fd);
 }
 
 int syschdir(char *path)
@@ -314,50 +254,30 @@ int sysdup(int old)
        return fd;
 }
 
-/* Could pass in the fgrp instead of the proc, but we need the to_proc for now
- * so we can claim a VFS FD */
+/* Could pass in the fdt instead of the proc, but we used to need the to_proc
+ * for now so we can claim a VFS FD.  Careful, we don't close the old chan. */
 int sys_dup_to(struct proc *from_proc, unsigned int from_fd,
                struct proc *to_proc, unsigned int to_fd)
 {
        ERRSTACK(1);
-       struct chan *c, *old_chan;
-       struct fgrp *to_fgrp = to_proc->open_files.fgrp;
+       int ret;
+       struct chan *c;
 
        if (waserror()) {
                poperror();
                return -1;
        }
-
        c = fdtochan(&from_proc->open_files, from_fd, -1, 0, 1);
        if (c->qid.type & QTAUTH) {
                cclose(c);
                error(Eperm);
        }
-
-       spin_lock(&to_fgrp->lock);
-       if (to_fgrp->closed) {
-               spin_unlock(&to_fgrp->lock);
-               cclose(c);
-               error("Can't dup, FGRP closed");
-       }
-       if (claim_fd(&to_proc->open_files, to_fd)) {
-               spin_unlock(&to_fgrp->lock);
-               cclose(c);
-               error("Can't claim FD %d", to_fd);
-       }
-       if (growfd(to_fgrp, to_fd) < 0) {
-               spin_unlock(&to_fgrp->lock);
-               cclose(c);
-               error(current_errstr());
-       }
-       if (to_fd > to_fgrp->maxfd)
-               to_fgrp->maxfd = to_fd;
-       old_chan = to_fgrp->fd[to_fd];
-       to_fgrp->fd[to_fd] = c;
-       spin_unlock(&to_fgrp->lock);
-       if (old_chan)
-               cclose(old_chan);
-
+       ret = insert_obj_fdt(&to_proc->open_files, c, to_fd, 0, TRUE, FALSE);
+       /* drop the ref from fdtochan.  if insert succeeded, there is one other ref
+        * stored in the FDT */
+       cclose(c);
+       if (ret < 0)
+               error("Can't insert FD %d into FDG", to_fd);
        poperror();
        return 0;
 }
@@ -459,32 +379,27 @@ int syspipe(int fd[2])
 {
        ERRSTACK(1);
        struct dev *d;
-       struct fgrp *f;
        struct chan *c[2];
        static char *names[] = { "data", "data1" };
 
-       f = current->open_files.fgrp;
-
        d = &devtab[devno('|', 0)];
        c[0] = namec("#|", Atodir, 0, 0);
        c[1] = 0;
        fd[0] = -1;
        fd[1] = -1;
        if (waserror()) {
-               if (c[0] != 0)
+               /* need to remove from the fd table and make sure the chan is closed
+                * exactly once.  if fd[i] >= 0, then the fd is valid (or it was!) and
+                * the fd table has the only ref (newfd() currently decrefs/consumes the
+                * reference).  cclose() doesn't care if you pass it 0 (like kfree()). */
+               if (fd[0] >= 0)
+                       close_fd(&current->open_files, fd[0]);
+               else
                        cclose(c[0]);
-               if (c[1] != 0)
+               if (fd[1] >= 0)
+                       close_fd(&current->open_files, fd[1]);
+               else
                        cclose(c[1]);
-               if (fd[0] >= 0) {
-                       /* VFS hack */
-                       f->fd[fd[0]] = 0;
-                       put_fd(&current->open_files, fd[0]);
-               }
-               if (fd[1] >= 0) {
-                       /* VFS hack */
-                       f->fd[fd[1]] = 0;
-                       put_fd(&current->open_files, fd[1]);
-               }
                poperror();
                return -1;
        }
index 97359b8..3764c19 100644 (file)
@@ -2298,14 +2298,19 @@ void print_proc_info(pid_t pid)
                return;
        }
        spin_lock(&files->lock);
-       for (int i = 0; i < files->max_files; i++)
-               if (GET_BITMASK_BIT(files->open_fds->fds_bits, i) &&
-                   (files->fd[i].fd_file)) {
-                       printk("\tFD: %02d, File: %p, File name: %s\n", i,
-                              files->fd[i].fd_file, file_name(files->fd[i].fd_file));
+       for (int i = 0; i < files->max_files; i++) {
+               if (GET_BITMASK_BIT(files->open_fds->fds_bits, i)) {
+                       printk("\tFD: %02d, ", i);
+                       if (files->fd[i].fd_file) {
+                               printk("File: %p, File name: %s\n", files->fd[i].fd_file,
+                                      file_name(files->fd[i].fd_file));
+                       } else {
+                               assert(files->fd[i].fd_chan);
+                               print_chaninfo(files->fd[i].fd_chan);
+                       }
                }
+       }
        spin_unlock(&files->lock);
-       print_9ns_files(p);
        printk("Children: (PID (struct proc *))\n");
        TAILQ_FOREACH(child, &p->children, sibling_link)
                printk("\t%d (%p)\n", child->pid, child);
index 327d5ad..1954b94 100644 (file)
@@ -2292,6 +2292,7 @@ done:
        return retval;
 }
 
+/* Careful: if an FD is busy, we don't close the old object, it just fails */
 static intreg_t sys_dup_fds_to(struct proc *p, unsigned int pid,
                                struct childfdmap *map, unsigned int nentries)
 {
index 03e8798..666c008 100644 (file)
@@ -2705,11 +2705,10 @@ void clone_fdt(struct fd_table *src, struct fd_table *dst)
                        SET_BITMASK_BIT(dst->open_fds->fds_bits, i);
                        dst->fd[i].fd_file = file;
                        dst->fd[i].fd_chan = chan;
-                       /* no file means 9ns is using it, they clone separately (TODO) */
                        if (file)
                                kref_get(&file->f_kref, 1);
-               //      else
-               //              chan_incref(chan);
+                       else
+                               chan_incref(chan);
                        if (i >= dst->next_fd)
                                dst->next_fd = i + 1;
                }