Track errno and errstr in the kthread
[akaros.git] / kern / src / vfs.c
index f783e91..667b52d 100644 (file)
@@ -29,6 +29,32 @@ struct kmem_cache *dentry_kcache; // not to be confused with the dcache
 struct kmem_cache *inode_kcache;
 struct kmem_cache *file_kcache;
 
+enum {
+       VFS_MTIME,
+       VFS_CTIME,
+       VFS_ATIME,
+};
+
+/* mtime implies ctime implies atime. */
+static void set_acmtime(struct inode *inode, int which)
+{
+       struct timespec now = nsec2timespec(epoch_nsec());
+
+       switch (which) {
+       case VFS_MTIME:
+               inode->i_mtime.tv_sec = now.tv_sec;
+               inode->i_mtime.tv_nsec = now.tv_nsec;
+               /* fall through */
+       case VFS_CTIME:
+               inode->i_ctime.tv_sec = now.tv_sec;
+               inode->i_ctime.tv_nsec = now.tv_nsec;
+               /* fall through */
+       case VFS_ATIME:
+               inode->i_atime.tv_sec = now.tv_sec;
+               inode->i_atime.tv_nsec = now.tv_nsec;
+       }
+}
+
 /* Mounts fs from dev_name at mnt_pt in namespace ns.  There could be no mnt_pt,
  * such as with the root of (the default) namespace.  Not sure how it would work
  * with multiple namespaces on the same FS yet.  Note if you mount the same FS
@@ -88,11 +114,14 @@ void vfs_init(void)
        struct fs_type *fs;
 
        dentry_kcache = kmem_cache_create("dentry", sizeof(struct dentry),
-                                         __alignof__(struct dentry), 0, 0, 0);
+                                         __alignof__(struct dentry), 0,
+                                         NULL, 0, 0, NULL);
        inode_kcache = kmem_cache_create("inode", sizeof(struct inode),
-                                        __alignof__(struct inode), 0, 0, 0);
+                                        __alignof__(struct inode), 0, NULL,
+                                        0, 0, NULL);
        file_kcache = kmem_cache_create("file", sizeof(struct file),
-                                       __alignof__(struct file), 0, 0, 0);
+                                       __alignof__(struct file), 0, NULL, 0,
+                                       0, NULL);
        /* default NS never dies, +1 to exist */
        kref_init(&default_ns.kref, fake_release, 1);
        spinlock_init(&default_ns.lock);
@@ -189,7 +218,7 @@ static struct dentry *do_lookup(struct dentry *parent, char *name)
                warn("OOM in do_lookup(), probably wasn't expected\n");
                return 0;
        }
-       result = dcache_get(parent->d_sb, query); 
+       result = dcache_get(parent->d_sb, query);
        if (result) {
                __dentry_free(query);
                return result;
@@ -218,7 +247,7 @@ static struct dentry *do_lookup(struct dentry *parent, char *name)
 
        /* TODO: if the following are done by us, how do we know the i_ino?
         * also need to handle inodes that are already read in!  For now, we're
-        * going to have the FS handle it in it's lookup() method: 
+        * going to have the FS handle it in its lookup() method:
         * - get a new inode
         * - read in the inode
         * - put in the inode cache */
@@ -298,7 +327,7 @@ static int follow_symlink(struct nameidata *nd)
        nd->depth++;
        symname = nd->dentry->d_inode->i_op->readlink(nd->dentry);
        /* We need to pin in nd->dentry (the dentry of the symlink), since we need
-        * it's symname's storage to stay in memory throughout the upcoming
+        * its symname's storage to stay in memory throughout the upcoming
         * link_path_walk().  The last_sym gets decreffed when we path_release() or
         * follow another symlink. */
        if (nd->last_sym)
@@ -312,7 +341,7 @@ static int follow_symlink(struct nameidata *nd)
                if (!current)
                        nd->dentry = default_ns.root->mnt_root;
                else
-                       nd->dentry = current->fs_env.root;      
+                       nd->dentry = current->fs_env.root;
                nd->mnt = nd->dentry->d_sb->s_mount;
                kref_get(&nd->mnt->mnt_kref, 1);
                kref_get(&nd->dentry->d_kref, 1);
@@ -337,7 +366,7 @@ static bool packed_trailing_slashes(char *first_slash)
        return FALSE;
 }
 
