SYS_dup_fds_to (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 19 Aug 2014 22:14:16 +0000 (15:14 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 19 Aug 2014 22:14:16 +0000 (15:14 -0700)
Finishes Ron's sys_mapchildfds.

Reinstall your kernel headers.

kern/include/ns.h
kern/include/ros/bits/syscall.h
kern/include/ros/syscall.h
kern/src/ns/sysfile.c
kern/src/syscall.c
tests/childfdmap.c

index 2e08181..bc90edd 100644 (file)
@@ -987,6 +987,8 @@ int grpclose(struct fgrp *f, int fd);
 int sysclose(int fd);
 int syscreate(char *path, int mode, uint32_t perm);
 int sysdup(int old, int new);
 int sysclose(int fd);
 int syscreate(char *path, int mode, uint32_t perm);
 int sysdup(int old, int new);
+int sys_dup_to(struct proc *from_proc, unsigned int from_fd,
+               struct proc *to_proc, unsigned int to_fd);
 int sysfstat(int fd, uint8_t*, int n);
 int sysfstatakaros(int fd, struct kstat *);
 char *sysfd2path(int fd);
 int sysfstat(int fd, uint8_t*, int n);
 int sysfstatakaros(int fd, struct kstat *);
 char *sysfd2path(int fd);
index 699313c..2a60329 100644 (file)
@@ -72,6 +72,7 @@
 #define SYS_fwstat                             122
 #define SYS_rename                             123
 #define SYS_fchdir                             124
 #define SYS_fwstat                             122
 #define SYS_rename                             123
 #define SYS_fchdir                             124
+#define SYS_dup_fds_to                 125
 
 /* Misc syscalls */
 #define SYS_gettimeofday               140
 
 /* Misc syscalls */
 #define SYS_gettimeofday               140
index 01f3521..567f713 100644 (file)
@@ -33,9 +33,9 @@ struct syscall {
 };
 
 struct childfdmap {
 };
 
 struct childfdmap {
-       int parentfd;
-       int childfd;
-       int ok;
+       unsigned int                            parentfd;
+       unsigned int                            childfd;
+       int                                                     ok;
 };
 
 #ifndef ROS_KERNEL
 };
 
 #ifndef ROS_KERNEL
index 8641aa9..b901e04 100644 (file)
@@ -346,60 +346,52 @@ int sysdup(int old, int new)
        return fd;
 }
 
        return fd;
 }
 
-int sysdup2(struct proc *to, int old, int new)
+/* Could pass in the fgrp instead of the proc, but we need the to_proc for now
+ * so we can claim a VFS FD */
+int sys_dup_to(struct proc *from_proc, unsigned int from_fd,
+               struct proc *to_proc, unsigned int to_fd)
 {
 {
-       ERRSTACK(2);
-       int fd;
-       struct chan *c, *oc;
-       struct fgrp *fromf = current->fgrp;
-       struct fgrp *tof = to->fgrp;
+       ERRSTACK(1);
+       struct chan *c, *old_chan;
+       struct fgrp *to_fgrp = to_proc->fgrp;
 
        if (waserror()) {
                poperror();
                return -1;
        }
 
 
        if (waserror()) {
                poperror();
                return -1;
        }
 
-       c = fdtochan(current->fgrp, old, -1, 0, 1);
+       c = fdtochan(from_proc->fgrp, from_fd, -1, 0, 1);
        if (c->qid.type & QTAUTH) {
                cclose(c);
                error(Eperm);
        }
        if (c->qid.type & QTAUTH) {
                cclose(c);
                error(Eperm);
        }
-       fd = new;
-       if (fd != -1) {
-               /* ideally we'll be done with the VFS before we fix this */
-               /* double check the ccloses when you fix this */
-               panic("Need to sync with the VFS");
-               spin_lock(&tof->lock);
-               if (tof->closed) {
-                       spin_unlock(&tof->lock);
-                       cclose(c);
-                       return -1;
-               }
-               if (fd < 0 || growfd(tof, fd) < 0) {
-                       spin_unlock(&tof->lock);
-                       cclose(c);
-                       error(Ebadfd);
-               }
-               if (fd > tof->maxfd)
-                       tof->maxfd = fd;
-               oc = tof->fd[fd];
-               tof->fd[fd] = c;
-               spin_unlock(&tof->lock);
-               if (oc)
-                       cclose(oc);
-       } else {
-               panic("unhandled; rewrite newfd");
-               if (waserror()) {
-                       cclose(c);
-                       nexterror();
-               }
-               fd = newfd(c);
-               if (fd < 0)
-                       error(Enofd);
-               poperror();
+
+       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("Couldn't grow, to_fd %d", to_fd);
+       }
+       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);
+
        poperror();
        poperror();
-       return fd;
+       return 0;
 }
 
 char *sysfd2path(int fd)
 }
 
 char *sysfd2path(int fd)
