Files are represented with struct file
authorAndrew Waterman <waterman@ros-dev.(none)>
Sat, 27 Mar 2010 00:52:26 +0000 (17:52 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:38 +0000 (17:35 -0700)
Right now, struct file pretty much just wraps an appserver fd,
but this provides enough abstraction so that the future
demand-paging stuff doesn't look so ghetto.

(Additionally, sys_exec now takes an fd, rather than a string.)

kern/include/elf.h
kern/include/frontend.h
kern/include/mm.h
kern/include/syscall.h
kern/src/elf.c
kern/src/frontend.c
kern/src/manager.c
kern/src/mm.c
kern/src/syscall.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/execve.c

index 56f95c1..8fb320a 100644 (file)
@@ -81,6 +81,7 @@ typedef long elf_aux_t[2];
 #define ELF_AUX_PHNUM          5
 #define ELF_AUX_ENTRY          9
 
-int load_elf(struct proc* p, const char* fn);
+struct file;
+int load_elf(struct proc* p, struct file* f);
 
 #endif /* !ROS_INC_ELF_H */
index ee24588..9e5ed4d 100644 (file)
@@ -8,6 +8,13 @@
 #include <env.h>
 #include <process.h>
 
+// for now, this is where struct file lives
+struct file {
+       int fd; // all it contains is an appserver fd (for pid 0, aka kernel)
+       int refcnt;
+       spinlock_t lock;
+};
+
 // Default APPSERVER_ETH_TYPE if not defined externally
 #ifndef APPSERVER_ETH_TYPE
 #define APPSERVER_ETH_TYPE 0x8888
@@ -31,9 +38,11 @@ char* user_strdup_errno(struct proc* p, const char* va, int max);
 int memcpy_to_user_errno(struct proc* p, void* dst, const void* src, int len);
 void* kmalloc_errno(int len);
 
-error_t read_page(struct proc* p, int fd, physaddr_t pa, int pgoff);
-error_t open_file(struct proc* p, const char* path, int oflag, int mode);
-error_t close_file(struct proc* p, int fd);
+error_t file_read_page(struct file* f, physaddr_t pa, size_t pgoff);
+struct file* file_open(const char* path, int oflag, int mode);
+struct file* file_open_from_fd(struct proc* p, int fd);
+void file_incref(struct file* f);
+void file_decref(struct file* f);
 
 #endif
 
@@ -57,6 +66,7 @@ error_t close_file(struct proc* p, int fd);
 #define APPSERVER_SYSCALL_dup          41
 #define APPSERVER_SYSCALL_umask        60
 #define APPSERVER_SYSCALL_fcntl        62
+#define APPSERVER_SYSCALL_kdup         87
 #define APPSERVER_SYSCALL_lstat        88
 #define APPSERVER_SYSCALL_tcgetattr    89
 #define APPSERVER_SYSCALL_tcsetattr    90
index 4043a19..7b557f9 100644 (file)
@@ -72,14 +72,12 @@ struct mm {
 // would rather this be a mm struct
 void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
            int fd, size_t offset);
+struct file;
+void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
+             struct file* f, size_t offset);
 int mprotect(struct proc* p, void* addr, size_t len, int prot);
 int munmap(struct proc* p, void* addr, size_t len);
 
-// not sure where to put this (asw)
-error_t open_file(struct proc* p, const char* fn, int flag, int mode);
-error_t close_file(struct proc* p, int fd);
-error_t read_page(struct proc* p, int fd, physaddr_t pa, int pgoff);
-
 int handle_page_fault(struct proc* p, uintptr_t va, int prot);
 
 #endif // !ROS_KERN_MM_H
index 565543e..ce9f494 100644 (file)
@@ -38,5 +38,5 @@ intreg_t sys_getcwd(struct proc* p, char* pwd, int size);
 intreg_t sys_gettimeofday(struct proc* p, int* buf);
 intreg_t sys_tcsetattr(struct proc* p, int fd, int optional_actions, const void* termios_p);
 intreg_t sys_tcgetattr(struct proc* p, int fd, void* termios_p);