-/* Simple helper to set nd to track it's last name to be Name.  Also be careful
+/* Simple helper to set nd to track its last name to be Name.  Also be careful
  * with the storage of name.  Don't use and nd's name past the lifetime of the
  * string used in the path_lookup()/link_path_walk/whatever.  Consider replacing
  * parts of this with a qstr builder.  Note this uses the dentry's d_op, which
@@ -492,7 +521,7 @@ next_loop:
 }
 
 /* Given path, return the inode for the final dentry.  The ND should be
- * initialized for the first call - specifically, we need the intent. 
+ * initialized for the first call - specifically, we need the intent.
  * LOOKUP_PARENT and friends go in the flags var, which is not the intent.
  *
  * If path_lookup wants a PARENT, but hits the top of the FS (root or
@@ -515,11 +544,11 @@ int path_lookup(char *path, int flags, struct nameidata *nd)
                if (!current)
                        nd->dentry = default_ns.root->mnt_root;
                else
-                       nd->dentry = current->fs_env.root;      
+                       nd->dentry = current->fs_env.root;
        } else {                                                /* relative lookup */
                assert(current);
                /* Don't need to lock on the fs_env since we're reading one item */
-               nd->dentry = current->fs_env.pwd;       
+               nd->dentry = current->fs_env.pwd;
        }
        nd->mnt = nd->dentry->d_sb->s_mount;
        /* Whenever references get put in the nd, incref them.  Whenever they are
@@ -528,7 +557,7 @@ int path_lookup(char *path, int flags, struct nameidata *nd)
        kref_get(&nd->dentry->d_kref, 1);
        nd->flags = flags;
        nd->depth = 0;                                  /* used in symlink following */
-       retval =  link_path_walk(path, nd);     
+       retval =  link_path_walk(path, nd);
        /* make sure our PARENT lookup worked */
        if (!retval && (flags & LOOKUP_PARENT))
                assert(nd->last.name);
@@ -556,7 +585,7 @@ int mount_fs(struct fs_type *fs, char *dev_name, char *path, int flags)
        retval = path_lookup(path, LOOKUP_DIRECTORY, nd);
        if (retval)
                goto out;
-       /* taking the namespace of the vfsmount of path */ 
+       /* taking the namespace of the vfsmount of path */
        if (!__mount_fs(fs, dev_name, nd->dentry, flags, nd->mnt->mnt_namespace))
                retval = -EINVAL;
 out:
@@ -587,7 +616,7 @@ static ssize_t __dcache_eq(void *k1, void *k2)
 
 /* Helper to alloc and initialize a generic superblock.  This handles all the
  * VFS related things, like lists.  Each FS will need to handle its own things
- * in it's *_get_sb(), usually involving reading off the disc. */
+ * in its *_get_sb(), usually involving reading off the disc. */
 struct super_block *get_sb(void)
 {
        struct super_block *sb = kmalloc(sizeof(struct super_block), 0);
@@ -610,7 +639,7 @@ struct super_block *get_sb(void)
 
 /* Final stages of initializing a super block, including creating and linking
  * the root dentry, root inode, vmnt, and sb.  The d_op and root_ino are
- * FS-specific, but otherwise it's FS-independent, tricky, and not worth having
+ * FS-specific, but otherwise its FS-independent, tricky, and not worth having
  * around multiple times.
  *
  * Not the world's best interface, so it's subject to change, esp since we're
@@ -1023,7 +1052,6 @@ void load_inode(struct dentry *dentry, unsigned long ino)
  * note we don't pass this an nd, like Linux does... */
 static struct inode *create_inode(struct dentry *dentry, int mode)
 {
-       uint64_t now = epoch_sec();
        /* note it is the i_ino that uniquely identifies a file in the specific
         * filesystem.  there's a diff between creating an inode (even for an in-use
         * ino) and then filling it in, and vs creating a brand new one.
@@ -1036,12 +1064,7 @@ static struct inode *create_inode(struct dentry *dentry, int mode)
        inode->i_nlink = 1;
        inode->i_size = 0;
        inode->i_blocks = 0;
-       inode->i_atime.tv_sec = now;
-       inode->i_ctime.tv_sec = now;
-       inode->i_mtime.tv_sec = now;
-       inode->i_atime.tv_nsec = 0;
-       inode->i_ctime.tv_nsec = 0;
-       inode->i_mtime.tv_nsec = 0;
+       set_acmtime(inode, VFS_MTIME);
        inode->i_bdev = inode->i_sb->s_bdev;
        /* when we have notions of users, do something here: */
        inode->i_uid = 0;
@@ -1058,6 +1081,7 @@ int create_file(struct inode *dir, struct dentry *dentry, int mode)
        if (!new_file)
                return -1;
        dir->i_op->create(dir, dentry, mode, 0);
+       set_acmtime(dir, VFS_MTIME);
        icache_put(new_file->i_sb, new_file);
        kref_put(&new_file->i_kref);
        return 0;
@@ -1078,6 +1102,7 @@ int create_dir(struct inode *dir, struct dentry *dentry, int mode)
        assert(parent && parent == TAILQ_LAST(&dir->i_dentry, dentry_tailq));
        /* parent dentry tracks dentry as a subdir, weak reference */
        TAILQ_INSERT_TAIL(&parent->d_subdirs, dentry, d_subdirs_link);
+       set_acmtime(dir, VFS_MTIME);
        icache_put(new_dir->i_sb, new_dir);
        kref_put(&new_dir->i_kref);
        return 0;
@@ -1092,6 +1117,7 @@ int create_symlink(struct inode *dir, struct dentry *dentry,
        if (!new_sym)
                return -1;
        dir->i_op->symlink(dir, dentry, symname);
+       set_acmtime(dir, VFS_MTIME);
        icache_put(new_sym->i_sb, new_sym);
        kref_put(&new_sym->i_kref);
        return 0;
@@ -1250,16 +1276,12 @@ ssize_t generic_file_read(struct file *file, char *buf, size_t count,
                error = pm_load_page(file->f_mapping, i, &page);
                assert(!error); /* TODO: handle ENOMEM and friends */
                copy_amt = MIN(PGSIZE - page_off, buf_end - buf);
-               /* TODO: (UMEM) think about this.  if it's a user buffer, we're relying
-                * on current to detect whose it is (which should work for async calls).
-                * Also, need to propagate errors properly...  Probably should do a
-                * user_mem_check, then free, and also to make a distinction between
-                * when the kernel wants a read/write (TODO: KFOP) */
-               if (current) {
+               /* TODO: (KFOP) Probably shouldn't do this.  Either memcpy directly, or
+                * split out the is_user_r(w)addr from copy_{to,from}_user() */
+               if (!is_ktask(per_cpu_info[core_id()].cur_kthread))
                        memcpy_to_user(current, buf, page2kva(page) + page_off, copy_amt);
-               } else {
+               else
                        memcpy(buf, page2kva(page) + page_off, copy_amt);
-               }
                buf += copy_amt;
                page_off = 0;
                pm_put_page(page);      /* it's still in the cache, we just don't need it */
@@ -1269,6 +1291,7 @@ ssize_t generic_file_read(struct file *file, char *buf, size_t count,
         * safe.  but at least it'll be a value that one of the concurrent ops could
         * have produced (compared to *offset_changed_concurrently += count. */
        *offset = orig_off + count;
+       set_acmtime(file->f_dentry->d_inode, VFS_ATIME);
        return count;
 }
 
@@ -1323,14 +1346,11 @@ ssize_t generic_file_write(struct file *file, const char *buf, size_t count,
                error = pm_load_page(file->f_mapping, i, &page);
                assert(!error); /* TODO: handle ENOMEM and friends */
                copy_amt = MIN(PGSIZE - page_off, buf_end - buf);
-               /* TODO: (UMEM) (KFOP) think about this.  if it's a user buffer, we're
-                * relying on current to detect whose it is (which should work for async
-                * calls). */
-               if (current) {
+               /* TODO: (UMEM) (KFOP) think about this. */
+               if (!is_ktask(per_cpu_info[core_id()].cur_kthread))
                        memcpy_from_user(current, page2kva(page) + page_off, buf, copy_amt);
-               } else {
+               else
                        memcpy(page2kva(page) + page_off, buf, copy_amt);
-               }
                buf += copy_amt;
                page_off = 0;
                atomic_or(&page->pg_flags, PG_DIRTY);
@@ -1338,6 +1358,7 @@ ssize_t generic_file_write(struct file *file, const char *buf, size_t count,
        }
        assert(buf == buf_end);
        *offset = orig_off + count;
+       set_acmtime(file->f_dentry->d_inode, VFS_MTIME);
        return count;
 }
 
@@ -1377,11 +1398,10 @@ ssize_t generic_dir_read(struct file *file, char *u_buf, size_t count,
                }
                /* Slight info exposure: could be extra crap after the name in the
                 * dirent (like the name of a deleted file) */
-               if (current) {
+               if (!is_ktask(per_cpu_info[core_id()].cur_kthread))
                        memcpy_to_user(current, u_buf, dirent, sizeof(struct dirent));
-               } else {
+               else
                        memcpy(u_buf, dirent, sizeof(struct dirent));
-               }
                amt_copied += sizeof(struct dirent);
                /* 0 signals end of directory */
                if (retval == 0)
@@ -1390,8 +1410,9 @@ ssize_t generic_dir_read(struct file *file, char *u_buf, size_t count,
        /* Next time read is called, we pick up where we left off */
        *offset = dirent->d_off;        /* UMEM */
        /* important to tell them how much they got.  they often keep going til they
-        * get 0 back (in the case of ls).  it's also how much has been read, but it
+        * get 0 back (in the case of ls).  It's also how much has been read, but it
         * isn't how much the f_pos has moved (which is opaque to the VFS). */
+       set_acmtime(file->f_dentry->d_inode, VFS_ATIME);
        return amt_copied;
 }
 
@@ -1438,7 +1459,7 @@ struct file *do_file_open(char *path, int flags, int mode)
        }
        /* So it didn't already exist, release the path from the previous lookup,
         * and then we try to create it. */
-       path_release(nd);       
+       path_release(nd);
        /* get the parent, following links.  this means you get the parent of the
         * final link (which may not be in 'path' in the first place. */
        nd->intent = LOOKUP_CREATE;
@@ -1448,7 +1469,7 @@ struct file *do_file_open(char *path, int flags, int mode)
                goto out_path_only;
        }
        /* see if the target is there (shouldn't be), and handle accordingly */
-       file_d = do_lookup(nd->dentry, nd->last.name); 
+       file_d = do_lookup(nd->dentry, nd->last.name);
        if (!file_d) {
                if (!(flags & O_CREAT)) {
                        warn("Extremely unlikely race, probably a bug");
@@ -1513,7 +1534,7 @@ int do_symlink(char *path, const char *symname, int mode)
                goto out_path_only;
        }
        /* see if the target is already there, handle accordingly */
-       sym_d = do_lookup(nd->dentry, nd->last.name); 
+       sym_d = do_lookup(nd->dentry, nd->last.name);
        if (sym_d) {
                set_errno(EEXIST);
                goto out_sym_d;
@@ -1525,6 +1546,7 @@ int do_symlink(char *path, const char *symname, int mode)
        parent_i = nd->dentry->d_inode;
        if (create_symlink(parent_i, sym_d, symname, mode))
                goto out_sym_d;
+       set_acmtime(parent_i, VFS_MTIME);
        dcache_put(sym_d->d_sb, sym_d);
        retval = 0;                             /* Note the fall through to the exit paths */
 out_sym_d:
@@ -1552,7 +1574,7 @@ int do_link(char *old_path, char *new_path)
        }
        parent_dir = nd->dentry->d_inode;
        /* see if the new target is already there, handle accordingly */
-       link_d = do_lookup(nd->dentry, nd->last.name); 
+       link_d = do_lookup(nd->dentry, nd->last.name);
        if (link_d) {
                set_errno(EEXIST);
                goto out_link_d;
@@ -1583,6 +1605,7 @@ int do_link(char *old_path, char *new_path)
                set_errno(-error);
                goto out_both_ds;
        }
+       set_acmtime(parent_dir, VFS_MTIME);
        /* Finally stitch it up */
        inode = old_d->d_inode;
        kref_get(&inode->i_kref, 1);
@@ -1618,7 +1641,7 @@ int do_unlink(char *path)
        }
        parent_dir = nd->dentry->d_inode;
        /* make sure the target is there */
-       dentry = do_lookup(nd->dentry, nd->last.name); 
+       dentry = do_lookup(nd->dentry, nd->last.name);
        if (!dentry) {
                set_errno(ENOENT);
                goto out_path_only;
@@ -1634,6 +1657,7 @@ int do_unlink(char *path)
                set_errno(-error);
                goto out_dentry;
        }
+       set_acmtime(parent_dir, VFS_MTIME);
        /* Now that our parent doesn't track us, we need to make sure we aren't
         * findable via the dentry cache.  DYING, so we will be freed in
         * dentry_release() */
@@ -1662,7 +1686,7 @@ int do_access(char *path, int mode)
        int retval = 0;
        nd->intent = LOOKUP_ACCESS;
        retval = path_lookup(path, 0, nd);
-       path_release(nd);       
+       path_release(nd);
        return retval;
 }
 
@@ -1676,6 +1700,7 @@ int do_file_chmod(struct file *file, int mode)
        else
        #endif
                file->f_dentry->d_inode->i_mode = (mode & S_PMASK) | old_mode_ftype;
+       set_acmtime(file->f_dentry->d_inode, VFS_CTIME);
        return 0;
 }
 
@@ -1710,6 +1735,7 @@ int do_mkdir(char *path, int mode)
        parent_i = nd->dentry->d_inode;
        if (create_dir(parent_i, dentry, mode))
                goto out_dentry;
+       set_acmtime(parent_i, VFS_MTIME);
        dcache_put(dentry->d_sb, dentry);
        retval = 0;                             /* Note the fall through to the exit paths */
 out_dentry:
@@ -1738,7 +1764,7 @@ int do_rmdir(char *path)
                goto out_path_only;
        }
        /* make sure the target is already there, handle accordingly */
