Inode cache
[akaros.git] / kern / include / vfs.h
index a4e97fb..2e0c204 100644 (file)
@@ -19,6 +19,8 @@
 #include <kref.h>
 #include <timing.h>
 #include <radix.h>
+#include <hashtable.h>
+#include <blockdev.h>
 
 /* ghetto preprocessor hacks (since proc includes vfs) */
 struct page;
@@ -29,11 +31,12 @@ typedef int dev_t;
 typedef int kdev_t;
 typedef int ino_t;
 typedef long off_t; // out there in other .h's, but not in the kernel yet
-struct block_device    {int x;};
 struct io_writeback    {int x;};
 struct event_poll {int x;};
 struct poll_table_struct {int x;};
-// end temp typedefs
+// end temp typedefs.  note ino and off_t are needed in the next include
+
+#include <ros/fs.h>
 
 struct page_map;       /* analagous to linux's address_space object */
 struct page_map_operations;
@@ -48,16 +51,6 @@ struct file_operations;
 struct fs_type;
 struct vfsmount;
 
-/* part of the kernel interface, ripped from man pages, ought to work. */
-// TODO: eventually move this to ros/fs.h or something.
-#define MAX_FILENAME_SZ 255
-struct dirent { // or maybe something else to not conflict with userspace
-       ino_t          d_ino;       /* inode number */
-       off_t          d_off;       /* offset to the next dirent */
-       unsigned short d_reclen;    /* length of this record */
-       char           d_name[MAX_FILENAME_SZ + 1]; /* filename */
-};
-
 struct iovec {
     void *iov_base;
     size_t iov_len;
@@ -73,7 +66,7 @@ TAILQ_HEAD(file_tailq, file);
 TAILQ_HEAD(io_wb_tailq, io_writeback);
 TAILQ_HEAD(event_poll_tailq, event_poll);
 TAILQ_HEAD(vfsmount_tailq, vfsmount);
-TAILQ_HEAD(fs_type_tailq, fs_type);
+TAILQ_HEAD(fs_type_tailq, fs_type); 
 
 /* Linux's quickstring - saves recomputing the hash and length.  Note the length
  * is the non-null-terminated length, as you'd get from strlen(). (for now) */
@@ -90,7 +83,9 @@ struct qstr {
  * This is meant to be pinning only the 'answer' to a path_lookup, and not the
  * intermediate steps.  The intermediates get pinned due to the existence of
  * their children in memory.  Internally, the VFS will refcnt any item whenever
- * it is in this struct. */
+ * it is in this struct.  The last_sym is needed to pin the dentry (and thus the
+ * inode and char* storage for the symname) for the duration of a lookup.  When
+ * you resolve a pathname, you need to keep its string in memory. */
 #define MAX_SYMLINK_DEPTH 6 // arbitrary.
 struct nameidata {
        struct dentry                           *dentry;                /* dentry of the obj */
@@ -99,8 +94,8 @@ struct nameidata {
        int                                                     flags;                  /* lookup flags */
        int                                                     last_type;              /* type of last component */
        unsigned int                            depth;                  /* search's symlink depth */
-       char                                            *saved_names[MAX_SYMLINK_DEPTH];
        int                                                     intent;                 /* access type for the file */
+       struct dentry                           *last_sym;              /* pins the symname */
 };
 
 /* nameidata lookup flags and access type fields */
@@ -108,28 +103,11 @@ struct nameidata {
 #define LOOKUP_DIRECTORY       0x02    /* last component must be a directory */
 #define LOOKUP_CONTINUE        0x04    /* still filenames to go */
 #define LOOKUP_PARENT          0x08    /* lookup the dir that includes the item */
+/* These are the nd's intent */
 #define LOOKUP_OPEN            0x10    /* intent is to open a file */
 #define LOOKUP_CREATE          0x11    /* create a file if it doesn't exist */
 #define LOOKUP_ACCESS          0x12    /* access / check user permissions */
 
-/* TODO: make our own versions (fucking octal) and put it in fcntl.h */
-/* File access modes for `open' and `fcntl'.  */
-#define O_RDONLY    0   /* Open read-only.  */
-#define O_WRONLY    1   /* Open write-only.  */
-#define O_RDWR      2   /* Open read/write.  */
-#define O_ACCMODE   3
-
-/* Bits OR'd into the second argument to open.  */
-#define O_CREAT        0100 /* not fcntl */
-#define O_EXCL         0200 /* not fcntl */
-#define O_NOCTTY       0400 /* not fcntl */
-#define O_TRUNC       01000 /* not fcntl */
-#define O_APPEND      02000
-#define O_NONBLOCK    04000
-#define O_SYNC       010000
-#define O_FSYNC      O_SYNC
-#define O_ASYNC      020000
-
 /* Every object that has pages, like an inode or the swap (or even direct block
  * devices) has a page_map, tracking which of its pages are currently in memory.
  * It is a map, per object, from index to physical page frame. */
@@ -181,8 +159,13 @@ struct super_block {
        struct inode_tailq                      s_inodes;               /* all inodes */
        struct inode_tailq                      s_dirty_i;              /* dirty inodes */
        struct io_wb_tailq                      s_io_wb;                /* writebacks */
-       struct dentry_slist                     s_anon_d;               /* anonymous dentries */
        struct file_tailq                       s_files;                /* assigned files */
+       struct dentry_tailq                     s_lru_d;                /* unused dentries (in dcache)*/
+       spinlock_t                                      s_lru_lock;
+       struct hashtable                        *s_dcache;              /* dentry cache */
+       spinlock_t                                      s_dcache_lock;
+       struct hashtable                        *s_icache;              /* inode cache */
+       spinlock_t                                      s_icache_lock;
        struct block_device                     *s_bdev;
        TAILQ_ENTRY(super_block)        s_instances;    /* list of sbs of this fs type*/
        char                                            s_name[32];
@@ -191,7 +174,7 @@ struct super_block {
 
 struct super_operations {
        struct inode *(*alloc_inode) (struct super_block *sb);
-       void (*destroy_inode) (struct inode *);         /* dealloc.  might need more */
+       void (*dealloc_inode) (struct inode *);
        void (*read_inode) (struct inode *);
        void (*dirty_inode) (struct inode *);
        void (*write_inode) (struct inode *, bool);
@@ -205,8 +188,11 @@ struct super_operations {
        void (*umount_begin) (struct super_block *);/* called by NFS */
 };
 
-#define FS_I_FILE                              0x01
-#define FS_I_DIR                               0x02
+/* Sets the type of file, IAW the bits in ros/fs.h */
+#define SET_FTYPE(mode, type) ((mode) = ((mode) & ~__S_IFMT) | (type))
+
+/* Will need a bunch of states/flags for an inode.  TBD */
+#define I_STATE_DIRTY                  0x001
 
 /* Inode: represents a specific file */
 struct inode {
@@ -216,8 +202,7 @@ struct inode {
        struct dentry_tailq                     i_dentry;               /* all dentries pointing here*/
        unsigned long                           i_ino;
        struct kref                                     i_kref;
-       int                                                     i_mode;                 /* access mode */
-       unsigned short                          i_type;                 /* file type */
+       int                                                     i_mode;                 /* access mode and file type */
        unsigned int                            i_nlink;                /* hard links */
        uid_t                                           i_uid;
        gid_t                                           i_gid;
@@ -259,14 +244,18 @@ struct inode_operations {
        int (*mknod) (struct inode *, struct dentry *, int, dev_t);
        int (*rename) (struct inode *, struct dentry *,
                       struct inode *, struct dentry *);
-       int (*readlink) (struct dentry *, char *, size_t);
-       int (*follow_link) (struct dentry *, struct nameidata *);
-       int (*put_link) (struct dentry *, struct nameidata *);
+       char *(*readlink) (struct dentry *);
        void (*truncate) (struct inode *);                      /* set i_size before calling */
        int (*permission) (struct inode *, int, struct nameidata *);
 };
 
 #define DNAME_INLINE_LEN 32
+
+/* Dentry flags.  All negatives are also unused. */
+#define DENTRY_USED                    0x01    /* has a kref > 0 */
+#define DENTRY_NEGATIVE                0x02    /* cache of a failed lookup */
+#define DENTRY_DYING           0x04    /* should be freed on release */
+
 /* Dentry: in memory object, corresponding to an element of a path.  E.g. /,
  * usr, bin, and vim are all dentries.  All have inodes.  Vim happens to be a
  * file instead of a directory.
@@ -290,8 +279,6 @@ struct dentry {
        struct vfsmount                         *d_mounted_fs;  /* fs mounted here */
        struct dentry                           *d_parent;
        struct qstr                                     d_name;                 /* pts to iname and holds hash*/
-       SLIST_ENTRY(dentry)                     d_hash;                 /* link for the dcache */
-       struct dentry_slist                     d_bucket;               /* hash bucket of this dentry */
        char                                            d_iname[DNAME_INLINE_LEN];
        void                                            *d_fs_info;
 };
@@ -385,6 +372,7 @@ struct vfsmount {
 /* Per-process structs */
 #define NR_OPEN_FILES_DEFAULT 32
 #define NR_FILE_DESC_DEFAULT 32
+/* keep this in sync with glibc's fd_setsize */
 #define NR_FILE_DESC_MAX 1024
 
 /* Bitmask for file descriptors, big for when we exceed the initial small.  We
@@ -431,10 +419,6 @@ extern struct sb_tailq super_blocks;                       /* list of all sbs */
 extern spinlock_t super_blocks_lock;
 extern struct fs_type_tailq file_systems;              /* lock this if it's dynamic */
 extern struct namespace default_ns;
-// TODO: should have a dentry_htable or something.  we have the structs built
-// in to the dentry right now (linux style).
-extern struct dentry_slist dcache;
-extern spinlock_t dcache_lock;
 
 /* Slab caches for common objects */
 extern struct kmem_cache *dentry_kcache;
@@ -447,6 +431,7 @@ 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);
+int mount_fs(struct fs_type *fs, char *dev_name, char *path, int flags);
 
 /* Superblock functions */
 struct super_block *get_sb(void);
@@ -457,23 +442,43 @@ void init_sb(struct super_block *sb, struct vfsmount *vmnt,
 /* Dentry Functions */
 struct dentry *get_dentry(struct super_block *sb, struct dentry *parent,
                           char *name);
-void dcache_put(struct dentry *dentry);
 void dentry_release(struct kref *kref);
+void __dentry_free(struct dentry *dentry);
+struct dentry *lookup_dentry(char *path, int flags);
+struct dentry *dcache_get(struct super_block *sb, struct dentry *what_i_want);
+void dcache_put(struct super_block *sb, struct dentry *key_val);
+struct dentry *dcache_remove(struct super_block *sb, struct dentry *key);
 
 /* Inode Functions */
 struct inode *get_inode(struct dentry *dentry);
-int create_file(struct inode *dir, struct dentry *dentry, int flags, int mode);
+void load_inode(struct dentry *dentry, unsigned int ino);
+int create_file(struct inode *dir, struct dentry *dentry, int mode);
 int create_dir(struct inode *dir, struct dentry *dentry, int mode);
+int create_symlink(struct inode *dir, struct dentry *dentry,
+                   const char *symname, int mode);
 int check_perms(struct inode *inode, int access_mode);
 void inode_release(struct kref *kref);
+void stat_inode(struct inode *inode, struct kstat *kstat);
+struct inode *icache_get(struct super_block *sb, unsigned int ino);
+void icache_put(struct super_block *sb, struct inode *inode);
+struct inode *icache_remove(struct super_block *sb, unsigned int ino);
 
-/* File functions */
+/* File-ish functions */
 ssize_t generic_file_read(struct file *file, char *buf, size_t count,
                           off_t *offset);
 ssize_t generic_file_write(struct file *file, const char *buf, size_t count,
                            off_t *offset);
+ssize_t generic_dir_read(struct file *file, char *u_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);
+int do_symlink(char *path, const char *symname, int mode);
+int do_link(char *old_path, char *new_path);
+int do_unlink(char *path);
+int do_access(char *path, int mode);
+int do_chmod(char *path, int mode);
+int do_mkdir(char *path, int mode);
+int do_rmdir(char *path);
+struct file *dentry_open(struct dentry *dentry, int flags);
 void file_release(struct kref *kref);
 
 /* Page cache functions */
@@ -485,7 +490,13 @@ int file_load_page(struct file *file, unsigned long index, struct page **pp);
 /* Process-related File management functions */
 struct file *get_file_from_fd(struct files_struct *open_files, int fd);
 struct file *put_file_from_fd(struct files_struct *open_files, int file_desc);
-int insert_file(struct files_struct *open_files, struct file *file);
-void close_all_files(struct files_struct *open_files);
+int insert_file(struct files_struct *open_files, struct file *file, int low_fd);
+void close_all_files(struct files_struct *open_files, bool cloexec);
+void clone_files(struct files_struct *src, struct files_struct *dst);
+int do_chdir(struct fs_struct *fs_env, char *path);
+char *do_getcwd(struct fs_struct *fs_env, char **kfree_this, size_t cwd_l);
+
+/* Debugging */
+int ls_dash_r(char *path);
 
 #endif /* ROS_KERN_VFS_H */