Return bool from reset_alarm_* apis.
[akaros.git] / kern / src / vfs.c
index 0cbceb0..cd330bc 100644 (file)
@@ -112,16 +112,26 @@ void vfs_init(void)
        printk("vfs_init() completed\n");
 }
 
+/* FS's can provide another, if they want */
+int generic_dentry_hash(struct dentry *dentry, struct qstr *qstr)
+{
+       unsigned long hash = 5381;
+
+       for (int i = 0; i < qstr->len; i++) {
+               /* hash * 33 + c, djb2's technique */
+               hash = ((hash << 5) + hash) + qstr->name[i];
+       }
+       return hash;
+}
+
 /* Builds / populates the qstr of a dentry based on its d_iname.  If there is an
  * l_name, (long), it will use that instead of the inline name.  This will
  * probably change a bit. */
 void qstr_builder(struct dentry *dentry, char *l_name)
 {
        dentry->d_name.name = l_name ? l_name : dentry->d_iname;
-       // TODO: pending what we actually do in d_hash
-       //dentry->d_name.hash = dentry->d_op->d_hash(dentry, &dentry->d_name); 
-       dentry->d_name.hash = 0xcafebabe;
        dentry->d_name.len = strnlen(dentry->d_name.name, MAX_FILENAME_SZ);
+       dentry->d_name.hash = dentry->d_op->d_hash(dentry, &dentry->d_name);
 }
 
 /* Useful little helper - return the string ptr for a given file */
@@ -1381,6 +1391,10 @@ struct file *do_file_open(char *path, int flags, int mode)
                kref_get(&file_d->d_kref, 1);
                goto open_the_file;
        }
+       if (!(flags & O_CREAT)) {
+               set_errno(-error);
+               goto out_path_only;
+       }
        /* So it didn't already exist, release the path from the previous lookup,
         * and then we try to create it. */
        path_release(nd);       
@@ -1396,6 +1410,7 @@ struct file *do_file_open(char *path, int flags, int mode)
        file_d = do_lookup(nd->dentry, nd->last.name); 
        if (!file_d) {
                if (!(flags & O_CREAT)) {
+                       warn("Extremely unlikely race, probably a bug");
                        set_errno(ENOENT);
                        goto out_path_only;
                }
@@ -2308,7 +2323,8 @@ struct file *get_file_from_fd(struct files_struct *open_files, int file_desc)
 }
 
 /* Grow the vfs fd set */