-       dentry = do_lookup(nd->dentry, nd->last.name); 
+       dentry = do_lookup(nd->dentry, nd->last.name);
        if (!dentry) {
                set_errno(ENOENT);
                goto out_path_only;
@@ -1759,6 +1785,7 @@ int do_rmdir(char *path)
                set_errno(-error);
                goto out_dentry;
        }
+       set_acmtime(parent_i, VFS_MTIME);
        /* Now that our parent doesn't track us, we need to make sure we aren't
         * findable via the dentry cache.  DYING, so we will be freed in
         * dentry_release() */
@@ -1855,6 +1882,7 @@ ssize_t pipe_file_read(struct file *file, char *buf, size_t count,
        if (amt_copied)
                __cv_broadcast(&pii->p_cv);
        cv_unlock(&pii->p_cv);
+       set_acmtime(file->f_dentry->d_inode, VFS_ATIME);
        return amt_copied;
 }
 
@@ -1909,6 +1937,7 @@ ssize_t pipe_file_write(struct file *file, const char *buf, size_t count,
        if (amt_copied)
                __cv_broadcast(&pii->p_cv);
        cv_unlock(&pii->p_cv);
+       set_acmtime(file->f_dentry->d_inode, VFS_MTIME);
        return amt_copied;
 }
 