-intreg_t sys_exec(struct proc* p, const char fn[MAX_PATH_LEN], procinfo_t* pi);
+intreg_t sys_exec(struct proc* p, int fd, procinfo_t* pi);
 #endif /* !ROS_KERN_SYSCALL_H */
index 991de2f..3c529b4 100644 (file)
@@ -7,7 +7,7 @@
 #include <elf.h>
 #include <pmap.h>
 
-struct elf_info
+typedef struct
 {
        long entry;
        long highest_addr;
@@ -15,9 +15,10 @@ struct elf_info
        int phnum;
        int dynamic;
        char interp[256];
-};
+} elf_info_t;
 
-int load_one_elf(struct proc* p, int fd, int pgoffset, struct elf_info* ei)
+static int
+load_one_elf(struct proc* p, struct file* f, int pgoffset, elf_info_t* ei)
 {
        int ret = -1;
        ei->phdr = -1;
@@ -25,7 +26,7 @@ int load_one_elf(struct proc* p, int fd, int pgoffset, struct elf_info* ei)
        ei->highest_addr = 0;
 
        char* elf = (char*)kmalloc(PGSIZE,0);
-       if(!elf || read_page(p,fd,PADDR(elf),0) == -1)
+       if(!elf || file_read_page(f,PADDR(elf),0) == -1)
                goto fail;
 
        elf_t* elfhdr = (elf_t*)elf;
@@ -73,16 +74,16 @@ int load_one_elf(struct proc* p, int fd, int pgoffset, struct elf_info* ei)
                        // mmap will zero the rest of the page if filesz % PGSIZE != 0
                        if(filesz)
                                // TODO: waterman, figure out proper permissions
-                               if(mmap(p, memstart+pgoffset*PGSIZE, filesz,
-                                       PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED,
-                                       fd, filestart/PGSIZE) == MAP_FAILED)
+                               if(do_mmap(p, memstart+pgoffset*PGSIZE, filesz,
+                                          PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED,
+                                          f, filestart/PGSIZE) == MAP_FAILED)
                                        goto fail;
 
                        filesz = ROUNDUP(filesz,PGSIZE);
                        if(filesz < memsz)
-                               if(mmap(p, memstart+filesz+pgoffset*PGSIZE, memsz-filesz,
-                                       PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_ANON,
-                                       -1, 0) == MAP_FAILED)
+                               if(do_mmap(p, memstart+filesz+pgoffset*PGSIZE, memsz-filesz,
+                                          PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_ANON,
+                                          NULL, 0) == MAP_FAILED)
                                        goto fail;
                }
        }
@@ -96,27 +97,18 @@ fail:
        return ret;
 }
 
