mm: Use struct file_or_chan for VMR files
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 28 Feb 2018 21:52:00 +0000 (16:52 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 6 Apr 2018 19:23:01 +0000 (15:23 -0400)
As they say, all problems in CS can be solved with a layer of indirection.
The file_or_chan struct hides the details of whether or not we're talking
to a file or a chan.  This will ease the transition from the VFS to 9ns.

The chan stuff isn't implemented yet - that'll require a few more changes.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
17 files changed:
kern/drivers/dev/proc.c
kern/include/elf.h
kern/include/linux_compat.h
kern/include/mm.h
kern/include/process.h
kern/include/profiler.h
kern/include/vfs.h
kern/src/elf.c
kern/src/kdebug.c
kern/src/ktest/pb_ktests.c
kern/src/mm.c
kern/src/monitor.c
kern/src/pagemap.c
kern/src/process.c
kern/src/profiler.c
kern/src/syscall.c
kern/src/vfs.c

index 702f0de..a494314 100644 (file)
@@ -412,9 +412,9 @@ static void build_maps_cb(struct vm_region *vmr, void *arg)
        char *path;
        unsigned long inode_nr;
 
-       if (vmr->vm_file) {
-               path = file_abs_path(vmr->vm_file, path_buf, sizeof(path_buf));
-               inode_nr = vmr->vm_file->f_dentry->d_inode->i_ino;
+       if (vmr_has_file(vmr)) {
+               path = foc_abs_path(vmr->__vm_foc, path_buf, sizeof(path_buf));
+               inode_nr = 0; /* TODO: do we care about this? */
        } else {
                strlcpy(path_buf, "[heap]", sizeof(path_buf));
                path = path_buf;
@@ -429,8 +429,8 @@ static void build_maps_cb(struct vm_region *vmr, void *arg)
                               vmr->vm_prot & PROT_WRITE   ? 'w' : '-',
                               vmr->vm_prot & PROT_EXEC    ? 'x' : '-',
                               vmr->vm_flags & MAP_PRIVATE ? 'p' : 's',
-                              vmr->vm_file ? vmr->vm_foff : 0,
-                              vmr->vm_file ? 1 : 0,    /* VFS == 1 for major */
+                              vmr_has_file(vmr) ? vmr->vm_foff : 0,
+                              vmr_has_file(vmr) ? 1 : 0,       /* VFS == 1 for major */
                               0,
                               inode_nr);
        /* Align the filename to the 74th char, like Linux (73 chars so far) */
index ed0515c..01b8aa1 100644 (file)
@@ -146,9 +146,9 @@ typedef long elf_aux_t[2];
 // Hardware capabilities (for use with ELF_AUX_HWCAP)
 #define ELF_HWCAP_SPARC_FLUSH  1
 
-struct file;
-bool is_valid_elf(struct file *f);
-int load_elf(struct proc* p, struct file* f,
+struct file_or_chan;
+bool is_valid_elf(struct file_or_chan *f);
+int load_elf(struct proc *p, struct file_or_chan *f,
              int argc, char *argv[], int envc, char *envp[]);
 ssize_t get_startup_argc(struct proc *p);
 char *get_startup_argv(struct proc *p, size_t idx, char *argp,
index f8c5067..781915c 100644 (file)
@@ -869,14 +869,14 @@ static inline int request_firmware(const struct firmware **fwp,
                                                                   struct device *ignored)
 {
        struct firmware *ret_fw;
-       struct file *fw_file;
+       struct file_or_chan *fw_file;
        void *fw_data;
        char dirname[] = "/lib/firmware/";
        /* could dynamically allocate the min of this and some MAX */
        char fullpath[sizeof(dirname) + strlen(file_name) + 1];
 
        snprintf(fullpath, sizeof(fullpath), "%s%s", dirname, file_name);
-       fw_file = do_file_open(fullpath, O_READ, 0);
+       fw_file = foc_open(fullpath, O_READ, 0);
        if (!fw_file) {
                printk("Unable to find firmware file %s!\n", fullpath);
                return -1;
@@ -884,14 +884,14 @@ static inline int request_firmware(const struct firmware **fwp,
        fw_data = kread_whole_file(fw_file);
        if (!fw_data) {
                printk("Unable to load firmware file %s!\n", fullpath);
-               kref_put(&fw_file->f_kref);
+               foc_decref(fw_file);
                return -1;
        }
        ret_fw = kmalloc(sizeof(struct firmware), MEM_WAIT);
        ret_fw->data = fw_data;
-       ret_fw->size = fw_file->f_dentry->d_inode->i_size;
+       ret_fw->size = foc_get_len(fw_file);
        *fwp = ret_fw;
-       kref_put(&fw_file->f_kref);
+       foc_decref(fw_file);
        return 0;
 }
 
index 2a9813d..ccb2119 100644 (file)
 #include <atomic.h>
 #include <sys/queue.h>
 #include <slab.h>
+#include <kref.h>
 
 struct file;
+struct chan;
+struct fd_table;
 struct proc;                                                           /* preprocessor games */
 
+#define F_OR_C_NONE 0
+#define F_OR_C_FILE 1
+#define F_OR_C_CHAN 2
+
+struct file_or_chan {
+       int type;
+       struct file *file;
+       struct chan *chan;
+       struct kref kref;
+};
+
+char *foc_to_name(struct file_or_chan *foc);
+char *foc_abs_path(struct file_or_chan *foc, char *path, size_t max_size);
+ssize_t foc_read(struct file_or_chan *foc, void *buf, size_t amt, off64_t off);
+struct file_or_chan *foc_open(char *path, int omode, int perm);
+struct file_or_chan *fd_to_foc(struct fd_table *fdt, int fd);
+void foc_incref(struct file_or_chan *foc);
+void foc_decref(struct file_or_chan *foc);
+void *foc_pointer(struct file_or_chan *foc);
+size_t foc_get_len(struct file_or_chan *foc);
+
 /* Basic structure defining a region of a process's virtual memory.  Note we
  * don't refcnt these.  Either they are in the TAILQ/tree, or they should be
  * freed.  There should be no other references floating around.  We still need
@@ -29,11 +53,22 @@ struct vm_region {
        uintptr_t                                       vm_end;
        int                                                     vm_prot;
        int                                                     vm_flags;
-       struct file                                     *vm_file;
+       struct file_or_chan                     *__vm_foc;
        size_t                                          vm_foff;
 };
 TAILQ_HEAD(vmr_tailq, vm_region);                      /* Declares 'struct vmr_tailq' */
 
+static inline bool vmr_has_file(struct vm_region *vmr)
+{
+       return vmr->__vm_foc ? true : false;
+}
+
+static inline char *vmr_to_filename(struct vm_region *vmr)
+{
+       assert(vmr_has_file(vmr));
+       return foc_to_name(vmr->__vm_foc);
+}
+
 /* VM Region Management Functions.  For now, these just maintain themselves -
  * anything related to mapping needs to be done by the caller. */
 void vmr_init(void);
@@ -62,7 +97,7 @@ void enumerate_vmrs(struct proc *p,
 void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
            int fd, size_t offset);
 void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
-              struct file *f, size_t offset);
+              struct file_or_chan *foc, size_t offset);
 int mprotect(struct proc *p, uintptr_t addr, size_t len, int prot);
 int munmap(struct proc *p, uintptr_t addr, size_t len);
 int handle_page_fault(struct proc *p, uintptr_t va, int prot);
index bae8b7b..74948f7 100644 (file)
@@ -90,7 +90,7 @@ void proc_init_procdata(struct proc* p);
 struct proc *pid_nth(unsigned int n);
 error_t proc_alloc(struct proc **pp, struct proc *parent, int flags);
 void __proc_ready(struct proc *p);
-struct proc *proc_create(struct file *prog, char **argv, char **envp);
+struct proc *proc_create(struct file_or_chan *prog, char **argv, char **envp);
 int __proc_set_state(struct proc *p, uint32_t state);
 struct proc *pid2proc(pid_t pid);
 bool proc_controls(struct proc *actor, struct proc *target);
index 8a40c62..012214e 100644 (file)
@@ -10,7 +10,7 @@
 
 struct hw_trapframe;
 struct proc;
-struct file;
+struct file_or_chan;
 struct cmdbuf;
 
 int profiler_configure(struct cmdbuf *cb);
@@ -28,5 +28,5 @@ void profiler_trace_data_flush(void);
 int profiler_size(void);
 int profiler_read(void *va, int n);
 void profiler_notify_mmap(struct proc *p, uintptr_t addr, size_t size, int prot,
-                                                 int flags, struct file *f, size_t offset);
+                                                 int flags, struct file_or_chan *foc, size_t offset);
 void profiler_notify_new_process(struct proc *p);
index 6b877f9..3a457d4 100644 (file)
@@ -500,8 +500,8 @@ int do_rename(char *old_path, char *new_path);
 int do_truncate(struct inode *inode, off64_t len);
 struct file *dentry_open(struct dentry *dentry, int flags);
 void file_release(struct kref *kref);
-ssize_t kread_file(struct file *file, void *buf, size_t sz);
-void *kread_whole_file(struct file *file);
+ssize_t kread_file(struct file_or_chan *file, void *buf, size_t sz);
+void *kread_whole_file(struct file_or_chan *file);
 
 /* Process-related File management functions */
 void *lookup_fd(struct fd_table *fdt, int fd, bool incref, bool vfs);
index a287bb3..89408ba 100644 (file)
 
 /* Check if the file is valid elf file (i.e. by checking for ELF_MAGIC in the
  * header) */
-bool is_valid_elf(struct file *f)
+bool is_valid_elf(struct file_or_chan *foc)
 {
        elf64_t h;
-       off64_t o = 0;
        uintptr_t c = switch_to_ktask();
 
-       if (f->f_op->read(f, (char*)&h, sizeof(elf64_t), &o) != sizeof(elf64_t)) {
+       if (foc_read(foc, (char*)&h, sizeof(elf64_t), 0) != sizeof(elf64_t))
                goto fail;
-       }
        if (h.e_magic != ELF_MAGIC) {
                goto fail;
        }
@@ -134,8 +132,8 @@ static uintptr_t populate_stack(struct proc *p, int argc, char *argv[],
 /* We need the writable flag for ld.  Even though the elf header says it wants
  * RX (and not W) for its main program header, it will page fault (eip 56f0,
  * 46f0 after being relocated to 0x1000, va 0x20f4). */
-static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
-                        elf_info_t *ei, bool writable)
+static int load_one_elf(struct proc *p, struct file_or_chan *foc,
+                        uintptr_t pg_num, elf_info_t *ei, bool writable)
 {
        int ret = -1;
        ei->phdr = -1;
@@ -153,7 +151,7 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
        elf64_t elfhdr_storage;
        elf32_t* elfhdr32 = (elf32_t*)&elfhdr_storage;
        elf64_t* elfhdr64 = &elfhdr_storage;
-       if (f->f_op->read(f, (char*)elfhdr64, sizeof(elf64_t), &f_off)
+       if (foc_read(foc, (char*)elfhdr64, sizeof(elf64_t), f_off)
                != sizeof(elf64_t)) {
                /* if you ever debug this, be sure to 0 out elfhrd_storage in advance */
                printk("[kernel] load_one_elf: failed to read file\n");
@@ -195,7 +193,7 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
        }
        phdrs = kmalloc(e_phnum * phsz, 0);
        f_off = e_phoff;
-       if (!phdrs || f->f_op->read(f, phdrs, e_phnum * phsz, &f_off) !=
+       if (!phdrs || foc_read(foc, phdrs, e_phnum * phsz, f_off) !=
                      e_phnum * phsz) {
                printk("[kernel] load_one_elf: could not get program headers\n");
                goto fail;
@@ -223,7 +221,7 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
                else if (p_type == ELF_PROG_INTERP) {
                        f_off = p_offset;
                        ssize_t maxlen = sizeof(ei->interp);
-                       ssize_t bytes = f->f_op->read(f, ei->interp, maxlen, &f_off);
+                       ssize_t bytes = foc_read(foc, ei->interp, maxlen, f_off);
                        /* trying to catch errors.  don't know how big it could be, but it
                         * should be at least 0. */
                        if (bytes <= 0) {
@@ -276,7 +274,7 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
                                if (filesz - partial) {
                                        /* Map the complete pages. */
                                        if (do_mmap(p, memstart, filesz - partial, mm_perms,
-                                                   mm_flags, f, filestart) == MAP_FAILED) {
+                                                   mm_flags, foc, filestart) == MAP_FAILED) {
                                                printk("[kernel] load_one_elf: complete mmap failed\n");
                                                goto fail;
                                        }
@@ -294,7 +292,8 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
                                        /* Map the final partial page. */
                                        uintptr_t last_page = memstart + filesz - partial;
                                        if (do_mmap(p, last_page, PGSIZE, mm_perms, mm_flags,
-                                                   f, filestart + filesz - partial) == MAP_FAILED) {
+                                                   foc, filestart + filesz - partial)
+                                               == MAP_FAILED) {
                                                printk("[kernel] load_one_elf: partial mmap failed\n");
                                                goto fail;
                                        }
@@ -336,7 +335,7 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
                uintptr_t filestart = ROUNDDOWN(e_phoff, PGSIZE);
                uintptr_t filesz = e_phoff + (e_phnum * phsz) - filestart;
                void *phdr_addr = do_mmap(p, 0, filesz, PROT_READ | PROT_WRITE,
-                                         MAP_PRIVATE, f, filestart);
+                                         MAP_PRIVATE, foc, filestart);
                if (phdr_addr == MAP_FAILED) {
                        printk("[kernel] load_one_elf: prog header mmap failed\n");
                        goto fail;
@@ -355,15 +354,15 @@ fail:
        return ret;
 }
 
-int load_elf(struct proc* p, struct file* f,
+int load_elf(struct proc *p, struct file_or_chan *foc,
              int argc, char *argv[], int envc, char *envp[])
 {
        elf_info_t ei, interp_ei;
-       if (load_one_elf(p, f, 0, &ei, FALSE))
+       if (load_one_elf(p, foc, 0, &ei, FALSE))
                return -1;
 
        if (ei.dynamic) {
-               struct file *interp = do_file_open(ei.interp, O_READ, 0);
+               struct file_or_chan *interp = foc_open(ei.interp, O_READ, 0);
                if (!interp)
                        return -1;
                /* Load dynamic linker at 1M. Obvious MIB joke avoided.
@@ -374,7 +373,7 @@ int load_elf(struct proc* p, struct file* f,
                 * explicit. */
                int error = load_one_elf(p, interp, MMAP_LD_FIXED_VA >> PGSHIFT,
                                         &interp_ei, TRUE);
-               kref_put(&interp->f_kref);
+               foc_decref(interp);
                if (error)
                        return -1;
        }
index 6381147..787de72 100644 (file)
@@ -179,12 +179,12 @@ void debug_addr_proc(struct proc *p, unsigned long addr)
                printk("Addr %p has no VMR\n", addr);
                return;
        }
-       if (!vmr->vm_file) {
+       if (!vmr_has_file(vmr)) {
                spin_unlock(&p->vmr_lock);
                printk("Addr %p's VMR has no file\n", addr);
                return;
        }
-       printk("Addr %p is in %s at offset %p\n", addr, file_name(vmr->vm_file),
+       printk("Addr %p is in %s at offset %p\n", addr, vmr_to_filename(vmr),
               addr - vmr->vm_base + vmr->vm_foff);
        spin_unlock(&p->vmr_lock);
 }
index 640a575..2841e4c 100644 (file)
@@ -924,8 +924,9 @@ bool test_ucq(void)
        set_awaiter_rel(waiter, 1000000);       /* 1s should be long enough */
        set_alarm(tchain, waiter);
        /* Just spawn the program */
-       struct file *program;
-       program = do_file_open("/bin/ucq", O_READ, 0);
+       struct file_or_chan *program;
+
+       program = foc_open("/bin/ucq", O_READ, 0);
 
        KT_ASSERT_M("We should be able to find /bin/ucq",
                    program);
@@ -935,7 +936,7 @@ bool test_ucq(void)
        /* instead of getting rid of the reference created in proc_create, we'll put
         * it in the awaiter */
        waiter->data = p;
-       kref_put(&program->f_kref);
+       foc_decref(program);
        /* Should never return from schedule (env_pop in there) also note you may
         * not get the process you created, in the event there are others floating
         * around that are runnable */
@@ -1071,7 +1072,9 @@ bool test_vm_regions(void)
        for (int i = 0; i < 3; i++) {
                vmrs[i]->vm_prot = PROT_READ;
                vmrs[i]->vm_flags = 0;
-               vmrs[i]->vm_file = 0; /* would like to test this, it's a pain for now */
+               /* would like to test this, it's a pain for now */
+               if (vmr_has_file(vmrs[i]))
+                       vmrs[i]->__vm_foc->type = 0;
        }
        vmrs[0] = merge_me(vmrs[1]);
        results[0].base = 0x2000;
index ee0ae43..dd964d7 100644 (file)
@@ -37,10 +37,159 @@ static int populate_pm_va(struct proc *p, uintptr_t va, unsigned long nr_pgs,
                           int pte_prot, struct page_map *pm, size_t offset,
                           int flags, bool exec);
 
-/* minor helper, will ease the file->chan transition */
-static struct page_map *file2pm(struct file *file)
+static struct page_map *foc_to_pm(struct file_or_chan *foc)
 {
-       return file->f_mapping;
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               return foc->file->f_mapping;
+       case F_OR_C_CHAN:
+               return NULL; /* TODO: (chan) hook to fs_file mapping */
+       }
+       panic("unknown F_OR_C type");
+}
+
+static struct page_map *vmr_to_pm(struct vm_region *vmr)
+{
+       return foc_to_pm(vmr->__vm_foc);
+}
+
+char *foc_to_name(struct file_or_chan *foc)
+{
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               return foc->file->f_dentry->d_name.name;
+       case F_OR_C_CHAN:
+               return NULL;    /* TODO: (chan) */
+       }
+       panic("unknown F_OR_C type");
+}
+
+char *foc_abs_path(struct file_or_chan *foc, char *path, size_t max_size)
+{
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               return file_abs_path(foc->file, path, max_size);
+       case F_OR_C_CHAN:
+               return NULL;    /* TODO: (chan) */
+       }
+       panic("unknown F_OR_C type");
+}
+
+ssize_t foc_read(struct file_or_chan *foc, void *buf, size_t amt, off64_t off)
+{
+       off64_t fake_off = off;
+
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               return foc->file->f_op->read(foc->file, buf, amt, &fake_off);
+       case F_OR_C_CHAN:
+               return -1;      /* TODO: (chan) */
+       }
+       panic("unknown F_OR_C type");
+}
+
+static void foc_release(struct kref *kref)
+{
+       struct file_or_chan *foc = container_of(kref, struct file_or_chan, kref);
+
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               kref_put(&foc->file->f_kref);
+               break;
+       case F_OR_C_CHAN:
+               /* TODO: (chan) */
+               break;
+       default:
+               panic("unknown F_OR_C type, %d", foc->type);
+       }
+       kfree(foc);
+}
+
+static struct file_or_chan *foc_alloc(void)
+{
+       struct file_or_chan *foc;
+
+       foc = kzmalloc(sizeof(struct file_or_chan), MEM_ATOMIC);
+       if (!foc)
+               return NULL;
+       kref_init(&foc->kref, foc_release, 1);
+       return foc;
+}
+
+struct file_or_chan *foc_open(char *path, int omode, int perm)
+{
+       struct file_or_chan *foc = foc_alloc();
+
+       if (!foc)
+               return NULL;
+       foc->type = F_OR_C_FILE;
+       foc->file = do_file_open(path, omode, perm);
+       if (!foc->file) {
+               kfree(foc);
+               foc = NULL;
+       }
+       return foc;
+}
+
+struct file_or_chan *fd_to_foc(struct fd_table *fdt, int fd)
+{
+       struct file_or_chan *foc = foc_alloc();
+
+       if (!foc)
+               return NULL;
+       foc->type = F_OR_C_FILE;
+       foc->file = get_file_from_fd(fdt, fd);
+       if (!foc->file) {
+               kfree(foc);
+               foc = NULL;
+       }
+       return foc;
+}
+
+void foc_incref(struct file_or_chan *foc)
+{
+       kref_get(&foc->kref, 1);
+}
+
+void foc_decref(struct file_or_chan *foc)
+{
+       kref_put(&foc->kref);
+}
+
+void *foc_pointer(struct file_or_chan *foc)
+{
+       if (!foc)
+               return NULL;
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               return foc->file;
+       case F_OR_C_CHAN:
+               return foc->chan;
+       default:
+               panic("unknown F_OR_C type, %d", foc->type);
+       }
+}
+
+size_t foc_get_len(struct file_or_chan *foc)
+{
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               return foc->file->f_dentry->d_inode->i_size;
+       case F_OR_C_CHAN:
+               return 0;       /* TODO: (chan) */
+       }
+       panic("unknown F_OR_C type, %d", foc->type);
+}
+
+int foc_dev_mmap(struct file_or_chan *foc, struct vm_region *vmr)
+{
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               return foc->file->f_op->mmap(foc->file, vmr);
+       case F_OR_C_CHAN:
+               return -1;      /* TODO: (chan) */
+       }
+       panic("unknown F_OR_C type, %d", foc->type);
 }
 
 void vmr_init(void)
@@ -129,14 +278,14 @@ struct vm_region *split_vmr(struct vm_region *old_vmr, uintptr_t va)
        old_vmr->vm_end = va;
        new_vmr->vm_prot = old_vmr->vm_prot;
        new_vmr->vm_flags = old_vmr->vm_flags;
-       if (old_vmr->vm_file) {
-               kref_get(&old_vmr->vm_file->f_kref, 1);
-               new_vmr->vm_file = old_vmr->vm_file;
+       if (vmr_has_file(old_vmr)) {
+               foc_incref(old_vmr->__vm_foc);
+               new_vmr->__vm_foc = old_vmr->__vm_foc;
                new_vmr->vm_foff = old_vmr->vm_foff +
                                      old_vmr->vm_end - old_vmr->vm_base;
-               pm_add_vmr(file2pm(old_vmr->vm_file), new_vmr);
+               pm_add_vmr(vmr_to_pm(old_vmr), new_vmr);
        } else {
-               new_vmr->vm_file = 0;
+               new_vmr->__vm_foc = NULL;
                new_vmr->vm_foff = 0;
        }
        return new_vmr;
@@ -150,10 +299,10 @@ int merge_vmr(struct vm_region *first, struct vm_region *second)
        if ((first->vm_end != second->vm_base) ||
            (first->vm_prot != second->vm_prot) ||
            (first->vm_flags != second->vm_flags) ||
-           (first->vm_file != second->vm_file))
+           (first->__vm_foc != second->__vm_foc))
                return -1;
-       if ((first->vm_file) && (second->vm_foff != first->vm_foff +
-                                first->vm_end - first->vm_base))
+       if (vmr_has_file(first) && (second->vm_foff != first->vm_foff +
+                                   first->vm_end - first->vm_base))
                return -1;
        first->vm_end = second->vm_end;
        destroy_vmr(second);
@@ -207,9 +356,9 @@ int shrink_vmr(struct vm_region *vmr, uintptr_t va)
  * out the page table entries. */
 void destroy_vmr(struct vm_region *vmr)
 {
-       if (vmr->vm_file) {
-               pm_remove_vmr(file2pm(vmr->vm_file), vmr);
-               kref_put(&vmr->vm_file->f_kref);
+       if (vmr_has_file(vmr)) {
+               pm_remove_vmr(vmr_to_pm(vmr), vmr);
+               foc_decref(vmr->__vm_foc);
        }
        TAILQ_REMOVE(&vmr->vm_proc->vm_regions, vmr, vm_link);
        kmem_cache_free(vmr_kcache, vmr);
@@ -326,7 +475,7 @@ static int fill_vmr(struct proc *p, struct proc *new_p, struct vm_region *vmr)
 {
        int ret = 0;
 
-       if ((!vmr->vm_file) || (vmr->vm_flags & MAP_PRIVATE)) {
+       if (!vmr_has_file(vmr) || (vmr->vm_flags & MAP_PRIVATE)) {
                /* We don't support ANON + SHARED yet */
                assert(!(vmr->vm_flags & MAP_SHARED));
                ret = copy_pages(p, new_p, vmr->vm_base, vmr->vm_end);
@@ -335,15 +484,15 @@ static int fill_vmr(struct proc *p, struct proc *new_p, struct vm_region *vmr)
                 * (but we might be able to ignore MAP_POPULATE). */
                if (vmr->vm_flags & MAP_LOCKED) {
                        /* need to keep the file alive in case we unlock/block */
-                       kref_get(&vmr->vm_file->f_kref, 1);
+                       foc_incref(vmr->__vm_foc);
                        /* math is a bit nasty if vm_base isn't page aligned */
                        assert(!PGOFF(vmr->vm_base));
                        ret = populate_pm_va(new_p, vmr->vm_base,
                                             (vmr->vm_end - vmr->vm_base) >> PGSHIFT,
-                                            vmr->vm_prot, vmr->vm_file->f_mapping,
+                                            vmr->vm_prot, vmr_to_pm(vmr),
                                             vmr->vm_foff, vmr->vm_flags,
                                             vmr->vm_prot & PROT_EXEC);
-                       kref_put(&vmr->vm_file->f_kref);
+                       foc_decref(vmr->__vm_foc);
                }
        }
        return ret;
@@ -373,17 +522,17 @@ int duplicate_vmrs(struct proc *p, struct proc *new_p)
                vmr->vm_end = vm_i->vm_end;
                vmr->vm_prot = vm_i->vm_prot;
                vmr->vm_flags = vm_i->vm_flags;
-               vmr->vm_file = vm_i->vm_file;
+               vmr->__vm_foc = vm_i->__vm_foc;
                vmr->vm_foff = vm_i->vm_foff;
-               if (vm_i->vm_file) {
-                       kref_get(&vm_i->vm_file->f_kref, 1);
-                       pm_add_vmr(file2pm(vm_i->vm_file), vmr);
+               if (vmr_has_file(vm_i)) {
+                       foc_incref(vm_i->__vm_foc);
+                       pm_add_vmr(vmr_to_pm(vm_i), vmr);
                }
                ret = fill_vmr(p, new_p, vmr);
                if (ret) {
-                       if (vm_i->vm_file) {
-                               pm_remove_vmr(file2pm(vm_i->vm_file), vmr);
-                               kref_put(&vm_i->vm_file->f_kref);
+                       if (vmr_has_file(vm_i)) {
+                               pm_remove_vmr(vmr_to_pm(vm_i), vmr);
+                               foc_decref(vm_i->__vm_foc);
                        }
                        kmem_cache_free(vmr_kcache, vm_i);
                        return ret;
@@ -407,7 +556,7 @@ void print_vmrs(struct proc *p)
        TAILQ_FOREACH(vmr, &p->vm_regions, vm_link)
                printk("%02d: (%p - %p): 0x%08x, 0x%08x, %p, %p\n", count++,
                       vmr->vm_base, vmr->vm_end, vmr->vm_prot, vmr->vm_flags,
-                      vmr->vm_file, vmr->vm_foff);
+                      foc_pointer(vmr->__vm_foc), vmr->vm_foff);
 }
 
 void enumerate_vmrs(struct proc *p,
@@ -441,7 +590,7 @@ static bool mmap_flags_priv_ok(int flags)
 void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
            int fd, size_t offset)
 {
-       struct file *file = NULL;
+       struct file_or_chan *file = NULL;
        void *result;
 
        offset <<= PGSHIFT;
@@ -456,7 +605,7 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                return MAP_FAILED;
        }
        if (!(flags & MAP_ANON) && (fd >= 0)) {
-               file = get_file_from_fd(&p->open_files, fd);
+               file = fd_to_foc(&p->open_files, fd);
                if (!file) {
                        set_errno(EBADF);
                        result = MAP_FAILED;
@@ -492,7 +641,7 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
        result = do_mmap(p, addr, len, prot, flags, file, offset);
 out_ref:
        if (file)
-               kref_put(&file->f_kref);
+               foc_decref(file);
        return result;
 }
 
@@ -519,6 +668,24 @@ out_error: /* for debugging */
        return false;
 }
 
+static bool check_chan_perms(struct vm_region *vmr, struct chan *chan, int prot)
+{
+       /* TODO: (chan) */
+       return true;
+}
+
+static bool check_foc_perms(struct vm_region *vmr, struct file_or_chan *foc,
+                            int prot)
+{
+       switch (foc->type) {
+       case F_OR_C_FILE:
+               return check_file_perms(vmr, foc->file, prot);
+       case F_OR_C_CHAN:
+               return check_chan_perms(vmr, foc->chan, prot);
+       }
+       panic("unknown F_OR_C type");
+}
+
 /* Helper, maps in page at addr, but only if nothing is mapped there.  Returns
  * 0 on success.  Will take ownership of non-pagemap pages, including on error
  * cases.  This just means we free it on error, and notionally store it in the
@@ -645,7 +812,7 @@ static int populate_pm_va(struct proc *p, uintptr_t va, unsigned long nr_pgs,
 }
 
 void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
-              struct file *file, size_t offset)
+              struct file_or_chan *file, size_t offset)
 {
        len = ROUNDUP(len, PGSIZE);
        struct vm_region *vmr, *vmr_temp;
@@ -686,8 +853,8 @@ void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
        vmr->vm_flags = flags & MAP_PERSIST_FLAGS;
        vmr->vm_foff = offset;
        if (file) {
-               if (!check_file_perms(vmr, file, prot)) {
-                       assert(!vmr->vm_file);
+               if (!check_foc_perms(vmr, file, prot)) {
+                       assert(!vmr->__vm_foc);
                        destroy_vmr(vmr);
                        set_errno(EACCES);
                        spin_unlock(&p->vmr_lock);
@@ -695,7 +862,7 @@ void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                }
                /* TODO: consider locking the file while checking (not as manadatory as
                 * in handle_page_fault() */
-               if (nr_pages(offset + len) > nr_pages(file->f_dentry->d_inode->i_size)) {
+               if (nr_pages(offset + len) > nr_pages(foc_get_len(file))) {
                        /* We're allowing them to set up the VMR, though if they attempt to
                         * fault in any pages beyond the file's limit, they'll fail.  Since
                         * they might not access the region, we need to make sure POPULATE
@@ -707,17 +874,17 @@ void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                /* Prep the FS to make sure it can mmap the file.  Slightly weird
                 * semantics: if we fail and had munmapped the space, they will have a
                 * hole in their VM now. */
-               if (file->f_op->mmap(file, vmr)) {
-                       assert(!vmr->vm_file);
+               if (foc_dev_mmap(file, vmr)) {
+                       assert(!vmr->__vm_foc);
                        destroy_vmr(vmr);
                        set_errno(EACCES);      /* not quite */
                        spin_unlock(&p->vmr_lock);
                        return MAP_FAILED;
                }
-               kref_get(&file->f_kref, 1);
-               pm_add_vmr(file2pm(file), vmr);
+               foc_incref(file);
+               pm_add_vmr(foc_to_pm(file), vmr);
        }
-       vmr->vm_file = file;
+       vmr->__vm_foc = file;
        vmr = merge_me(vmr);            /* attempts to merge with neighbors */
 
        if (flags & MAP_POPULATE && prot != PROT_NONE) {
@@ -730,7 +897,7 @@ void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                } else {
                        /* Note: this will unlock if it blocks.  our refcnt on the file
                         * keeps the pm alive when we unlock */
-                       ret = populate_pm_va(p, addr, nr_pgs, pte_prot, file->f_mapping,
+                       ret = populate_pm_va(p, addr, nr_pgs, pte_prot, foc_to_pm(file),
                                             offset, flags, prot & PROT_EXEC);
                }
                if (ret == -ENOMEM) {
@@ -791,7 +958,7 @@ int __do_mprotect(struct proc *p, uintptr_t addr, size_t len, int prot)
        while (vmr && vmr->vm_base < addr + len) {
                if (vmr->vm_prot == prot)
                        goto next_vmr;
-               if (vmr->vm_file && !check_file_perms(vmr, vmr->vm_file, prot)) {
+               if (vmr_has_file(vmr) && !check_foc_perms(vmr, vmr->__vm_foc, prot)) {
                        file_access_failure = TRUE;
                        goto next_vmr;
                }
@@ -1001,6 +1168,7 @@ static int __hpf_load_page(struct proc *p, struct page_map *pm,
 static int __hpf(struct proc *p, uintptr_t va, int prot, bool file_ok)
 {
        struct vm_region *vmr;
+       struct file_or_chan *file;
        struct page *a_page;
        unsigned int f_idx;     /* index of the missing page in the file */
        int ret = 0;
@@ -1021,7 +1189,7 @@ refault:
                ret = -EPERM;
                goto out;
        }
-       if (!vmr->vm_file) {
+       if (!vmr_has_file(vmr)) {
                /* No file - just want anonymous memory */
                if (upage_alloc(p, &a_page, TRUE)) {
                        ret = -ENOMEM;
@@ -1032,12 +1200,13 @@ refault:
                        ret = -EACCES;
                        goto out;
                }
+               file = vmr->__vm_foc;
                /* If this fails, either something got screwed up with the VMR, or the
                 * permissions changed after mmap/mprotect.  Either way, I want to know
                 * (though it's not critical). */
-               if (!check_file_perms(vmr, vmr->vm_file, prot))
+               if (!check_foc_perms(vmr, file, prot))
                        printk("[kernel] possible issue with VMR prots on file %s!\n",
-                              file_name(vmr->vm_file));
+                              foc_to_name(file));
                /* Load the file's page in the page cache.
                 * TODO: (BLK) Note, we are holding the mem lock!  We need to rewrite
                 * this stuff so we aren't hold the lock as excessively as we are, and
@@ -1047,23 +1216,23 @@ refault:
                /* TODO: need some sort of lock on the file to deal with someone
                 * concurrently shrinking it.  Adding 1 to f_idx, since it is
                 * zero-indexed */
-               if (f_idx + 1 > nr_pages(vmr->vm_file->f_dentry->d_inode->i_size)) {
+               if (f_idx + 1 > nr_pages(foc_get_len(file))) {
                        /* We're asking for pages that don't exist in the file */
                        /* TODO: unlock the file */
                        ret = -ESPIPE; /* linux sends a SIGBUS at access time */
                        goto out;
                }
-               ret = pm_load_page_nowait(vmr->vm_file->f_mapping, f_idx, &a_page);
+               ret = pm_load_page_nowait(foc_to_pm(file), f_idx, &a_page);
                if (ret) {
                        if (ret != -EAGAIN)
                                goto out;
                        /* keep the file alive after we unlock */
-                       kref_get(&vmr->vm_file->f_kref, 1);
+                       foc_incref(file);
                        spin_unlock(&p->vmr_lock);
-                       ret = __hpf_load_page(p, vmr->vm_file->f_mapping, f_idx, &a_page,
+                       ret = __hpf_load_page(p, foc_to_pm(file), f_idx, &a_page,
                                              first);
                        first = FALSE;
-                       kref_put(&vmr->vm_file->f_kref);
+                       foc_decref(file);
                        if (ret)
                                return ret;
                        goto refault;
@@ -1115,6 +1284,7 @@ int handle_page_fault_nofile(struct proc *p, uintptr_t va, int prot)
 unsigned long populate_va(struct proc *p, uintptr_t va, unsigned long nr_pgs)
 {
        struct vm_region *vmr, vmr_copy;
+       struct file_or_chan *file;
        unsigned long nr_pgs_this_vmr;
        unsigned long nr_filled = 0;
        struct page *page;
@@ -1134,22 +1304,23 @@ unsigned long populate_va(struct proc *p, uintptr_t va, unsigned long nr_pgs)
                pte_prot = (vmr->vm_prot & PROT_WRITE) ? PTE_USER_RW :
                           (vmr->vm_prot & (PROT_READ|PROT_EXEC)) ? PTE_USER_RO : 0;
                nr_pgs_this_vmr = MIN(nr_pgs, (vmr->vm_end - va) >> PGSHIFT);
-               if (!vmr->vm_file) {
+               if (!vmr_has_file(vmr)) {
                        if (populate_anon_va(p, va, nr_pgs_this_vmr, pte_prot)) {
                                /* on any error, we can just bail.  we might be underestimating
                                 * nr_filled. */
                                break;
                        }
                } else {
+                       file = vmr->__vm_foc;
                        /* need to keep the file alive in case we unlock/block */
-                       kref_get(&vmr->vm_file->f_kref, 1);
+                       foc_incref(file);
                        /* Regarding foff + (va - base): va - base < len, and foff + len
                         * does not over flow */
                        ret = populate_pm_va(p, va, nr_pgs_this_vmr, pte_prot,
-                                            vmr->vm_file->f_mapping,
+                                            foc_to_pm(file),
                                             vmr->vm_foff + (va - vmr->vm_base),
                                             vmr->vm_flags, vmr->vm_prot & PROT_EXEC);
-                       kref_put(&vmr->vm_file->f_kref);
+                       foc_decref(file);
                        if (ret) {
                                /* we might have failed if the underlying file doesn't cover the
                                 * mmap window, depending on how we'll deal with truncation. */
index 11980b3..1d87344 100644 (file)
@@ -309,7 +309,7 @@ int mon_bin_run(int argc, char **argv, struct hw_trapframe *hw_tf)
                printk("Usage: bin_run FILENAME\n");
                return 1;
        }
-       struct file *program;
+       struct file_or_chan *program;
        int retval = 0;
        char buf[5 + MAX_FILENAME_SZ + 1] = "/bin/";    /* /bin/ + max + \0 */
 
@@ -318,7 +318,7 @@ int mon_bin_run(int argc, char **argv, struct hw_trapframe *hw_tf)
                printk("Filename '%s' too long!\n", argv[1]);
                return 1;
        }
-       program = do_file_open(buf, O_READ, 0);
+       program = foc_open(buf, O_READ, 0);
        if (!program) {
                printk("No such program!\n");
                return 1;
@@ -336,7 +336,7 @@ int mon_bin_run(int argc, char **argv, struct hw_trapframe *hw_tf)
        kfree(p_argv);
        proc_wakeup(p);
        proc_decref(p); /* let go of the reference created in proc_create() */
-       kref_put(&program->f_kref);
+       foc_decref(program);
        /* Make a scheduling decision.  You might not get the process you created,
         * in the event there are others floating around that are runnable */
        run_scheduler();
index bda2f02..46b0f03 100644 (file)
@@ -618,7 +618,8 @@ void print_page_map_info(struct page_map *pm)
        TAILQ_FOREACH(vmr_i, &pm->pm_vmrs, vm_pm_link) {
                printk("\tVMR proc %d: (%p - %p): 0x%08x, 0x%08x, %p, %p\n",
                       vmr_i->vm_proc->pid, vmr_i->vm_base, vmr_i->vm_end,
-                      vmr_i->vm_prot, vmr_i->vm_flags, vmr_i->vm_file, vmr_i->vm_foff);
+                      vmr_i->vm_prot, vmr_i->vm_flags, foc_pointer(vmr_i->__vm_foc),
+                          vmr_i->vm_foff);
        }
        spin_unlock(&pm->pm_lock);
 }
index f63b19a..fd2d646 100644 (file)
@@ -474,7 +474,7 @@ void __proc_ready(struct proc *p)
 }
 
 /* Creates a process from the specified file, argvs, and envps. */
-struct proc *proc_create(struct file *prog, char **argv, char **envp)
+struct proc *proc_create(struct file_or_chan *prog, char **argv, char **envp)
 {
        struct proc *p;
        error_t r;
index c94caed..9967d76 100644 (file)
@@ -261,7 +261,7 @@ static void profiler_emit_current_system_status(void)
                struct proc *p = (struct proc *) opaque;
 
                profiler_notify_mmap(p, vmr->vm_base, vmr->vm_end - vmr->vm_base,
-                                    vmr->vm_prot, vmr->vm_flags, vmr->vm_file,
+                                    vmr->vm_prot, vmr->vm_flags, vmr->__vm_foc,
                                     vmr->vm_foff);
        }
 
@@ -532,12 +532,12 @@ int profiler_read(void *va, int n)
 }
 
 void profiler_notify_mmap(struct proc *p, uintptr_t addr, size_t size, int prot,
-                          int flags, struct file *f, size_t offset)
+                          int flags, struct file_or_chan *foc, size_t offset)
 {
        if (kref_get_not_zero(&profiler_kref, 1)) {
-               if (f && (prot & PROT_EXEC) && profiler_percpu_ctx) {
+               if (foc && (prot & PROT_EXEC) && profiler_percpu_ctx) {
                        char path_buf[PROFILER_MAX_PRG_PATH];
-                       char *path = file_abs_path(f, path_buf, sizeof(path_buf));
+                       char *path = foc_abs_path(foc, path_buf, sizeof(path_buf));
 
                        if (likely(path))
                                profiler_push_pid_mmap(p, addr, size, offset, path);
index aa3df90..9a75919 100644 (file)
@@ -708,7 +708,7 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
 {
        int pid = 0;
        char *t_path;
-       struct file *program;
+       struct file_or_chan *program;
        struct proc *new_p;
        int argc, envc;
        char **argv, **envp;
@@ -717,8 +717,7 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
        t_path = copy_in_path(p, path, path_l);
        if (!t_path)
                return -1;
-       /* TODO: 9ns support */
-       program = do_file_open(t_path, O_READ, 0);
+       program = foc_open(t_path, O_READ, 0);
        if (!program)
                goto error_with_path;
        if (!is_valid_elf(program)) {
@@ -762,7 +761,7 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
        /* progname is argv0, which accounts for symlinks */
        proc_set_progname(new_p, argc ? argv[0] : NULL);
        proc_replace_binary_path(new_p, t_path);
-       kref_put(&program->f_kref);
+       foc_decref(program);
        user_memdup_free(p, kargenv);
        __proc_ready(new_p);
        pid = new_p->pid;
@@ -778,7 +777,7 @@ error_with_proc:
 error_with_kargenv:
        user_memdup_free(p, kargenv);
 error_with_file:
-       kref_put(&program->f_kref);
+       foc_decref(program);
 error_with_path:
        free_path(p, t_path);
        return -1;
@@ -982,7 +981,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
 {
        int ret = -1;
        char *t_path = NULL;
-       struct file *program;
+       struct file_or_chan *program;
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        int argc, envc;
        char **argv, **envp;
@@ -1033,8 +1032,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
                return -1;
        }
        /* This could block: */
-       /* TODO: 9ns support */
-       program = do_file_open(t_path, O_READ, 0);
+       program = foc_open(t_path, O_READ, 0);
        /* Clear the current_ctx.  We won't be returning the 'normal' way.  Even if
         * we want to return with an error, we need to go back differently in case
         * we succeed.  This needs to be done before we could possibly block, but
@@ -1062,7 +1060,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
        close_fdt(&p->open_files, TRUE);
        env_user_mem_free(p, 0, UMAPTOP);
        if (load_elf(p, program, argc, argv, envc, envp)) {
-               kref_put(&program->f_kref);
+               foc_decref(program);
                user_memdup_free(p, kargenv);
                systrace_finish_trace(pcpui->cur_kthread, -1);
                /* Note this is an inedible reference, but proc_destroy now returns */
@@ -1071,8 +1069,8 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
                 * return to the user (hence the all_out) */
                goto all_out;
        }
-       printd("[PID %d] exec %s\n", p->pid, file_name(program));
-       kref_put(&program->f_kref);
+       printd("[PID %d] exec %s\n", p->pid, foc_to_name(program));
+       foc_decref(program);
        systrace_finish_trace(pcpui->cur_kthread, 0);
        goto success;
        /* These error and out paths are so we can handle the async interface, both
@@ -1081,7 +1079,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
 mid_error:
        /* These two error paths are for when we want to restart the process with an
         * error value (errno is already set). */
-       kref_put(&program->f_kref);
+       foc_decref(program);
 early_error:
        /* Note the t_path is passed to proc_replace_binary_path for success */
        free_path(p, t_path);
index e7f9d3f..6fe67c9 100644 (file)
@@ -2342,12 +2342,12 @@ void file_release(struct kref *kref)
        kmem_cache_free(file_kcache, file);
 }
 
-ssize_t kread_file(struct file *file, void *buf, size_t sz)
+ssize_t kread_file(struct file_or_chan *file, void *buf, size_t sz)
 {
        /* TODO: (KFOP) (VFS kernel read/writes need to be from a ktask) */
        uintptr_t old_ret = switch_to_ktask();
        off64_t dummy = 0;
-       ssize_t cpy_amt = file->f_op->read(file, buf, sz, &dummy);
+       ssize_t cpy_amt = foc_read(file, buf, sz, dummy);
 
        switch_back_from_ktask(old_ret);
        return cpy_amt;
@@ -2355,23 +2355,23 @@ ssize_t kread_file(struct file *file, void *buf, size_t sz)
 
 /* Reads the contents of an entire file into a buffer, returning that buffer.
  * On error, prints something useful and returns 0 */
-void *kread_whole_file(struct file *file)
+void *kread_whole_file(struct file_or_chan *file)
 {
        size_t size;
        void *contents;
        ssize_t cpy_amt;
 
-       size = file->f_dentry->d_inode->i_size;
+       size = foc_get_len(file);
        contents = kmalloc(size, MEM_WAIT);
        cpy_amt = kread_file(file, contents, size);
        if (cpy_amt < 0) {
-               printk("Error %d reading file %s\n", get_errno(), file_name(file));
+               printk("Error %d reading file %s\n", get_errno(), foc_to_name(file));
                kfree(contents);
                return 0;
        }
        if (cpy_amt != size) {
                printk("Read %d, needed %d for file %s\n", cpy_amt, size,
-                      file_name(file));
+                      foc_to_name(file));
                kfree(contents);
                return 0;
        }