X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/96cf56ea15a22b8b362aac6c3ab202d2608e9151..0f73e6cc9945f9b4a074bb62b9708d1751fa3723:/lunaix-os/includes/lunaix/fs.h?ds=sidebyside diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 099d47e..d599023 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -6,25 +6,42 @@ #include #include #include +#include #include #include #include -#include #include + #include +#include + #define VFS_NAME_MAXLEN 128 #define VFS_MAX_FD 32 -#define VFS_IFDIR 0x1 -#define VFS_IFFILE 0x2 -#define VFS_IFSEQDEV 0x4 -#define VFS_IFVOLDEV 0x8 -#define VFS_IFSYMLINK 0x16 +#define VFS_IFDIR F_DIR +#define VFS_IFFILE F_FILE +#define VFS_IFDEV (F_DEV | F_FILE) +#define VFS_IFSEQDEV (F_SEQDEV | F_FILE) +#define VFS_IFVOLDEV (F_VOLDEV | F_FILE) +#define VFS_IFSYMLINK (F_SYMLINK | F_FILE) + +#define VFS_DEVFILE(type) ((type) & F_DEV) +#define VFS_DEVTYPE(type) ((type) & ((F_SEQDEV | F_VOLDEV) ^ F_DEV)) +// Walk, mkdir if component encountered is non-exists. #define VFS_WALK_MKPARENT 0x1 + +// Walk, relative to current FS. #define VFS_WALK_FSRELATIVE 0x2 + +/* + Terminate the walk on the immediate parent, + name of child (last component) is returned through `component` +*/ #define VFS_WALK_PARENT 0x4 + +// Do not follow the symbolic link #define VFS_WALK_NOFOLLOW 0x8 #define VFS_HASHTABLE_BITS 10 @@ -36,15 +53,15 @@ #define FSTYPE_ROFS 0x1 -#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno) -#define DO_STATUS_OR_RETURN(errno) ({ errno < 0 ? DO_STATUS(errno) : errno; }) - #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD) +#define EXPORT_FILE_SYSTEM(fs_id, init_fn) \ + export_ldga_el(fs, fs_id, ptr_t, init_fn) + #define VFS_VALID_CHAR(chr) \ (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') || \ ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' || \ - (chr) == '-') + (chr) == '-' || (chr) == ':') #define unlock_inode(inode) mutex_unlock(&inode->lock) #define lock_inode(inode) \ @@ -60,7 +77,7 @@ lru_use_one(dnode_lru, &dnode->lru); \ }) -typedef uint32_t inode_t; +typedef u32_t inode_t; struct v_dnode; struct v_inode; @@ -83,7 +100,7 @@ struct filesystem { struct hlist_node fs_list; struct hstr fs_name; - uint32_t types; + u32_t types; int fs_id; int (*mount)(struct v_superblock* vsb, struct v_dnode* mount_point); int (*unmount)(struct v_superblock* vsb); @@ -95,12 +112,13 @@ struct v_superblock struct device* dev; struct v_dnode* root; struct filesystem* fs; - uint32_t iobuf_size; struct hbucket* i_cache; + void* data; + size_t blksize; struct { - uint32_t (*read_capacity)(struct v_superblock* vsb); - uint32_t (*read_usage)(struct v_superblock* vsb); + u32_t (*read_capacity)(struct v_superblock* vsb); + u32_t (*read_usage)(struct v_superblock* vsb); void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode); } ops; }; @@ -119,6 +137,16 @@ struct v_file_ops { int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos); int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos); + + // for operatiosn {write|read}_page, following are true: + // + `len` always equals to PG_SIZE + // + `fpos` always PG_SIZE aligned. + // These additional operations allow underlying fs to use more specialized + // and optimized code. + + int (*write_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos); + int (*read_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos); + int (*readdir)(struct v_file* file, struct dir_context* dctx); int (*seek)(struct v_inode* inode, size_t offset); // optional int (*close)(struct v_file* file); @@ -161,7 +189,7 @@ struct v_file struct v_inode* inode; struct v_dnode* dnode; struct llist_header* f_list; - uint32_t f_pos; + u32_t f_pos; atomic_ulong ref_count; struct v_file_ops* ops; // for caching }; @@ -172,27 +200,43 @@ struct v_fd int flags; }; +// [v_inode::aka_nodes] +// how do we invalidate corresponding v_dnodes given the v_inode? +/* + Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow + info of every process being accessible via file system. Each process's + creation will result a creation of a directory under the root of task fs + with it's pid as name. But that dir must delete when process is killed, and + such deletion does not mediated by vfs itself, so there is a need of cache + syncing. + And this is also the case of all ramfs where argumentation to file tree is + performed by third party. +*/ + struct v_inode { inode_t id; mutex_t lock; - uint32_t itype; + u32_t itype; time_t ctime; time_t mtime; time_t atime; lba_t lb_addr; - uint32_t open_count; - uint32_t link_count; - uint32_t lb_usage; - uint32_t fsize; + u32_t open_count; + u32_t link_count; + u32_t lb_usage; + u32_t fsize; + void* data; // 允许底层FS绑定他的一些专有数据 + struct llist_header aka_dnodes; struct llist_header xattrs; struct v_superblock* sb; struct hlist_node hash_list; struct lru_node lru; struct pcache* pg_cache; - void* data; // 允许底层FS绑定他的一些专有数据 struct v_inode_ops* ops; struct v_file_ops* default_fops; + + void (*destruct)(struct v_inode* inode); }; struct v_mount @@ -204,7 +248,7 @@ struct v_mount struct v_mount* parent; struct v_dnode* mnt_point; struct v_superblock* super_block; - uint32_t busy_counter; + u32_t busy_counter; int flags; }; @@ -216,6 +260,7 @@ struct v_dnode struct v_inode* inode; struct v_dnode* parent; struct hlist_node hash_list; + struct llist_header aka_list; struct llist_header children; struct llist_header siblings; struct v_superblock* super_block; @@ -236,8 +281,8 @@ struct pcache struct btrie tree; struct llist_header pages; struct llist_header dirty; - uint32_t n_dirty; - uint32_t n_pages; + u32_t n_dirty; + u32_t n_pages; }; struct pcache_pg @@ -247,10 +292,11 @@ struct pcache_pg struct lru_node lru; struct pcache* holder; void* pg; - uint32_t flags; - uint32_t fpos; + u32_t flags; + u32_t fpos; + u32_t len; }; -/* --- file system manager --- */ + void fsm_init(); @@ -269,6 +315,9 @@ fsm_get(const char* fs_name); void vfs_init(); +void +vfs_export_attributes(); + struct v_dnode* vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str); @@ -318,9 +367,15 @@ vfs_mkdir(const char* path, struct v_dnode** dentry); int vfs_open(struct v_dnode* dnode, struct v_file** file); +int +vfs_pclose(struct v_file* file, pid_t pid); + int vfs_close(struct v_file* file); +void +vfs_free_fd(struct v_fd* fd); + int vfs_fsync(struct v_file* file); @@ -340,7 +395,7 @@ void vfs_d_free(struct v_dnode* dnode); struct v_inode* -vfs_i_find(struct v_superblock* sb, uint32_t i_id); +vfs_i_find(struct v_superblock* sb, u32_t i_id); void vfs_i_addhash(struct v_inode* inode); @@ -357,6 +412,21 @@ vfs_dup_fd(struct v_fd* old, struct v_fd** new); int vfs_getfd(int fd, struct v_fd** fd_s); +int +vfs_get_dtype(int itype); + +void +vfs_ref_dnode(struct v_dnode* dnode); + +void +vfs_ref_file(struct v_file* file); + +void +vfs_unref_dnode(struct v_dnode* dnode); + +int +vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth); + void pcache_init(struct pcache* pcache); @@ -364,22 +434,22 @@ void pcache_release_page(struct pcache* pcache, struct pcache_pg* page); struct pcache_pg* -pcache_new_page(struct pcache* pcache, uint32_t index); +pcache_new_page(struct pcache* pcache, u32_t index); void pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg); -struct pcache_pg* +int pcache_get_page(struct pcache* pcache, - uint32_t index, - uint32_t* offset, + u32_t index, + u32_t* offset, struct pcache_pg** page); int -pcache_write(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos); +pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos); int -pcache_read(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos); +pcache_read(struct v_inode* inode, void* data, u32_t len, u32_t fpos); void pcache_release(struct pcache* pcache);