X-Git-Url: http://akaros.cs.berkeley.edu/gitweb/?p=akaros.git;a=blobdiff_plain;f=kern%2Finclude%2Fvfs.h;h=fcfbef671dbf598e69f2014c2f8a7830c02044a5;hp=d6b4a0dbd3371524cb5fb2bf8a9b9ca2b16ca4b1;hb=85b96613c746c1b264af01ed347e9d17c1f1a88d;hpb=ea421578ed57846e419ae282118b24ff3610298f;ds=sidebyside diff --git a/kern/include/vfs.h b/kern/include/vfs.h index d6b4a0d..fcfbef6 100644 --- a/kern/include/vfs.h +++ b/kern/include/vfs.h @@ -15,10 +15,14 @@ #include #include -#include +#include +#include #include -#include +#include #include +#include +#include +#include /* ghetto preprocessor hacks (since proc includes vfs) */ struct page; @@ -28,8 +32,6 @@ struct vm_region; 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;}; @@ -37,8 +39,6 @@ struct poll_table_struct {int x;}; #include -struct page_map; /* analagous to linux's address_space object */ -struct page_map_operations; struct super_block; struct super_operations; struct dentry; @@ -49,11 +49,7 @@ struct file; struct file_operations; struct fs_type; struct vfsmount; - -struct iovec { - void *iov_base; - size_t iov_len; -}; +struct pipe_inode_info; /* List def's we need */ TAILQ_HEAD(sb_tailq, super_block); @@ -107,84 +103,6 @@ struct nameidata { #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 00000100 /* not fcntl */ -#define O_EXCL 00000200 /* not fcntl */ -#define O_NOCTTY 00000400 /* not fcntl */ -#define O_TRUNC 00001000 /* not fcntl */ -#define O_APPEND 00002000 -#define O_NONBLOCK 00004000 -#define O_SYNC 00010000 -#define O_FSYNC O_SYNC -#define O_ASYNC 00020000 -#define O_DIRECT 00040000 /* Direct disk access. */ -#define O_DIRECTORY 00200000 /* Must be a directory. */ -#define O_NOFOLLOW 00400000 /* Do not follow links. */ -#define O_NOATIME 01000000 /* Do not set atime. */ -#define O_CLOEXEC 02000000 /* Set close_on_exec. */ -#define O_CREAT_FLAGS (O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC) - -/* File creation modes (access controls) */ -#define S_IRWXU 00700 /* user (file owner) has read, write and execute perms */ -#define S_IRUSR 00400 /* user has read permission */ -#define S_IWUSR 00200 /* user has write permission */ -#define S_IXUSR 00100 /* user has execute permission */ -#define S_IRWXG 00070 /* group has read, write and execute permission */ -#define S_IRGRP 00040 /* group has read permission */ -#define S_IWGRP 00020 /* group has write permission */ -#define S_IXGRP 00010 /* group has execute permission */ -#define S_IRWXO 00007 /* others have read, write and execute permission */ -#define S_IROTH 00004 /* others have read permission */ -#define S_IWOTH 00002 /* others have write permission */ -#define S_IXOTH 00001 /* others have execute permission */ - -/* fcntl flags that we support, keep in sync with glibc */ -#define F_DUPFD 0 /* Duplicate file descriptor */ -#define F_GETFD 1 /* Get file descriptor flags */ -#define F_SETFD 2 /* Set file descriptor flags */ -#define F_GETFL 3 /* Get file status flags */ -#define F_SETFL 4 /* Set file status flags */ -/* For F_[GET|SET]FD */ -#define FD_CLOEXEC 1 - -/* 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. */ -struct page_map { - struct inode *pm_host; /* inode of the owner, if any */ - struct radix_tree pm_tree; /* tracks present pages */ - spinlock_t pm_tree_lock; /* spinlock => we can't block */ - unsigned long pm_num_pages; /* how many pages are present */ - struct page_map_operations *pm_op; - unsigned int pm_flags; - /*... and private lists, backing block dev info, other mappings, etc. */ -}; - -/* Operations performed on a page_map. These are usually FS specific, which - * get assigned when the inode is created. - * Will fill these in as they are created/needed/used. */ -struct page_map_operations { - int (*readpage) (struct file *, struct page *); /* read from backing store*/ -/* readpages: read a list of pages - writepage: write from a page to its backing store - writepages: write a list of pages - sync_page: start the IO of already scheduled ops - set_page_dirty: mark the given page dirty - prepare_write: prepare to write (disk backed pages) - commit_write: complete a write (disk backed pages) - bmap: get a logical block number from a file block index - invalidate page: invalidate, part of truncating - release page: prepare to release - direct_io: bypass the page cache */ -}; - /* Superblock: Specific instance of a mounted filesystem. All synchronization * is done with the one spinlock. */ @@ -205,8 +123,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]; @@ -229,9 +152,11 @@ struct super_operations { void (*umount_begin) (struct super_block *);/* called by NFS */ }; -#define FS_I_FILE 0x01 -#define FS_I_DIR 0x02 -#define FS_I_SYMLINK 0x03 +/* 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 { @@ -241,8 +166,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; @@ -257,7 +181,7 @@ struct inode { struct inode_operations *i_op; struct file_operations *i_fop; struct super_block *i_sb; - struct page_map *i_mapping; /* usually points to i_data */ + struct page_map *i_mapping; /* usually points to i_pm */ struct page_map i_pm; /* this inode's page cache */ union { struct pipe_inode_info *i_pipe; @@ -290,6 +214,12 @@ struct inode_operations { }; #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. @@ -313,8 +243,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; }; @@ -344,13 +272,13 @@ struct file { struct kref f_kref; unsigned int f_flags; /* O_APPEND, etc */ int f_mode; /* O_RDONLY, etc */ - off_t f_pos; /* offset / file pointer */ + off64_t f_pos; /* offset / file pointer */ unsigned int f_uid; unsigned int f_gid; int f_error; struct event_poll_tailq f_ep_links; spinlock_t f_ep_lock; - void *f_fs_info; /* tty driver hook */ + void *f_privdata; /* tty/socket driver hook */ struct page_map *f_mapping; /* page cache mapping */ /* Ghetto appserver support */ @@ -360,9 +288,9 @@ struct file { }; struct file_operations { - off_t (*llseek) (struct file *, off_t, int); - ssize_t (*read) (struct file *, char *, size_t, off_t *); - ssize_t (*write) (struct file *, const char *, size_t, off_t *); + int (*llseek) (struct file *, off64_t, off64_t *, int); + ssize_t (*read) (struct file *, char *, size_t, off64_t *); + ssize_t (*write) (struct file *, const char *, size_t, off64_t *); int (*readdir) (struct file *, struct dirent *); int (*mmap) (struct file *, struct vm_region *); int (*open) (struct inode *, struct file *); @@ -371,10 +299,11 @@ struct file_operations { int (*fsync) (struct file *, struct dentry *, int); unsigned int (*poll) (struct file *, struct poll_table_struct *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, - off_t *); + off64_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, - off_t *); - ssize_t (*sendpage) (struct file *, struct page *, int, size_t, off_t, int); + off64_t *); + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, off64_t, + int); int (*check_flags) (int flags); /* most FS's ignore this */ }; @@ -405,36 +334,63 @@ struct vfsmount { struct namespace *mnt_namespace; }; +struct pipe_inode_info +{ + char *p_buf; + size_t p_rd_off; + size_t p_wr_off; + unsigned int p_nr_readers; + unsigned int p_nr_writers; + struct cond_var p_cv; +}; + /* 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 +/* this is not in sync with glibc, sysdeps/ros/bits/typesizes.h */ +#define NR_FILE_DESC_MAX (512 * 1024) /* Bitmask for file descriptors, big for when we exceed the initial small. We * could just use the fd_array to check for openness instead of the bitmask, * but eventually we might want to use the bitmasks for other things (like * which files are close_on_exec. */ -struct fd_set { + +typedef struct fd_set { uint8_t fds_bits[BYTES_FOR_BITMASK(NR_FILE_DESC_MAX)]; -}; +} fd_set; + + struct small_fd_set { uint8_t fds_bits[BYTES_FOR_BITMASK(NR_FILE_DESC_DEFAULT)]; }; +/* Helper macros to manage fd_sets */ +#define FD_SET(n, p) ((p)->fds_bits[(n)/8] |= (1 << ((n) & 7))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/8] &= ~(1 << ((n) & 7))) +#define FD_ISSET(n,p) ((p)->fds_bits[(n)/8] & (1 << ((n) & 7))) +#define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p))) + +/* Describes an open file. We need this, since the FD flags are supposed to be + * per file descriptor, not per file (like the file status flags). */ +struct file_desc { + struct file *fd_file; + unsigned int fd_flags; +}; + /* All open files for a process */ struct files_struct { spinlock_t lock; + bool closed; int max_files; /* max files ptd to by fd */ int max_fdset; /* max of the current fd_set */ int next_fd; /* next number available */ - struct file **fd; /* initially pts to fd_array */ + struct file_desc *fd; /* initially pts to fd_array */ struct fd_set *open_fds; /* init, pts to open_fds_init */ struct small_fd_set open_fds_init; - struct file *fd_array[NR_OPEN_FILES_DEFAULT]; + struct file_desc fd_array[NR_OPEN_FILES_DEFAULT]; }; -/* Process specific filesysten info */ +/* Process specific filesystem info */ struct fs_struct { spinlock_t lock; int umask; @@ -455,10 +411,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; @@ -471,6 +423,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); @@ -479,14 +432,23 @@ void init_sb(struct super_block *sb, struct vfsmount *vmnt, void *d_fs_info); /* Dentry Functions */ +struct dentry *get_dentry_with_ops(struct super_block *sb, + struct dentry *parent, char *name, + struct dentry_operations *d_op); 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); +void dcache_prune(struct super_block *sb, bool negative_only); +int generic_dentry_hash(struct dentry *dentry, struct qstr *qstr); /* Inode Functions */ struct inode *get_inode(struct dentry *dentry); +void load_inode(struct dentry *dentry, unsigned long 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, @@ -494,37 +456,51 @@ int create_symlink(struct inode *dir, struct dentry *dentry, 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 long ino); +void icache_put(struct super_block *sb, struct inode *inode); +struct inode *icache_remove(struct super_block *sb, unsigned long ino); /* File-ish functions */ ssize_t generic_file_read(struct file *file, char *buf, size_t count, - off_t *offset); + off64_t *offset); ssize_t generic_file_write(struct file *file, const char *buf, size_t count, - off_t *offset); + off64_t *offset); ssize_t generic_dir_read(struct file *file, char *u_buf, size_t count, - off_t *offset); + off64_t *offset); +struct file *alloc_file(void); struct file *do_file_open(char *path, int flags, int mode); 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_file_access(char *path, int mode); +int do_access(char *path, int mode); +int do_file_chmod(struct file *file, int mode); +int do_mkdir(char *path, int mode); +int do_rmdir(char *path); +int do_pipe(struct file **pipe_files, int flags); +int do_rename(char *old_path, char *new_path); +int do_truncate(struct inode *inode, off64_t len); struct file *dentry_open(struct dentry *dentry, int flags); void file_release(struct kref *kref); -/* Page cache functions */ -struct page *pm_find_page(struct page_map *pm, unsigned long index); -int pm_insert_page(struct page_map *pm, unsigned long index, struct page *page); -int pm_remove_page(struct page_map *pm, struct page *page); -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); +int insert_file(struct files_struct *open_files, struct file *file, int low_fd, + bool must, bool cloexec); 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); +int do_fchdir(struct fs_struct *fs_env, struct file *file); +char *do_getcwd(struct fs_struct *fs_env, char **kfree_this, size_t cwd_l); /* Debugging */ +void print_kstat(struct kstat *kstat); int ls_dash_r(char *path); +extern struct inode_operations dummy_i_op; +extern struct dentry_operations dummy_d_op; + +int put_fd(struct files_struct *open_files, int file_desc); +int get_fd(struct files_struct *open_files, int low_fd, int cloexec); +int claim_fd(struct files_struct *open_files, int file_desc); #endif /* ROS_KERN_VFS_H */