growfd() grows enough for the desired fd
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 10 Sep 2014 21:54:15 +0000 (14:54 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 10 Sep 2014 21:58:57 +0000 (14:58 -0700)
Removing the hacky while loop, too.

This was bugging out if we asked for an FD > nfd + delta.  The
allocation wasn't big enough, and we'd fail.  9ns opens would fail if
there were too many VFS opens between 9ns opens (the VFS and 9ns share
an FD pool).

kern/src/ns/sysfile.c

index b901e04..14db385 100644 (file)
@@ -31,10 +31,14 @@ static int growfd(struct fgrp *f, int fd)
        if (fd < f->nfd) {
                return 0;
        }
-       n = f->nfd + DELTAFD;
+       /* want to grow by a reasonable amount (delta), but also make sure we can
+        * handle the fd we're asked for */
+       n = MAX(f->nfd, fd + 1) + DELTAFD;
        if (n > MAXNFD)
                n = MAXNFD;
        if (fd >= n) {
+               set_errno(EMFILE);
+               set_errstr("Asked for FD %d, more than %d\n", fd, MAXNFD);
                return -1;
        }
        nfd = kzmalloc(n * sizeof(struct chan *), 0);
@@ -64,27 +68,20 @@ int newfd(struct chan *c)
        /* 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);
-       while (i >= f->nfd) {
-               if (growfd(f, i) < 0) {
-                       spin_unlock(&f->lock);
-                       exhausted("file descriptors");
-                       return -1;
-               }
-               cpu_relax();
-       }
-       assert(f->fd[i] == 0);
-#if 0  // 9ns style
+#else  // 9ns style
        /* TODO: use a unique integer allocator */
        for (i = f->minfd; i < f->nfd; i++)
                if (f->fd[i] == 0)
                        break;
-       if (i >= f->nfd && growfd(f, i) < 0) {
+#endif
+       if (growfd(f, i) < 0) {
                spin_unlock(&f->lock);
                exhausted("file descriptors");
                return -1;
        }
-#endif
+       assert(f->fd[i] == 0);
        f->minfd = i + 1;
        if (i > f->maxfd)
                f->maxfd = i;