-int load_elf(struct proc* p, const char* fn)
+int load_elf(struct proc* p, struct file* f)
 {
-       struct elf_info ei,interp_ei;
-       int fd = open_file(p,fn,0,0);
-       if(fd == -1 || load_one_elf(p,fd,0,&ei))
+       elf_info_t ei,interp_ei;
+       if(load_one_elf(p,f,0,&ei))
                return -1;
-       close_file(p,fd);
 
        if(ei.dynamic)
        {
-               // plzplzplz let us use the stack and PADDR()
-               char* str = kmalloc(sizeof(ei.interp),0);
-               if(!str)
+               struct file* interp = file_open(ei.interp,0,0);
+               if(interp == NULL || load_one_elf(p,interp,1,&interp_ei))
                        return -1;
-               memcpy(str,ei.interp,sizeof(ei.interp));
-               int fd2 = open_file(p,str,0,0);
-               kfree(str);
-
-               if(fd2 == -1 || load_one_elf(p,fd2,1,&interp_ei))
-                       return -1;
-               close_file(p,fd2);
+               file_decref(interp);
 
                // fill in info for dynamic linker
                elf_aux_t auxp[] = {{ELF_AUX_PHDR,ei.phdr},
index 9a2bcba..d7bc5d9 100644 (file)
@@ -124,25 +124,77 @@ void* kmalloc_errno(int len)
        return kva;
 }
 
-error_t read_page(struct proc* p, int fd, physaddr_t pa, int pgoff)
+error_t file_read_page(struct file* f, physaddr_t pa, size_t pgoff)
 {
-       int ret = frontend_syscall(p ? p->pid : 0,APPSERVER_SYSCALL_pread,fd,
-                               pa,PGSIZE,pgoff*PGSIZE,NULL);
-
+       int ret = frontend_syscall(0,APPSERVER_SYSCALL_pread,f->fd,pa,PGSIZE,
+                                  pgoff*PGSIZE,NULL);
        if(ret >= 0)
                memset(KADDR(pa)+ret,0,PGSIZE-ret);
        return ret;
 }
 
-error_t open_file(struct proc* p, const char* path, int oflag, int mode)
+struct file* file_open_from_fd(struct proc* p, int fd)
+{
+       struct file* f = NULL;
+       if(!(f = kmalloc(sizeof(struct file),0)))
+               goto out;
+
+       f->fd = frontend_syscall(p->pid,APPSERVER_SYSCALL_kdup,fd,0,0,0,NULL);
+       spinlock_init(&f->lock);
+       f->refcnt = 1;
+
+out:
+       return f;
+}
+
+struct file* file_open(const char* path, int oflag, int mode)
+{
+       struct file* f = NULL;
+       // although path is a kernel pointer, it may be below KERNBASE.
+       // fix that if so.
+       char* malloced = NULL;
+       if((uintptr_t)path < KERNBASE)
+       {
+               size_t len = strlen(path)+1;
+               malloced = kmalloc(len,0);
+               if(!malloced)
+                       goto out;
+               path = memcpy(malloced,path,len);
+       }
+
+       if(!(f = kmalloc(sizeof(struct file),0)))
+               goto out;
+
+       f->fd = frontend_syscall(0,APPSERVER_SYSCALL_open,PADDR(path),
+                                oflag,mode,0,NULL);
+       spinlock_init(&f->lock);
+       f->refcnt = 1;
+
+out:
+       if(malloced)
+               kfree(malloced);
+       return f;
+}
+
+void file_incref(struct file* f)
 {
-       return frontend_syscall(p->pid,APPSERVER_SYSCALL_open,PADDR(path),
-                               oflag,mode,0,NULL);
+       spin_lock(&f->lock);
+       f->refcnt++;
+       spin_unlock(&f->lock);
 }
 
-error_t close_file(struct proc* p, int fd)
+void file_decref(struct file* f)
 {
-       return frontend_syscall(p->pid,APPSERVER_SYSCALL_close,fd,0,0,0,NULL);
+       // if you decref too many times, you'll clobber memory :(
+       spin_lock(&f->lock);
+       if(--f->refcnt == 0)
+       {
+               int ret = frontend_syscall(0,APPSERVER_SYSCALL_close,f->fd,0,0,0,NULL);
+               assert(ret == 0);
+               kfree(f);
+       }
+       else
+               spin_unlock(&f->lock);
 }
 
 int frontend_syscall_errno(struct proc* p, int n, int a0, int a1, int a2, int a3)
index cd7ce0a..1ba1c80 100644 (file)
@@ -13,6 +13,7 @@
 #include <arch/init.h>
 #include <mm.h>
 #include <elf.h>
+#include <frontend.h>
 
 #include <kmalloc.h>
 #include <assert.h>
@@ -217,7 +218,10 @@ void manager_waterman()
                procinfo_pack_args(p->env_procinfo,argv,envp);
 
                printk("loading busybox\n");
-               assert(load_elf(p,"/bin/busybox") == 0);
+               struct file* f = file_open("/bin/busybox",0,0);
+               assert(f != NULL);
+               assert(load_elf(p,f) == 0);
+               file_decref(f);
                printk("loaded busybox\n");
 
                __proc_set_state(p, PROC_RUNNABLE_S);
index eab9b5e..346e222 100644 (file)
@@ -28,6 +28,16 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                return (void*)-1;
        }
 
+       struct file* file = file_open_from_fd(p,fd);
+       if(!file)
+               return (void*)-1;
+
+       return do_mmap(p,addr,len,prot,flags,file,offset);
+}
+
+void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
+              struct file* file, size_t offset)
+{
        /* TODO: make this work, instead of a ghetto hack
         * Find a valid range, make sure it doesn't run into the kernel
         * make sure there's enough memory (not exceeding quotas)
@@ -65,7 +75,7 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                // This is just to get it correct at first
                if(!(flags & MAP_ANON))
                {
-                       if(read_page(p,fd,page2pa(a_page),offset+i) < 0)
+                       if(file_read_page(file,page2pa(a_page),offset+i) < 0)
                                goto mmap_abort;
 
                        // zero-fill end of last page
index c8f2cd0..9c86834 100644 (file)
@@ -363,18 +363,17 @@ static ssize_t sys_fork(env_t* e)
        return env->pid;
 }
 
-intreg_t sys_exec(struct proc* p, const char fn[MAX_PATH_LEN], procinfo_t* pi)
+intreg_t sys_exec(struct proc* p, int fd, procinfo_t* pi)
 {
        if(p->state != PROC_RUNNING_S)
                return -1;
 
        int ret = -1;
-       char* kfn = kmalloc(MAX_PATH_LEN,0);
-       if(kfn == NULL)
-               goto out;
-       if(memcpy_from_user(p,kfn,fn,MAX_PATH_LEN))
+       struct file* f = file_open_from_fd(p,fd);
+       if(f == NULL)
                goto out;
 
+
        if(memcpy_from_user(p,p->env_procinfo,pi,sizeof(procinfo_t)))
        {
                proc_destroy(p);
@@ -384,18 +383,18 @@ intreg_t sys_exec(struct proc* p, const char fn[MAX_PATH_LEN], procinfo_t* pi)
 
        env_segment_free(p,0,USTACKTOP);
 
-       if(load_elf(p,kfn))
+       if(load_elf(p,f))
        {
                proc_destroy(p);
                goto out;
        }
+       file_decref(f);
        *current_tf = p->env_tf;
        ret = 0;
 
-       printd("[PID %d] exec %s\n",p->pid,kfn);
+       printd("[PID %d] exec fd %d\n",p->pid,fd);
 
 out:
-       kfree(kfn);
        return ret;
 }
 
index bc167e7..c39f713 100644 (file)
@@ -24,6 +24,7 @@
 #include <fcntl.h>
 #include <elf/elf.h>
 #include <ros/procinfo.h>
+#include <assert.h>
 
 /* Replace the current process, executing PATH with arguments ARGV and
    environment ENVP.  ARGV and ENVP are terminated by NULL pointers.  */
@@ -40,13 +41,20 @@ __execve (path, argv, envp)
     return -1;
   }
 
-  char name[MAX_PATH_LEN];
-  if(strncpy(name,path,MAX_PATH_LEN) == MAX_PATH_LEN)
-  {
-    errno = ENAMETOOLONG;
-    return -1;
-  }
+  int fd = __libc_open(path,O_RDONLY);
+  if(fd == -1)
+               return -1; // errno already set by open
+
+  int ret = ros_syscall(SYS_exec,fd,(uintptr_t)&pi,0,0,0);
+
+  // if we got here, then exec better have failed...
+  assert(ret == -1);
+
+  // close the file, but keep exec's errno
+  int exec_errno = errno;
+  close(fd);
+  errno = exec_errno;
 
-  return syscall(SYS_exec,(uintptr_t)name,(uintptr_t)&pi,0,0,0);
+  return ret;
 }
 weak_alias (__execve, execve)