kfs_run and friends use the FS and s/kfs/bin/
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 23 Jul 2010 18:41:06 +0000 (11:41 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:49 +0000 (17:35 -0700)
The monitor functions will ls and run programs out of the bin directory,
however you get one of those.  For KFS, make a bin/ directory in
whatever folder you pull from for your initramfs (e.g. kern/kfs) and put
your binaries in there.

kern/include/monitor.h
kern/include/vfs.h
kern/src/kfs.c
kern/src/monitor.c
kern/src/vfs.c

index a8e15b0..a0b925e 100644 (file)
@@ -19,8 +19,8 @@ int mon_showmapping(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_setmapperm(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_cpuinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_nanwan(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-int mon_kfs_ls(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-int mon_kfs_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_bin_ls(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_bin_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_kfs_cat(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_manager(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_procinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
index 5abbe97..9102abf 100644 (file)
@@ -425,8 +425,10 @@ extern struct kmem_cache *file_kcache;
 /* Misc VFS functions */
 void vfs_init(void);
 void qstr_builder(struct dentry *dentry, char *l_name);
+char *file_name(struct file *file);
 int path_lookup(char *path, int flags, struct nameidata *nd);
 void path_release(struct nameidata *nd);
+struct file *path_to_file(char *path);
 
 /* Superblock functions */
 struct super_block *get_sb(void);
index 1bae7a0..9776421 100644 (file)
@@ -637,8 +637,13 @@ int kfs_flush(struct file *file)
 /* Called when the file refcnt == 0 */
 int kfs_release(struct inode *inode, struct file *file)
 {
+       TAILQ_REMOVE(&inode->i_sb->s_files, file, f_list);
+       /* TODO: (REF) need to dealloc when this hits 0, atomic/concurrent/etc */
+       atomic_dec(&inode->i_refcnt);
+       /* TODO: clean up the inode if it was the last and we don't want it around
+        */
        kmem_cache_free(file_kcache, file);
-       return -1;
+       return 0;
 }
 
 /* Flushes the file's dirty contents to disc */
index d0a9ef8..28898fc 100644 (file)
@@ -25,6 +25,7 @@
 #include <kdebug.h>
 #include <syscall.h>
 #include <kmalloc.h>
+#include <elf.h>
 
 #include <ros/timer.h>
 #include <ros/memlayout.h>
@@ -48,8 +49,8 @@ static command_t (RO commands)[] = {
        { "cpuinfo", "Prints CPU diagnostics", mon_cpuinfo},
        { "ps", "Prints process list", mon_ps},
        { "nanwan", "Meet Nanwan!!", mon_nanwan},
-       { "kfs_ls", "List files in KFS", mon_kfs_ls},
-       { "kfs_run", "Create and run a program from KFS", mon_kfs_run},
+       { "bin_ls", "List files in /bin", mon_bin_ls},
+       { "bin_run", "Create and run a program from /bin", mon_bin_run},
        { "kfs_cat", "Dumps text from a file from KFS", mon_kfs_cat},
        { "manager", "Run the manager", mon_manager},
        { "procinfo", "Show information about processes", mon_procinfo},
@@ -251,36 +252,63 @@ int mon_nanwan(int argc, char **argv, trapframe_t *tf)
        return 0;
 }
 
-int mon_kfs_ls(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
+int mon_bin_ls(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
 {
-       printk("Files in KFS:\n-------------------------------\n");
-       for (int i = 0; i < MAX_KFS_FILES; i++)
-               if (kfs[i].name[0])
-                       printk("%s\n", kfs[i].name);
+       struct dirent dir = {0};
+       struct file *bin_dir;
+       int retval = 0;
+
+       bin_dir = path_to_file("/bin");
+       if (!bin_dir) {
+               printk("No /bin directory!\n");
+               return 1;
+       }
+       printk("Files in KFS /bin:\n-------------------------------\n");
+       do {
+               retval = bin_dir->f_op->readdir(bin_dir, &dir); 
+               printk("%s\n", dir.d_name);
+               dir.d_off++;
+       } while (retval == 1);
+       /* TODO: (REF) need to dealloc when this hits 0, atomic/concurrent/etc */
+       atomic_dec(&bin_dir->f_refcnt);
+       assert(!bin_dir->f_refcnt);
+       bin_dir->f_op->release(bin_dir->f_inode, bin_dir);
        return 0;
 }
 
-int mon_kfs_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
+int mon_bin_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
 {
        if (argc != 2) {
                printk("Usage: kfs_run FILENAME\n");
                return 1;
        }
-       int kfs_inode = kfs_lookup_path(argv[1]);
-       if (kfs_inode < 0) {
-               printk("Bad filename!\n");
+       struct file *program;
+       int retval = 0;
+       char buf[6 + MAX_FILENAME_SZ] = "/bin/";        /* /bin/ + max + \0 */
+       strncpy(buf + 5, argv[1], MAX_FILENAME_SZ);
+       program = path_to_file(buf);
+       if (!program) {
+               printk("No such program!\n");
                return 1;
        }
-       struct proc *p = kfs_proc_create(kfs_inode);
-       // go from PROC_CREATED->PROC_RUNNABLE_S
-       spin_lock(&p->proc_lock); // might not be necessary for a mon function
+       /* TODO: push this into proc_create */
+       struct proc *p = proc_create(NULL, 0);
+       char* p_argv[] = {0, 0, 0};
+       char* p_envp[] = {"LD_LIBRARY_PATH=/lib",0};
+       p_argv[0] = file_name(program);
+       procinfo_pack_args(p->procinfo, p_argv, p_envp);
+       assert(load_elf(p, program) == 0);
+
+       spin_lock(&p->proc_lock);
        __proc_set_state(p, PROC_RUNNABLE_S);
        schedule_proc(p);
        spin_unlock(&p->proc_lock);
-       proc_decref(p, 1); // let go of the reference created in proc_create()
-       // 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
+       proc_decref(p, 1); /* let go of the reference created in proc_create() */
+       /* TODO: (REF) need to dealloc when this hits 0, atomic/concurrent/etc */
+       atomic_dec(&program->f_refcnt);
+       /* 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 */
        schedule();
        return 0;
 }
index 39ae86c..3e4c01a 100644 (file)
@@ -125,6 +125,12 @@ void qstr_builder(struct dentry *dentry, char *l_name)
        dentry->d_name.len = strnlen(dentry->d_name.name, MAX_FILENAME_SZ);
 }
 
+/* Useful little helper - return the string ptr for a given file */
+char *file_name(struct file *file)
+{
+       return (char*)TAILQ_FIRST(&file->f_inode->i_dentry)->d_name.name;
+}
+
 /* Some issues with this, coupled closely to fs_lookup.  This assumes that
  * negative dentries are not returned (might differ from linux) */
 static struct dentry *do_lookup(struct dentry *parent, char *name)
@@ -302,6 +308,28 @@ void path_release(struct nameidata *nd)
        atomic_dec(&nd->mnt->mnt_refcnt);
 }
 
+/* Seems convenient: Given a path, return the appropriate file.  The reference
+ * returned is refcounted (which is done by open()). */
+struct file *path_to_file(char *path)
+{
+       struct file *f = 0;
+       struct nameidata nd = {0};
+       if (path_lookup(path, 0, &nd))
+               return 0;
+       f = kmem_cache_alloc(file_kcache, 0);
+       if (!f) {
+               path_release(&nd);
+               return 0;
+       }
+       if (nd.dentry->d_inode->i_fop->open(nd.dentry->d_inode, f)) {
+               path_release(&nd);
+               kmem_cache_free(file_kcache, f);
+               return 0;
+       }
+       path_release(&nd);
+       return f;
+}
+
 /* Superblock functions */
 
 /* Helper to alloc and initialize a generic superblock.  This handles all the