File <-> file descriptor management
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 20 Jul 2010 02:16:51 +0000 (19:16 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:49 +0000 (17:35 -0700)
mmap() now works with file descriptors.  Of course, you the process to
open a file first, which you have to do manually...

kern/include/vfs.h
kern/src/mm.c
kern/src/vfs.c

index 93e8524..a7fee23 100644 (file)
@@ -437,4 +437,9 @@ int pm_insert_page(struct page_map *pm, unsigned long index, struct page *page);
 int pm_remove_page(struct page_map *pm, struct page *page);
 int file_load_page(struct file *file, unsigned long index, struct page **pp);
 
+/* Process-related File management functions */
+struct file *get_file_from_fd(struct files_struct *open_files, int fd);
+struct file *put_file_from_fd(struct files_struct *open_files, int file_desc);
+int insert_file(struct files_struct *open_files, struct file *file);
+
 #endif /* ROS_KERN_VFS_H */
index c0dac97..eb55cc7 100644 (file)
@@ -272,11 +272,6 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
        struct file *file = NULL;
        printd("mmap(addr %x, len %x, prot %x, flags %x, fd %x, off %x)\n", addr,
               len, prot, flags, fd, offset);
-       if (fd >= 0 && (flags & MAP_SHARED)) {
-               printk("[kernel] mmap() for files requires !MAP_SHARED.\n");
-               set_errno(current_tf, EACCES);
-               return MAP_FAILED;
-       }
        if (fd >= 0 && (flags & MAP_ANON)) {
                set_errno(current_tf, EBADF);
                return MAP_FAILED;
@@ -290,7 +285,7 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                return MAP_FAILED;
        }
        if (fd != -1) {
-               file = file_open_from_fd(p, fd);
+               file = get_file_from_fd(&p->open_files, fd);
                if (!file) {
                        set_errno(current_tf, EBADF);
                        return MAP_FAILED;
index 308407f..ffe9854 100644 (file)
@@ -456,3 +456,73 @@ int file_load_page(struct file *file, unsigned long index, struct page **pp)
        assert(page->pg_flags & PG_UPTODATE);
        return 0;
 }
+
+/* Process-related File management functions */
+
+/* Given any FD, get the appropriate file, 0 o/w */
+struct file *get_file_from_fd(struct files_struct *open_files, int file_desc)
+{
+       struct file *retval = 0;
+       spin_lock(&open_files->lock);
+       if (file_desc < open_files->max_fdset) {
+               if (GET_BITMASK_BIT(open_files->open_fds->fds_bits, 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];
+                       assert(retval);
+                       atomic_inc(&retval->f_refcnt);
+               }
+       }
+       spin_unlock(&open_files->lock);
+       return retval;
+}
+
+/* Remove FD from the open files, if it was there, and return f.  Currently,
+ * this decref's f, so the return value is not consumable or even usable.  This
+ * hasn't been thought through yet. */
+struct file *put_file_from_fd(struct files_struct *open_files, int file_desc)
+{
+       struct file *f = 0;
+       spin_lock(&open_files->lock);
+       if (file_desc < open_files->max_fdset) {
+               if (GET_BITMASK_BIT(open_files->open_fds->fds_bits, 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);
+                       f = open_files->fd[file_desc];
+                       open_files->fd[file_desc] = 0;
+                       /* TODO: (REF) need to make sure we free if we hit 0 (might do this
+                        * in the caller */
+                       if (f)
+                               atomic_dec(&f->f_refcnt);
+                       // if 0, drop, decref from higher, sync, whatever
+               }
+       }
+       spin_unlock(&open_files->lock);
+       return f;
+}
+
+/* Inserts the file in the files_struct, returning the corresponding new file
+ * descriptor, or an error code.  We currently grab the first open FD. */
+int insert_file(struct files_struct *open_files, struct file *file)
+{
+       int slot = -1;
+       spin_lock(&open_files->lock);
+       for (int i = 0; i < open_files->max_fdset; i++) {
+               if (GET_BITMASK_BIT(open_files->open_fds->fds_bits, i))
+                       continue;
+               slot = i;
+               SET_BITMASK_BIT(open_files->open_fds->fds_bits, slot);
+               assert(slot < open_files->max_files && open_files->fd[slot] == 0);
+               open_files->fd[slot] = file;
+               atomic_inc(&file->f_refcnt);
+               if (slot >= open_files->next_fd)
+                       open_files->next_fd = slot + 1;
+               break;
+       }
+       if (slot == -1) /* should expand the FD array and fd_set */
+               warn("Ran out of file descriptors, deal with me!");
+       spin_unlock(&open_files->lock);
+       return slot;
+}