Applies FD flags per file desc, not per file
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 5 Oct 2010 23:49:18 +0000 (16:49 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:55 +0000 (17:35 -0700)
Was causing stderr messages to be ignored for programs spawned by
busybox.  (O_CLOEXEC on a duped FD of stderr before forking).

kern/include/vfs.h
kern/src/process.c
kern/src/syscall.c
kern/src/vfs.c

index 6b16ead..235ec9c 100644 (file)
@@ -354,16 +354,23 @@ struct small_fd_set {
     uint8_t fds_bits[BYTES_FOR_BITMASK(NR_FILE_DESC_DEFAULT)];
 };
 
+/* Describes an open file.  We need this, since the FD flags are supposed to be
+ * per file descriptor, not per file (like the file status flags). */
+struct file_desc {
+       struct file                                     *fd_file;
+       unsigned int                            fd_flags;
+};
+
 /* All open files for a process */
 struct files_struct {
        spinlock_t                                      lock;
        int                                                     max_files;              /* max files ptd to by fd */
        int                                                     max_fdset;              /* max of the current fd_set */
        int                                                     next_fd;                /* next number available */
-       struct file                                     **fd;                   /* initially pts to fd_array */
+       struct file_desc                        *fd;                    /* initially pts to fd_array */
        struct fd_set                           *open_fds;              /* init, pts to open_fds_init */
        struct small_fd_set                     open_fds_init;
-       struct file                                     *fd_array[NR_OPEN_FILES_DEFAULT];
+       struct file_desc                        fd_array[NR_OPEN_FILES_DEFAULT];
 };
 
 /* Process specific filesysten info */
index 998f45f..8240be7 100644 (file)
@@ -1530,9 +1530,10 @@ void print_proc_info(pid_t pid)
        struct files_struct *files = &p->open_files;
        spin_lock(&files->lock);
        for (int i = 0; i < files->max_files; i++)
-               if (files->fd_array[i]) {
+               if (files->fd_array[i].fd_file) {
                        printk("\tFD: %02d, File: %08p, File name: %s\n", i,
-                              files->fd_array[i], file_name(files->fd_array[i]));
+                              files->fd_array[i].fd_file,
+                              file_name(files->fd_array[i].fd_file));
                }
        spin_unlock(&files->lock);
        /* No one cares, and it clutters the terminal */
index a4f596f..97165e7 100644 (file)
@@ -920,10 +920,7 @@ intreg_t sys_fcntl(struct proc *p, int fd, int cmd, int arg)
                        }
                        break;
                case (F_GETFD):
-                       /* GET and SETFD just care about CLOEXEC.  We don't have a separate
-                        * flag variable for the FD (we might need to, technically). */
-                       if (file->f_flags & O_CLOEXEC)
-                               retval = FD_CLOEXEC;
+                       retval = p->open_files.fd[fd].fd_flags;
                        break;
                case (F_SETFD):
                        if (arg == FD_CLOEXEC)
index eff652d..2fb22c8 100644 (file)
@@ -1715,7 +1715,7 @@ struct file *get_file_from_fd(struct files_struct *open_files, int file_desc)
                        /* while max_files and max_fdset might not line up, we should never
                         * have a valid fdset higher than files */
                        assert(file_desc < open_files->max_files);
-                       retval = open_files->fd[file_desc];
+                       retval = open_files->fd[file_desc].fd_file;
                        assert(retval);
                        kref_get(&retval->f_kref, 1);
                }
@@ -1738,8 +1738,8 @@ struct file *put_file_from_fd(struct files_struct *open_files, int file_desc)
                        /* while max_files and max_fdset might not line up, we should never
                         * have a valid fdset higher than files */
                        assert(file_desc < open_files->max_files);
-                       file = open_files->fd[file_desc];
-                       open_files->fd[file_desc] = 0;
+                       file = open_files->fd[file_desc].fd_file;
+                       open_files->fd[file_desc].fd_file = 0;
                        assert(file);
                        kref_put(&file->f_kref);
                        CLR_BITMASK_BIT(open_files->open_fds->fds_bits, file_desc);
@@ -1762,9 +1762,11 @@ int insert_file(struct files_struct *open_files, struct file *file, int low_fd)
                        continue;
                slot = i;
                SET_BITMASK_BIT(open_files->open_fds->fds_bits, slot);
-               assert(slot < open_files->max_files && open_files->fd[slot] == 0);
+               assert(slot < open_files->max_files &&
+                      open_files->fd[slot].fd_file == 0);
                kref_get(&file->f_kref, 1);
-               open_files->fd[slot] = file;
+               open_files->fd[slot].fd_file = file;
+               open_files->fd[slot].fd_flags = 0;
                if (slot >= open_files->next_fd)
                        open_files->next_fd = slot + 1;
                break;
@@ -1786,11 +1788,11 @@ void close_all_files(struct files_struct *open_files, bool cloexec)
                        /* while max_files and max_fdset might not line up, we should never
                         * have a valid fdset higher than files */
                        assert(i < open_files->max_files);
-                       file = open_files->fd[i];
-                       if (cloexec && !(file->f_flags & O_CLOEXEC))
+                       file = open_files->fd[i].fd_file;
+                       if (cloexec && !(open_files->fd[i].fd_flags & O_CLOEXEC))
                                continue;
                        /* Actually close the file */
-                       open_files->fd[i] = 0;
+                       open_files->fd[i].fd_file = 0;
                        assert(file);
                        kref_put(&file->f_kref);
                        CLR_BITMASK_BIT(open_files->open_fds->fds_bits, i);
@@ -1810,10 +1812,10 @@ void clone_files(struct files_struct *src, struct files_struct *dst)
                        /* while max_files and max_fdset might not line up, we should never
                         * have a valid fdset higher than files */
                        assert(i < src->max_files);
-                       file = src->fd[i];
-                       assert(i < dst->max_files && dst->fd[i] == 0);
+                       file = src->fd[i].fd_file;
+                       assert(i < dst->max_files && dst->fd[i].fd_file == 0);
                        SET_BITMASK_BIT(dst->open_fds->fds_bits, i);
-                       dst->fd[i] = file;
+                       dst->fd[i].fd_file = file;
                        assert(file);
                        kref_get(&file->f_kref, 1);
                        if (i >= dst->next_fd)