CPU state tracking
[akaros.git] / kern / src / kfs.c
index 8324323..3d9c457 100644 (file)
@@ -139,6 +139,7 @@ int kfs_readpage(struct page_map *pm, struct page *page)
        struct buffer_head *bh = kmem_cache_alloc(bh_kcache, 0);
        if (!bh)
                return -1;                      /* untested, un-thought-through */
+       atomic_or(&page->pg_flags, PG_BUFFER);
        /* KFS does a 1:1 BH to page mapping */
        bh->bh_page = page;                                                             /* weak ref */
        bh->bh_buffer = page2kva(page);
@@ -151,10 +152,16 @@ int kfs_readpage(struct page_map *pm, struct page *page)
        /* This is supposed to be done in the IO system when the operation is
         * complete.  Since we aren't doing a real IO request, and it is already
         * done, we can do it here. */
-       page->pg_flags |= PG_UPTODATE;
+       atomic_or(&page->pg_flags, PG_UPTODATE);
        return 0;
 }
 
+int kfs_writepage(struct page_map *pm, struct page *page)
+{
+       warn_once("KFS writepage does not save file contents!\n");
+       return -1;
+}
+
 /* Super Operations */
 
 /* Creates and initializes a new inode.  FS specific, yet inode-generic fields
@@ -438,7 +445,7 @@ int kfs_rmdir(struct inode *dir, struct dentry *dentry)
        if (!empty)
                return -ENOTEMPTY;
        kref_put(&dentry->d_kref);                              /* unpin the dentry, KFS-style */
-       printk("DENTRY %s REFCNT %d\n", dentry->d_name.name, kref_refcnt(&dentry->d_kref));
+       printd("DENTRY %s REFCNT %d\n", dentry->d_name.name, kref_refcnt(&dentry->d_kref));
        return 0;
 }
 
@@ -450,11 +457,26 @@ int kfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
        return -1;
 }
 
-/* Moves old_dentry from old_dir to new_dentry in new_dir */
-int kfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-               struct inode *new_dir, struct dentry *new_dentry)
-{
-       return -1;
+/* Moves old_d from old_dir to new_d in new_dir.  TODO: super racy */
+int kfs_rename(struct inode *old_dir, struct dentry *old_d,
+               struct inode *new_dir, struct dentry *new_d)
+{
+       /* new_d is already gone, we just use it for its name.  kfs might not care
+        * about the name.  it might just use whatever the dentry says. */
+       struct kfs_i_info *old_info = (struct kfs_i_info*)old_dir->i_fs_info;
+       struct kfs_i_info *new_info = (struct kfs_i_info*)new_dir->i_fs_info;
+       printd("KFS rename: %s/%s -> %s/%s\n",
+              TAILQ_FIRST(&old_dir->i_dentry)->d_name.name, old_d->d_name.name,
+              TAILQ_FIRST(&new_dir->i_dentry)->d_name.name, new_d->d_name.name);
+       /* we want to remove from the old and add to the new.  for non-directories,
+        * we need to adjust parent's children lists (which reuses subdirs_link,
+        * yikes!).  directories aren't actually tracked by KFS; it just hopes the
+        * VFS's pinned dentry tree is enough (aka, "all paths pinned"). */
+       if (!S_ISDIR(old_d->d_inode->i_mode)) {
+               TAILQ_REMOVE(&old_info->children, old_d, d_subdirs_link);
+               TAILQ_INSERT_TAIL(&new_info->children, old_d, d_subdirs_link);
+       }
+       return 0;
 }
 
 /* Returns the char* for the symname for the given dentry.  The VFS code that
@@ -474,6 +496,11 @@ char *kfs_readlink(struct dentry *dentry)
 /* Modifies the size of the file of inode to whatever its i_size is set to */
 void kfs_truncate(struct inode *inode)
 {
+       struct kfs_i_info *k_i_info = (struct kfs_i_info*)inode->i_fs_info;
+       /* init_size tracks how much of the file KFS has.  everything else is 0s.
+        * we only need to update it if we are dropping data.  as with other data
+        * beyond init_size, KFS will not save it during a write page! */
+       k_i_info->init_size = MIN(k_i_info->init_size, inode->i_size);
 }
 
 /* Checks whether the the access mode is allowed for the file belonging to the
@@ -492,12 +519,6 @@ int kfs_d_revalidate(struct dentry *dir, struct nameidata *nd)
        return -1;
 }
 
-/* Produces the hash to lookup this dentry from the dcache */
-int kfs_d_hash(struct dentry *dentry, struct qstr *name)
-{
-       return -1;
-}
-
 /* Compares name1 and name2.  name1 should be a member of dir. */
 int kfs_d_compare(struct dentry *dir, struct qstr *name1, struct qstr *name2)
 { // default, string comp (case sensitive)
@@ -524,8 +545,7 @@ void kfs_d_iput(struct dentry *dentry, struct inode *inode)
 
 /* file_operations */
 
-/* Updates the file pointer.  KFS doesn't let you go past the end of a file
- * yet, so it won't let you seek past either.  TODO: think about locking. */
+/* Updates the file pointer.  TODO: think about locking. */
 int kfs_llseek(struct file *file, off64_t offset, off64_t *ret, int whence)
 {
        off64_t temp_off = 0;
@@ -544,9 +564,6 @@ int kfs_llseek(struct file *file, off64_t offset, off64_t *ret, int whence)
                        warn("Unknown 'whence' in llseek()!\n");
                        return -1;
        }
-       /* make sure the f_pos isn't outside the limits of the existing file.
-        * techincally, if they go too far, we should return EINVAL */
-       temp_off = MAX(MIN(temp_off, file->f_dentry->d_inode->i_size), 0);
        file->f_pos = temp_off;
        *ret = temp_off;
        return 0;
@@ -688,6 +705,7 @@ int kfs_check_flags(int flags)
 /* Redeclaration and initialization of the FS ops structures */
 struct page_map_operations kfs_pm_op = {
        kfs_readpage,
+       kfs_writepage,
 };
 
 struct super_operations kfs_s_op = {
@@ -723,7 +741,7 @@ struct inode_operations kfs_i_op = {
 
 struct dentry_operations kfs_d_op = {
        kfs_d_revalidate,
-       kfs_d_hash,
+       generic_dentry_hash,
        kfs_d_compare,
        kfs_d_delete,
        kfs_d_release,