index 464a5c1..ae17b0c 100644 (file)
@@ -1127,35 +1127,6 @@ static intreg_t sys_write(struct proc *p, int fd, const void *buf, int len)
        return ret;
 }
 
        return ret;
 }
 
-static intreg_t sys_mapchildfds(struct proc *p, int pid, struct childfdmap *map, int nentries)
-{
-       ssize_t ret = 0;
-       int i;
-       // TODO: validate pointer, etc.
-       struct proc *child = pid2proc(pid);
-       if (! child)
-               return -ENOENT;
-
-       for (i = 0; i < nentries; i++) {
-               int slot;
-               struct file *file = get_file_from_fd(&p->open_files, map[i].parentfd);
-               printk("Try to map parent fd %d(%p) to %d\n", map[i].parentfd, file, map[i].childfd);
-               map[i].ok = -1;
-               if (! file) {
-                       printk("sys_mapchildfds: %d is wrong\n", map[i].parentfd);
-                       continue;
-               }
-               slot = insert_file(&child->open_files, file, map[i].childfd, 1);
-               printk("%s: slot is %d\n", __func__, slot);
-               if (slot == map[i].childfd) {
-                       map[i].ok = 0;
-                       ret++;
-               }
-               kref_put(&file->f_kref);
-       }
-       return ret;
-}
-
 /* Checks args/reads in the path, opens the file, and inserts it into the
  * process's open file list. */
 static intreg_t sys_open(struct proc *p, const char *path, size_t path_l,
 /* Checks args/reads in the path, opens the file, and inserts it into the
  * process's open file list. */
 static intreg_t sys_open(struct proc *p, const char *path, size_t path_l,
@@ -2015,6 +1986,43 @@ done:
        return retval;
 }
 
        return retval;
 }
 