-static int grow_fd_set(struct files_struct *open_files) {
+static int grow_fd_set(struct files_struct *open_files)
+{
        int n;
        struct file_desc *nfd, *ofd;
 
@@ -2324,10 +2340,10 @@ static int grow_fd_set(struct files_struct *open_files) {
        /* Grow the open_files->fd array in increments of NR_OPEN_FILES_DEFAULT */
        n = open_files->max_files + NR_OPEN_FILES_DEFAULT;
        if (n > NR_FILE_DESC_MAX)
-               n = NR_FILE_DESC_MAX;
+               return -EMFILE;
        nfd = kzmalloc(n * sizeof(struct file_desc), 0);
        if (nfd == NULL)
-               return -1;
+               return -ENOMEM;
 
        /* Move the old array on top of the new one */
        ofd = open_files->fd;
@@ -2345,11 +2361,24 @@ static int grow_fd_set(struct files_struct *open_files) {
 }
 
 /* Free the vfs fd set if necessary */
-static void free_fd_set(struct files_struct *open_files) {
+static void free_fd_set(struct files_struct *open_files)
+{
+       void *free_me;
        if (open_files->open_fds != (struct fd_set*)&open_files->open_fds_init) {
-               kfree(open_files->open_fds);
                assert(open_files->fd != open_files->fd_array);
-               kfree(open_files->fd);
+               /* need to reset the pointers to the internal addrs, in case we take a
+                * look while debugging.  0 them out, since they have old data.  our
+                * current versions should all be closed. */
+               memset(&open_files->open_fds_init, 0, sizeof(struct small_fd_set));
+               memset(&open_files->fd_array, 0, sizeof(open_files->fd_array));
+
+               free_me = open_files->open_fds;
+               open_files->open_fds = (struct fd_set*)&open_files->open_fds_init;
+               kfree(free_me);
+
+               free_me = open_files->fd;
+               open_files->fd = open_files->fd_array;
+               kfree(free_me);
        }
 }
 
@@ -2401,6 +2430,7 @@ struct file *put_file_from_fd(struct files_struct *open_files, int file_desc)
 static int __get_fd(struct files_struct *open_files, int low_fd)
 {
        int slot = -1;
+       int error;
        if ((low_fd < 0) || (low_fd > NR_FILE_DESC_MAX))
                return -EINVAL;
        if (open_files->closed)
@@ -2421,27 +2451,29 @@ static int __get_fd(struct files_struct *open_files, int low_fd)
                        break;
                }
                if (slot == -1) {
-                       /* Expand the FD array and fd_set */
-                       if (grow_fd_set(open_files) == -1)
-                               return -ENOMEM;
-                       /* loop after growing */
+                       if ((error = grow_fd_set(open_files)))
+                               return error;
                }
        }
        return slot;
 }
 
-/* Gets and claims a free FD, used by 9ns.  < 0 == error. */
-int get_fd(struct files_struct *open_files, int low_fd)
+/* Gets and claims a free FD, used by 9ns.  < 0 == error.  cloexec is tracked on
+ * the VFS FD.  It's value will be O_CLOEXEC (not 1) or 0. */
+int get_fd(struct files_struct *open_files, int low_fd, int cloexec)
 {
        int slot;
        spin_lock(&open_files->lock);
        slot = __get_fd(open_files, low_fd);
+       if (cloexec && (slot >= 0))
+               open_files->fd[slot].fd_flags |= FD_CLOEXEC;
        spin_unlock(&open_files->lock);
        return slot;
 }
 
 static int __claim_fd(struct files_struct *open_files, int file_desc)
 {
+       int error;
        if ((file_desc < 0) || (file_desc > NR_FILE_DESC_MAX))
                return -EINVAL;
        if (open_files->closed)
@@ -2449,7 +2481,8 @@ static int __claim_fd(struct files_struct *open_files, int file_desc)
 
        /* Grow the open_files->fd_set until the file_desc can fit inside it */
        while(file_desc >= open_files->max_files) {
-               grow_fd_set(open_files);
+               if ((error = grow_fd_set(open_files)))
+                       return error;
                cpu_relax();
        }
 
@@ -2465,7 +2498,8 @@ static int __claim_fd(struct files_struct *open_files, int file_desc)
        return 0;
 }
 
-/* Claims a specific FD when duping FDs. used by 9ns.  < 0 == error. */
+/* Claims a specific FD when duping FDs. used by 9ns.  < 0 == error.  No need
+ * for cloexec here, since it's not used during dup. */
 int claim_fd(struct files_struct *open_files, int file_desc)
 {
        int ret;
@@ -2476,9 +2510,12 @@ int claim_fd(struct files_struct *open_files, int file_desc)
 }
 
 /* Inserts the file in the files_struct, returning the corresponding new file
- * descriptor, or an error code.  We start looking for open fds from low_fd. */
+ * descriptor, or an error code.  We start looking for open fds from low_fd.
+ *
+ * Passing cloexec is a bit cheap, since we might want to expand it to support
+ * more FD options in the future. */
 int insert_file(struct files_struct *open_files, struct file *file, int low_fd,
-                bool must)
+                bool must, bool cloexec)
 {
        int slot, ret;
        spin_lock(&open_files->lock);
@@ -2503,12 +2540,14 @@ int insert_file(struct files_struct *open_files, struct file *file, int low_fd,
        kref_get(&file->f_kref, 1);
        open_files->fd[slot].fd_file = file;
        open_files->fd[slot].fd_flags = 0;
+       if (cloexec)
+               open_files->fd[slot].fd_flags |= FD_CLOEXEC;
        spin_unlock(&open_files->lock);
        return slot;
 }
 
 /* Closes all open files.  Mostly just a "put" for all files.  If cloexec, it
- * will only close files that are opened with O_CLOEXEC. */
+ * will only close the FDs with FD_CLOEXEC (opened with O_CLOEXEC or fcntld). */
 void close_all_files(struct files_struct *open_files, bool cloexec)
 {
        struct file *file;
@@ -2526,7 +2565,7 @@ void close_all_files(struct files_struct *open_files, bool cloexec)
                        /* no file == 9ns uses the FD.  they will deal with it */
                        if (!file)
                                continue;
-                       if (cloexec && !(open_files->fd[i].fd_flags & O_CLOEXEC))
+                       if (cloexec && !(open_files->fd[i].fd_flags & FD_CLOEXEC))
                                continue;
                        /* Actually close the file */
                        open_files->fd[i].fd_file = 0;