File opening revisited
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 6 Aug 2010 00:46:26 +0000 (17:46 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:50 +0000 (17:35 -0700)
Pulled all of the file opening out of KFS and into the VFS,
and converted old usages of path_to_file() to use do_file_open().

kern/include/vfs.h
kern/src/elf.c
kern/src/kfs.c
kern/src/manager.c
kern/src/monitor.c
kern/src/syscall.c
kern/src/vfs.c

index 3398c44..077ac74 100644 (file)
@@ -447,7 +447,6 @@ 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);
@@ -471,6 +470,7 @@ ssize_t generic_file_read(struct file *file, char *buf, size_t count,
 ssize_t generic_file_write(struct file *file, const char *buf, size_t count,
                            off_t *offset);
 struct file *do_file_open(char *path, int flags, int mode);
+struct file *dentry_open(struct dentry *dentry);
 void file_release(struct kref *kref);
 
 /* Page cache functions */
index 31d65ee..a48d3cc 100644 (file)
@@ -136,7 +136,7 @@ int load_elf(struct proc* p, struct file* f)
                return -1;
 
        if (ei.dynamic) {
-               struct file *interp = path_to_file(ei.interp);
+               struct file *interp = do_file_open(ei.interp, 0, 0);
                if (!interp)
                        return -1;
                /* careful, this could conflict with the mmap from the TLS up above */
index e2c374e..f86a148 100644 (file)
@@ -606,37 +606,10 @@ int kfs_mmap(struct file *file, struct vm_region *vmr)
        return -1;
 }
 
-/* Opens the file specified by the inode, creating and filling in the file */
-/* TODO: fill out the other // entries */
+/* Called by the VFS while opening the file, which corresponds to inode,  for
+ * the FS to do whatever it needs. */
 int kfs_open(struct inode *inode, struct file *file)
 {
-       /* This is mostly FS-agnostic, consider a get_file() helper (TODO) */
-       //file = kmem_cache_alloc(file_kcache, 0); /* done in the VFS */
-
-       /* one for the ref passed out, and *none* for the sb TAILQ */
-       kref_init(&file->f_kref, file_release, 1);
-       /* Add to the list of all files of this SB */
-       TAILQ_INSERT_TAIL(&inode->i_sb->s_files, file, f_list);
-
-       /* TODO: when we pull this out to the VFS, the function will take the dentry
-        * instead, and then call the fs_open(dentry->d_inode) */
-       struct dentry *my_d = TAILQ_FIRST(&inode->i_dentry);
-       kref_get(&my_d->d_kref, 1);
-       file->f_dentry = my_d;
-
-       kref_get(&inode->i_sb->s_mount->mnt_kref, 1);
-       file->f_vfsmnt = inode->i_sb->s_mount;          /* saving a ref to the vmnt...*/
-       file->f_op = &kfs_f_op;         /* TODO: set me == to i_fop */
-       file->f_flags = inode->i_flags;                         /* just taking the inode vals */
-       file->f_mode = inode->i_mode;
-       file->f_pos = 0;
-       file->f_uid = inode->i_uid;
-       file->f_gid = inode->i_gid;
-       file->f_error = 0;
-//     struct event_poll_tailq         f_ep_links;
-       spinlock_init(&file->f_ep_lock);
-       file->f_fs_info = 0;
-       file->f_mapping = inode->i_mapping;
        return 0;
 }
 
index dca9157..cdf4e78 100644 (file)
@@ -58,9 +58,9 @@ char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
 /* Helper macro for quickly running a process.  Pass it a string, *file, and a
  * *proc. */
 #define quick_proc_run(x, p, f)                                                  \
-       (f) = path_to_file((x));                                                     \
+       (f) = do_file_open((x), 0, 0);                                               \
        assert((f));                                                                 \
-       p_argv[0] = file_name((f));                                               \
+       p_argv[0] = file_name((f));                                                  \
        (p) = proc_create((f), p_argv, p_envp);                                      \
        kref_put(&(f)->f_kref);                                                      \
        spin_lock(&(p)->proc_lock);                                                  \
@@ -70,9 +70,9 @@ char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
        kref_put(&(p)->kref);
 
 #define quick_proc_create(x, p, f)                                               \
-       (f) = path_to_file((x));                                                     \
+       (f) = do_file_open((x), 0, 0);                                               \
        assert((f));                                                                 \
-       p_argv[0] = file_name((f));                                               \
+       p_argv[0] = file_name((f));                                                  \
        (p) = proc_create((f), p_argv, p_envp);                                      \
        kref_put(&(f)->f_kref);                                                      \
        spin_lock(&(p)->proc_lock);                                                  \
@@ -80,9 +80,9 @@ char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
        spin_unlock(&(p)->proc_lock);
 
 #define quick_proc_color_run(x, p, c, f)                                         \
-       (f) = path_to_file((x));                                                     \
+       (f) = do_file_open((x), 0, 0);                                               \
        assert((f));                                                                 \
-       p_argv[0] = file_name((f));                                               \
+       p_argv[0] = file_name((f));                                                  \
        (p) = proc_create((f), p_argv, p_envp);                                      \
        kref_put(&(f)->f_kref);                                                      \
        spin_lock(&(p)->proc_lock);                                                  \
@@ -95,9 +95,9 @@ char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
        kref_put(&(p)->kref);
 
 #define quick_proc_color_create(x, p, c, f)                                      \
-       (f) = path_to_file((x));                                                     \
+       (f) = do_file_open((x), 0, 0);                                               \
        assert((f));                                                                 \
-       p_argv[0] = file_name((f));                                               \
+       p_argv[0] = file_name((f));                                                  \
        (p) = proc_create((f), p_argv, p_envp);                                      \
        kref_put(&(f)->f_kref);                                                      \
        spin_lock(&(p)->proc_lock);                                                  \
index c762157..812c0f2 100644 (file)
@@ -257,7 +257,7 @@ int mon_bin_ls(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
        struct file *bin_dir;
        int retval = 0;
 
-       bin_dir = path_to_file("/bin");
+       bin_dir = do_file_open("/bin", 0, 0);
        if (!bin_dir) {
                printk("No /bin directory!\n");
                return 1;
@@ -282,7 +282,7 @@ int mon_bin_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
        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);
+       program = do_file_open(buf, 0, 0);
        if (!program) {
                printk("No such program!\n");
                return 1;
index 77ae012..19cb653 100644 (file)
@@ -209,7 +209,7 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
        t_path = user_strdup_errno(p, path, path_l);
        if (IS_ERR(t_path))
                return -1;
-       program = path_to_file(t_path);
+       program = do_file_open(t_path, 0, 0);
        user_memdup_free(p, t_path);
        if (!program)
                return -1;                      /* presumably, errno is already set */
@@ -402,7 +402,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
        t_path = user_strdup_errno(p, path, path_l);
        if (IS_ERR(t_path))
                return -1;
-       program = path_to_file(t_path);
+       program = do_file_open(t_path, 0, 0);
        user_memdup_free(p, t_path);
        if (!program)
                return -1;                      /* presumably, errno is already set */
index 9b10dcf..33216bd 100644 (file)
@@ -321,30 +321,6 @@ void path_release(struct nameidata *nd)
        kref_put(&nd->mnt->mnt_kref);
 }
 
-/* Seems convenient: Given a path, return the appropriate file.  The reference
- * returned is refcounted (which is done by open()).  TODO: make sure the called
- * functions do error checking and propagate errno. */
-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);
-       assert(kref_refcnt(&f->f_kref) == 1);
-       return f;
-}
-
 /* Superblock functions */
 
 /* Helper to alloc and initialize a generic superblock.  This handles all the
@@ -625,10 +601,10 @@ ssize_t generic_file_write(struct file *file, const char *buf, size_t count,
 }
 
 /* Opens the file, using permissions from current for lack of a better option.
- * Called by sys_open.  This will return 0 on failure, and set errno.
- * There's a lot of stuff that we don't do, esp related to permission checking
- * and file truncating.
- * TODO: open and create should set errno and propagate it up. */
+ * It will attempt to create the file if it does not exist and O_CREAT is
+ * specified.  This will return 0 on failure, and set errno.
+ * TODO: There's a lot of stuff that we don't do, esp related to permission
+ * checking and file truncating.  Create should set errno and propagate it up.*/
 struct file *do_file_open(char *path, int flags, int mode)
 {
        struct file *file = 0;
@@ -652,7 +628,7 @@ struct file *do_file_open(char *path, int flags, int mode)
        if (!file_d) {
                if (!(flags & O_CREAT)) {
                        path_release(nd);
-                       set_errno(current_tf, EACCES);
+                       set_errno(current_tf, ENOENT);
                        return 0;
                }
                /* Create the inode/file.  get a fresh dentry too: */
@@ -682,20 +658,12 @@ struct file *do_file_open(char *path, int flags, int mode)
        }
        /* now open the file (freshly created or if it already existed).  At this
         * point, file_d is a refcnt'd dentry, regardless of which branch we took.*/
-       file = kmem_cache_alloc(file_kcache, 0);
-       if (!file) {
-               kref_put(&file_d->d_kref);
-               path_release(nd);
-               set_errno(current_tf, ENOMEM);
-               return 0;
-       }
        if (flags & O_TRUNC)
                warn("File truncation not supported yet.");
-       if (file_d->d_inode->i_fop->open(file_d->d_inode, file)) {
+       file = dentry_open(file_d);             /* sets errno */
+       if (!file) {
                kref_put(&file_d->d_kref);
                path_release(nd);
-               kmem_cache_free(file_kcache, file);
-               set_errno(current_tf, ENOENT);
                return 0;
        }
        /* TODO: check the inode's mode (S_XXX) against the flags O_RDWR */
@@ -706,6 +674,39 @@ struct file *do_file_open(char *path, int flags, int mode)
        return file;
 }
 
+/* Opens and returns the file specified by dentry */
+struct file *dentry_open(struct dentry *dentry)
+{
+       struct inode *inode;
+       struct file *file = kmem_cache_alloc(file_kcache, 0);
+       if (!file) {
+               set_errno(current_tf, ENOMEM);
+               return 0;
+       }
+       inode = dentry->d_inode;
+       /* one for the ref passed out, and *none* for the sb TAILQ */
+       kref_init(&file->f_kref, file_release, 1);
+       /* Add to the list of all files of this SB */
+       TAILQ_INSERT_TAIL(&inode->i_sb->s_files, file, f_list);
+       kref_get(&dentry->d_kref, 1);
+       file->f_dentry = dentry;
+       kref_get(&inode->i_sb->s_mount->mnt_kref, 1);
+       file->f_vfsmnt = inode->i_sb->s_mount;          /* saving a ref to the vmnt...*/
+       file->f_op = inode->i_fop;
+       file->f_flags = inode->i_flags;                         /* just taking the inode vals */
+       file->f_mode = inode->i_mode;
+       file->f_pos = 0;
+       file->f_uid = inode->i_uid;
+       file->f_gid = inode->i_gid;
+       file->f_error = 0;
+//     struct event_poll_tailq         f_ep_links;
+       spinlock_init(&file->f_ep_lock);
+       file->f_fs_info = 0;                                            /* prob overriden by the fs */
+       file->f_mapping = inode->i_mapping;
+       file->f_op->open(inode, file);
+       return file;
+}
+
 /* Closes a file, fsync, whatever else is necessary.  Called when the kref hits
  * 0.  Note that the file is not refcounted on the s_files list, nor is the
  * f_mapping refcounted (it is pinned by the i_mapping). */