@@ -2013,7 +2042,7 @@ int do_pipe(struct file **pipe_files, int flags)
        /* Actually build the pipe.  We're using one page, hanging off the
         * pipe_inode_info struct.  When we release the inode, we free the pipe
         * memory too */
-       pipe_i->i_pipe = kmalloc(sizeof(struct pipe_inode_info), KMALLOC_WAIT);
+       pipe_i->i_pipe = kmalloc(sizeof(struct pipe_inode_info), MEM_WAIT);
        pii = pipe_i->i_pipe;
        if (!pii) {
                set_errno(ENOMEM);
@@ -2065,7 +2094,6 @@ int do_rename(char *old_path, char *new_path)
        struct dentry *old_d, *new_d, *unlink_d;
        int error;
        int retval = 0;
-       uint64_t now;
 
        nd_o->intent = LOOKUP_ACCESS; /* maybe, might need another type */
 
@@ -2109,7 +2137,7 @@ int do_rename(char *old_path, char *new_path)
                goto out_paths_and_src;
        }
        /* TODO: if we're doing a rename that moves a directory, we need to make
-        * sure the new_path doesn't include the old_path.  it's not as simple as
+        * sure the new_path doesn't include the old_path.  It's not as simple as
         * just checking, since there could be a concurrent rename that breaks the
         * check later.  e.g. what if new_dir's parent is being moved into a child
         * of old_dir?
@@ -2193,16 +2221,9 @@ int do_rename(char *old_path, char *new_path)
         * replace a potentially negative dentry for new_d (now called old_d) */
        dcache_put(old_dir_d->d_sb, old_d);
 
-       /* TODO could have a helper for this, but it's going away soon */
-       now = epoch_sec();
-       old_dir_i->i_ctime.tv_sec = now;
-       old_dir_i->i_mtime.tv_sec = now;
-       old_dir_i->i_ctime.tv_nsec = 0;
-       old_dir_i->i_mtime.tv_nsec = 0;
-       new_dir_i->i_ctime.tv_sec = now;
-       new_dir_i->i_mtime.tv_sec = now;
-       new_dir_i->i_ctime.tv_nsec = 0;
-       new_dir_i->i_mtime.tv_nsec = 0;
+       set_acmtime(old_dir_i, VFS_MTIME);
+       set_acmtime(new_dir_i, VFS_MTIME);
+       set_acmtime(old_d->d_inode, VFS_CTIME);
 
        /* fall-through */
 out_paths_and_refs:
