Fix bug with duping fds for plan 9 files
authorKevin Klues <klueska@cs.berkeley.edu>
Fri, 21 Mar 2014 05:53:06 +0000 (22:53 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Fri, 21 Mar 2014 06:05:37 +0000 (23:05 -0700)
I added a new claim_fd() function similar to the get_fd() and put_fd()
functions in vfs.c.  When duping plan9 fds for a new_proc via dupfgrp()
we call claim_fd() to update the new_proc's open_file list shared with
the vfs.

I also swapped the order of put_fd() and setting the fd in
src/ns/sysfile.c to avoid a potential race condition with the assert in
newfd().

kern/include/ns.h
kern/include/vfs.h
kern/src/ns/pgrp.c
kern/src/ns/sysfile.c
kern/src/vfs.c

index f988de0..0716238 100644 (file)
@@ -664,7 +664,7 @@ int domount(struct chan **, struct mhead **);
 void drawactive(int);
 void drawcmap(void);
 void dumpstack(void);
-struct fgrp *dupfgrp(struct fgrp *);
+struct fgrp *dupfgrp(struct proc *, struct fgrp *);
 void egrpcpy(struct egrp *, struct egrp *);
 int emptystr(char *unused_char_p_t);
 int eqchan(struct chan *, struct chan *, int);
index bfc55de..7d3967b 100644 (file)
@@ -493,5 +493,6 @@ extern struct dentry_operations dummy_d_op;
 
 int put_fd(struct files_struct *open_files, int file_desc);
 int get_fd(struct files_struct *open_files, int low_fd);
+int claim_fd(struct files_struct *open_files, int file_desc);
 
 #endif /* ROS_KERN_VFS_H */
index c6cc4b4..7fc8388 100644 (file)
@@ -186,7 +186,7 @@ struct fgrp *newfgrp(void)
        return new;
 }
 
-struct fgrp *dupfgrp(struct fgrp *f)
+struct fgrp *dupfgrp(struct proc *new_proc, struct fgrp *f)
 {
        int i;
        struct chan *c;
@@ -216,6 +216,7 @@ struct fgrp *dupfgrp(struct fgrp *f)
        for (i = 0; i <= f->maxfd; i++) {
                if ((c = f->fd[i])) {
                        kref_get(&c->ref, 1);
+                       claim_fd(&new_proc->open_files, i);
                        new->fd[i] = c;
                }
        }
index 13b46a8..20ea6ea 100644 (file)
@@ -428,13 +428,13 @@ int syspipe(int fd[2])
                        cclose(c[1]);
                if (fd[0] >= 0) {
                        /* VFS hack */
-                       put_fd(&current->open_files, fd[0]);
                        f->fd[fd[0]] = 0;
+                       put_fd(&current->open_files, fd[0]);
                }
                if (fd[1] >= 0) {
                        /* VFS hack */
-                       put_fd(&current->open_files, fd[1]);
                        f->fd[fd[1]] = 0;
+                       put_fd(&current->open_files, fd[1]);
                }
                poperror();
                return -1;
@@ -1421,7 +1421,7 @@ int plan9setup(struct proc *new_proc, struct proc *parent)
        }
        /* Copy semantics: do not change this without revisiting proc_destroy,
         * close_9ns_files, and closefgrp. */
-       new_proc->fgrp = dupfgrp(parent->fgrp);
+       new_proc->fgrp = dupfgrp(new_proc, parent->fgrp);
        /* Shared semantics */
        kref_get(&parent->pgrp->ref, 1);
        new_proc->pgrp = parent->pgrp;
index 94a8e42..53a2142 100644 (file)
@@ -2136,6 +2136,23 @@ int get_fd(struct files_struct *open_files, int low_fd)
        return slot;
 }
 
+/* Claims a specific FD when duping FDs. used by 9ns.  < 0 == error. */
+int claim_fd(struct files_struct *open_files, int file_desc)
+{
+       if ((file_desc < 0) || (file_desc > NR_FILE_DESC_MAX))
+               return -EINVAL;
+       if (open_files->closed)
+               return -EINVAL; /* won't matter, they are dying */
+       if (GET_BITMASK_BIT(open_files->open_fds->fds_bits, file_desc))
+               return -ENFILE; /* Should never really happen. Here to catch bugs. */
+
+       SET_BITMASK_BIT(open_files->open_fds->fds_bits, file_desc);
+       assert(file_desc < open_files->max_files && open_files->fd[0].fd_file == 0);
+       if (file_desc >= open_files->next_fd)
+               open_files->next_fd = file_desc + 1;
+       return 0;
+}
+
 /* Inserts the file in the files_struct, returning the corresponding new file
  * descriptor, or an error code.  We start looking for open fds from low_fd. */
 int insert_file(struct files_struct *open_files, struct file *file, int low_fd)