#ifndef __LUNAIX_FSAPI_H #define __LUNAIX_FSAPI_H #include #include #include #include #include struct fsapi_vsb_ops { size_t (*read_capacity)(struct v_superblock* vsb); size_t (*read_usage)(struct v_superblock* vsb); void (*init_inode)(struct v_superblock* vsb, struct v_inode* inode); void (*release)(struct v_superblock* vsb); }; static inline struct device* fsapi_blockdev(struct v_superblock* vsb) { if (!(vsb->fs->types & FSTYPE_PSEUDO)) { assert_fs(vsb->dev); } return vsb->dev; } typedef void (*inode_init)(struct v_superblock* vsb, struct v_inode* inode) ; typedef void (*inode_free)(struct v_inode* inode) ; typedef void (*dnode_free)(struct v_dnode* dnode) ; static inline void fsapi_set_inode_initiator(struct v_superblock* vsb, inode_init inode_initiator) { vsb->ops.init_inode = inode_initiator; } static inline size_t fsapi_block_size(struct v_superblock* vsb) { return vsb->blksize; } static inline void fsapi_set_vsb_ops(struct v_superblock* vsb, struct fsapi_vsb_ops* basic_ops) { vsb->ops.read_capacity = basic_ops->read_capacity; vsb->ops.read_usage = basic_ops->read_usage; vsb->ops.release = basic_ops->release; vsb->ops.init_inode = basic_ops->init_inode; } static inline void fsapi_complete_vsb_setup(struct v_superblock* vsb, void* cfs_sb) { assert_fs(vsb->ops.init_inode); assert_fs(vsb->ops.read_capacity); assert_fs(vsb->blksize); assert_fs(vsb->blks); vsb->data = cfs_sb; } static inline void fsapi_begin_vsb_setup(struct v_superblock* vsb, size_t blksz) { assert(!vsb->blks); assert(blksz); vsb->blksize = blksz; vsb->blks = blkbuf_create(block_dev(vsb->dev), blksz); } static inline void fsapi_reset_vsb(struct v_superblock* vsb) { assert(vsb->blks); blkbuf_release(vsb->blks); vsb->blks = NULL; vsb->data = NULL; vsb->blksize = 0; vsb->root->mnt->flags = 0; memset(&vsb->ops, 0, sizeof(vsb->ops)); } static inline bool fsapi_readonly_mount(struct v_superblock* vsb) { return (vsb->root->mnt->flags & MNT_RO); } static inline void fsapi_set_readonly_mount(struct v_superblock* vsb) { vsb->root->mnt->flags |= MNT_RO; } #define fsapi_impl_data(vfs_obj, type) (type*)((vfs_obj)->data) static inline void fsapi_inode_setid(struct v_inode* inode, inode_t i_id, unsigned int blk_addr) { inode->id = i_id; inode->lb_addr = blk_addr; } static inline void fsapi_inode_settype(struct v_inode* inode, unsigned int type) { inode->itype = type; } static inline void fsapi_inode_setsize(struct v_inode* inode, unsigned int fsize) { inode->lb_usage = ICEIL(fsize, inode->sb->blksize); inode->fsize = fsize; } static inline void fsapi_inode_setops(struct v_inode* inode, struct v_inode_ops* ops) { inode->ops = ops; } static inline void fsapi_inode_setfops(struct v_inode* inode, struct v_file_ops* fops) { inode->default_fops = fops; } static inline void fsapi_inode_setdector(struct v_inode* inode, inode_free free_cb) { inode->destruct = free_cb; } static inline void fsapi_inode_complete(struct v_inode* inode, void* data) { assert_fs(inode->ops); assert_fs(inode->default_fops); assert_fs(inode->default_fops); inode->data = data; } static inline void fsapi_inode_settime(struct v_inode* inode, time_t ctime, time_t mtime, time_t atime) { inode->ctime = ctime; inode->mtime = mtime; inode->atime = atime; } static inline void fsapi_dnode_setdector(struct v_dnode* dnode, dnode_free free_cb) { dnode->destruct = free_cb; } static inline struct v_inode* fsapi_dnode_parent(struct v_dnode* dnode) { assert(dnode->parent); return dnode->parent->inode; } static inline void fsapi_dir_report(struct dir_context *dctx, const char *name, const int len, const int dtype) { dctx->read_complete_callback(dctx, name, len, dtype); } /** * @brief Get a block with file-system defined block size * from underlying storage medium at given block id * (block address). Depending on the device attribute, * it may or may not go through the block cache layer. * * @param vsb super-block * @param block_id block address * @return bbuf_t */ static inline bbuf_t fsblock_get(struct v_superblock* vsb, unsigned int block_id) { return blkbuf_take(vsb->blks, block_id); } /** * @brief put the block back into cache, must to pair with * fsblock_get. Otherwise memory leakage will occur. * * @param blkbuf */ static inline void fsblock_put(bbuf_t blkbuf) { return blkbuf_put(blkbuf); } static inline bbuf_t fsblock_take(bbuf_t blk) { return blkbuf_refonce(blk); } static inline unsigned int fsblock_id(bbuf_t blkbuf) { return blkbuf_id(blkbuf); } /** * @brief Mark the block dirty and require scheduling a device * write request to sync it with underlying medium. Lunaix * will do the scheduling when it sees fit. * * @param blkbuf */ static inline void fsblock_dirty(bbuf_t blkbuf) { return blkbuf_dirty(blkbuf); } /** * @brief Manually trigger a sync cycle, regardless the * dirty property. * * @param blkbuf */ static inline void fsblock_sync(bbuf_t blkbuf) { /* XXX delay the sync for better write aggregation scheduled sync event may happened immediately (i.e., blkio queue is empty or nearly empty), any susequent write to the same blkbuf must schedule another write. Which could thrash the disk IO when intensive workload */ return blkbuf_schedule_sync(blkbuf); } static inline bool fsapi_handle_pseudo_dirent(struct v_file* file, struct dir_context* dctx) { if (file->f_pos == 0) { fsapi_dir_report(dctx, ".", 1, vfs_get_dtype(VFS_IFDIR)); return true; } if (file->f_pos == 1) { fsapi_dir_report(dctx, "..", 2, vfs_get_dtype(VFS_IFDIR)); return true; } return false; } static inline struct filesystem* fsapi_fs_declare(const char* name, unsigned int type) { struct filesystem* fs; fs = fsm_new_fs(name, -1); assert_fs(fs); fs->types = type; return fs; } static inline void fsapi_fs_set_mntops(struct filesystem* fs, mntops_mnt mnt, mntops_umnt umnt) { fs->mount = mnt; fs->unmount = umnt; } static inline void fsapi_fs_finalise(struct filesystem* fs) { assert_fs(fs->mount); assert_fs(fs->unmount); fsm_register(fs); } static inline bool fsapi_check_readdir_pos_pseduo(struct v_file* file) { return file->f_pos < 2; } static inline bool fsapi_readdir_pos_entries_at(struct v_file* file, unsigned int pos) { return file->f_pos == pos + 2; } #endif /* __LUNAIX_FSAPI_H */