@@ -2219,7 +2240,7 @@ out_old_path:
 int do_truncate(struct inode *inode, off64_t len)
 {
        off64_t old_len;
-       uint64_t now;
+
        if (len < 0) {
                set_errno(EINVAL);
                return -1;
@@ -2244,11 +2265,7 @@ int do_truncate(struct inode *inode, off64_t len)
                pm_remove_contig(inode->i_mapping, old_len >> PGSHIFT,
                                 (len >> PGSHIFT) - (old_len >> PGSHIFT));
        }
-       now = epoch_sec();
-       inode->i_ctime.tv_sec = now;
-       inode->i_mtime.tv_sec = now;
-       inode->i_ctime.tv_nsec = 0;
-       inode->i_mtime.tv_nsec = 0;
+       set_acmtime(inode, VFS_MTIME);
        return 0;
 }
 
@@ -2327,11 +2344,12 @@ void file_release(struct kref *kref)
 
 ssize_t kread_file(struct file *file, void *buf, size_t sz)
 {
-       /* TODO: (KFOP) (VFS kernel read/writes need to have no proc current) */
-       struct proc *old_proc = switch_to(0);
+       /* 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);
-       switch_back(0, old_proc);
+
+       switch_back_from_ktask(old_ret);
        return cpy_amt;
 }
 
@@ -2344,7 +2362,7 @@ void *kread_whole_file(struct file *file)
        ssize_t cpy_amt;
 
        size = file->f_dentry->d_inode->i_size;
-       contents = kmalloc(size, KMALLOC_WAIT);
+       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));
@@ -2606,7 +2624,7 @@ void close_fdt(struct fd_table *fdt, bool cloexec)
        int idx = 0;
 
        to_close = kzmalloc(sizeof(struct file_desc) * fdt->max_files,
-                           KMALLOC_WAIT);
+                           MEM_WAIT);
        spin_lock(&fdt->lock);
        if (fdt->closed) {
                spin_unlock(&fdt->lock);
@@ -2660,6 +2678,8 @@ void clone_fdt(struct fd_table *src, struct fd_table *dst)
 {
        struct file *file;
        struct chan *chan;
+       int ret;
+
        spin_lock(&src->lock);
        if (src->closed) {
                spin_unlock(&src->lock);
@@ -2672,6 +2692,15 @@ void clone_fdt(struct fd_table *src, struct fd_table *dst)
                spin_unlock(&src->lock);
                return;
        }
+       while (src->max_files > dst->max_files) {
+               ret = grow_fd_set(dst);
+               if (ret < 0) {
+                       set_error(-ret, "Failed to grow for a clone_fdt");
+                       spin_unlock(&dst->lock);
+                       spin_unlock(&src->lock);
+                       return;
+               }
+       }
        for (int i = 0; i < src->max_fdset; i++) {
                if (GET_BITMASK_BIT(src->open_fds->fds_bits, i)) {
                        /* while max_files and max_fdset might not line up, we should never
@@ -2761,7 +2790,7 @@ char *do_getcwd(struct fs_struct *fs_env, char **kfree_this, size_t cwd_l)
        kbuf[cwd_l - 2] = '/';
        /* for each dentry in the path, all the way back to the root of fs_env, we
         * grab the dentry name, push path_start back enough, and write in the name,
-        * using /'s to terminate.  We skip the root, since we don't want it's
+        * using /'s to terminate.  We skip the root, since we don't want its
         * actual name, just "/", which is set before each loop. */
        path_start = kbuf + cwd_l - 2;  /* the last byte written */
        while (dentry != fs_env->root) {
@@ -2775,7 +2804,7 @@ char *do_getcwd(struct fs_struct *fs_env, char **kfree_this, size_t cwd_l)
                memmove(path_start, dentry->d_name.name, link_len);
                path_start--;
                *path_start = '/';
-               dentry = dentry->d_parent;      
+               dentry = dentry->d_parent;
        }
        return path_start;
 }
@@ -2840,7 +2869,7 @@ static void print_dir(struct dentry *dentry, char *buf, int depth)
                                default:
                                        warn("Look around you!  Unknown filetype!");
                        }
-                       kref_put(&child_d->d_kref);     
+                       kref_put(&child_d->d_kref);
                }
 loop_next:
                if (retval <= 0)