X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/baca54322c66983205edecd2ebb00d997878be50..270869139db617e29a35bb9ded41087bb702f9ac:/lunaix-os/includes/lunaix/fs/api.h?ds=inline diff --git a/lunaix-os/includes/lunaix/fs/api.h b/lunaix-os/includes/lunaix/fs/api.h new file mode 100644 index 0000000..d002774 --- /dev/null +++ b/lunaix-os/includes/lunaix/fs/api.h @@ -0,0 +1,301 @@ +#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); +} + +#endif /* __LUNAIX_FSAPI_H */