+static intreg_t sys_dup_fds_to(struct proc *p, unsigned int pid,
+                               struct childfdmap *map, unsigned int nentries)
+{
+       ssize_t ret = 0;
+       struct proc *child;
+       int slot;
+       struct file *file;
+
+       if (!is_user_rwaddr(map, sizeof(struct childfdmap) * nentries))
+               return -EINVAL;
+       child = pid2proc(pid);
+       if (!child)
+               return -ENOENT;
+       for (int i = 0; i < nentries; i++) {
+               map[i].ok = -1;
+               file = get_file_from_fd(&p->open_files, map[i].parentfd);
+               if (file) {
+                       slot = insert_file(&child->open_files, file, map[i].childfd, TRUE);
+                       if (slot == map[i].childfd) {
+                               map[i].ok = 0;
+                               ret++;
+                       }
+                       kref_put(&file->f_kref);
+                       continue;
+               }
+               if (!sys_dup_to(p, map[i].parentfd, child, map[i].childfd)) {
+                       map[i].ok = 0;
+                       ret++;
+                       continue;
+               }
+               /* probably a bug, could send EBADF, maybe via 'ok' */
+               printk("[kernel] dup_fds_to: couldn't find %d\n", map[i].parentfd);
+       }
+       proc_decref(child);
+       return ret;
+}
+
 /************** Syscall Invokation **************/
 
 const struct sys_table_entry syscall_table[] = {
 /************** Syscall Invokation **************/
 
 const struct sys_table_entry syscall_table[] = {
@@ -2089,7 +2097,7 @@ const struct sys_table_entry syscall_table[] = {
        [SYS_wstat] ={(syscall_t)sys_wstat, "wstat"},
        [SYS_fwstat] ={(syscall_t)sys_fwstat, "fwstat"},
        [SYS_rename] ={(syscall_t)sys_rename, "rename"},
        [SYS_wstat] ={(syscall_t)sys_wstat, "wstat"},
        [SYS_fwstat] ={(syscall_t)sys_fwstat, "fwstat"},
        [SYS_rename] ={(syscall_t)sys_rename, "rename"},
-       [65536] = {(syscall_t)sys_mapchildfds, "mapchildfds"},
+       [SYS_dup_fds_to] = {(syscall_t)sys_dup_fds_to, "dup_fds_to"},
 };
 const int max_syscall = sizeof(syscall_table)/sizeof(syscall_table[0]);
 /* Executes the given syscall.
 };
 const int max_syscall = sizeof(syscall_table)/sizeof(syscall_table[0]);
 /* Executes the given syscall.
index e692c70..6876761 100644 (file)
@@ -24,46 +24,72 @@ int main(int argc, char *argv[])
        int ret;
        int flag = 0;
        int kid;
        int ret;
        int flag = 0;
        int kid;
-       int in[2], out[2];
-       char hi[3];
-       if (pipe(in) < 0) {
-               perror("pipe");
-               exit(1);
+       int talk[2];
+       char hi[3] = {0};
+       char *child_argv[3];
+
+       /* detect the child by the number of args. */
+       if (argc > 1) {
+               read(0, hi, 3);
+               assert(!strcmp(hi, "HI"));
+               /* pass something else back */
+               hi[0] = 'Y';
+               hi[1] = 'O';
+               hi[2] = '\0';
+               write(1, hi, 3);
+               exit(0);
        }
        }
-       if (pipe(out) < 0) {
-               perror("2nd pipe");
+
+       if (pipe(talk) < 0) {
+               perror("pipe");
                exit(1);
        }
                exit(1);
        }
-       printf("pipe(in) [%d, %d]; pipe(out)[%d, %d]\n", in[0], in[1], out[0], out[1]);
-       childfdmap[0].parentfd = in[0];
-       childfdmap[0].childfd = in[1];
-       childfdmap[1].parentfd = out[0];
-       childfdmap[1].childfd = out[1];
+       printd("pipe [%d, %d]\n", talk[0], talk[1]);
+
+       /* parent will read and write on talk[0], and the child does the same for
+        * talk[1].  internally, writing to talk 0 gets read on talk 1.  the child
+        * gets talk1 mapped for both stdin (fd 0) and stdout (fd 1). */
+       childfdmap[0].parentfd = talk[1];
+       childfdmap[0].childfd = 0;
+       childfdmap[1].parentfd = talk[1];
+       childfdmap[1].childfd = 1;
 
        sprintf(filename, "/bin/%s", argv[0]);
 
        sprintf(filename, "/bin/%s", argv[0]);
-       kid = sys_proc_create(filename, strlen(filename), NULL, NULL, 0);
+       child_argv[0] = filename;
+       child_argv[1] = "1"; /* dummy arg, signal so we know they're the child */
+       child_argv[2] = 0;
+
+       kid = sys_proc_create(filename, strlen(filename), child_argv, NULL, 0);
        if (kid < 0) {
                perror("create failed");
                exit(1);
        }
 
        if (kid < 0) {
                perror("create failed");
                exit(1);
        }
 
-       ret = syscall(65536, kid, childfdmap, 2);
-       if (ret < 0) {
+       ret = syscall(SYS_dup_fds_to, kid, childfdmap, 2);
+       if (ret != 2) {
                perror("childfdmap faled");
                exit(2);
        }
 
                perror("childfdmap faled");
                exit(2);
        }
 
+       /* close the pipe endpoint that we duped in the child.  it doesn't matter
+        * for this test, but after the child exits, the pipe will still be open
+        * unless we close our side of it. */
+       close(talk[1]);
 
        sys_proc_run(kid);
 
        sys_proc_run(kid);
-       if (write(childfdmap[0].parentfd, "HI", 2) < 2) {
+
+       if (write(talk[0], "HI", 3) < 3) {
                perror("write HI");
                exit(3);
        }
 
                perror("write HI");
                exit(3);
        }
 
-       if (read(childfdmap[1].parentfd, hi, 2) < 2) {
-               perror("read HI");
+       if (read(talk[0], hi, 3) < 3) {
+               perror("read YO");
                exit(4);
        }
                exit(4);
        }
+       assert(!strcmp(hi, "YO"));
+
+       printf("Passed\n");
 
        return 0;
 }
 
        return 0;
 }