From 31dc307d0baaa6f2d0d2dde284f9352c820d2e43 Mon Sep 17 00:00:00 2001 From: 1iaan Date: Sun, 22 Feb 2026 14:46:17 +0000 Subject: [PATCH] =?UTF-8?q?zvfs:=20=E9=87=8D=E6=9E=84=E6=A0=B8=E5=BF=83?= =?UTF-8?q?=E8=AF=BB=E5=86=99=E9=80=BB=E8=BE=91=E5=B9=B6=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20POSIX=20hook=EF=BC=9B=E5=BC=95=E5=85=A5=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE=E4=B8=8E=E4=BC=AA=20fd=EF=BC=9B?= =?UTF-8?q?=E5=88=86=E7=A6=BB=E5=88=9B=E5=BB=BA=E3=80=81=E6=89=93=E5=BC=80?= =?UTF-8?q?=E3=80=81=E5=85=B3=E9=97=AD=E3=80=81=E5=88=A0=E9=99=A4=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + Makefile | 8 +- README.md | 295 ++++++++++---- func_test.c | 40 ++ success-case/.gitkeep | 0 success-case/Makefile | 18 - success-case/zvfs.c | 869 ------------------------------------------ test_so/posix.c | 79 ---- test_so/test_so.c | 29 -- zv2404fs.c | 664 -------------------------------- zvfs.c | 553 +++++++++++++++++++++++++++ zvfs.h | 91 +++++ zvfs.old/Makefile | 16 + zvfs.old/zvfs.c | 442 +++++++++++++++++++++ zvfs.old/zvfs.json | 17 + zvfs.old/zvfs.old.c | 176 +++++++++ zvfs_hook.c | 359 +++++++++++++++++ 17 files changed, 1931 insertions(+), 1727 deletions(-) create mode 100644 .gitignore create mode 100644 func_test.c delete mode 100644 success-case/.gitkeep delete mode 100644 success-case/Makefile delete mode 100644 success-case/zvfs.c delete mode 100755 test_so/posix.c delete mode 100755 test_so/test_so.c delete mode 100755 zv2404fs.c create mode 100755 zvfs.c create mode 100644 zvfs.h create mode 100755 zvfs.old/Makefile create mode 100755 zvfs.old/zvfs.c create mode 100644 zvfs.old/zvfs.json create mode 100644 zvfs.old/zvfs.old.c create mode 100644 zvfs_hook.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db62a4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +*.so \ No newline at end of file diff --git a/Makefile b/Makefile index e721362..a5ecee8 100755 --- a/Makefile +++ b/Makefile @@ -1,14 +1,16 @@ # SPDX-License-Identifier: BSD-3-Clause +# Copyright (C) 2017 Intel Corporation +# All rights reserved. # -SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../spdk) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk APP = zvfs -C_SRCS := zv2404fs.c +C_SRCS := zvfs.c SPDK_LIB_LIST = $(ALL_MODULES_LIST) event event_bdev -include $(SPDK_ROOT_DIR)/mk/spdk.app.mk +include $(SPDK_ROOT_DIR)/mk/spdk.app.mk \ No newline at end of file diff --git a/README.md b/README.md index c2172dd..089825b 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,257 @@ -# 5.3.1 Zv2404fs - - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin http://gitlab.0voice.com/2404_vip/5.3.1-zv2404fs.git -git branch -M main -git push -uf origin main +## usage +```shell ``` -## Integrate with your tools -- [ ] [Set up project integrations](http://gitlab.0voice.com/2404_vip/5.3.1-zv2404fs/-/settings/integrations) +## SPDK +1. blob_store: blob仓库,管理多个blob对象。 +2. blob: 存储对象,逻辑上连续,物理上不一定连续。相当于文件。 +3. cluster: 分配单元,一个 blob 可以由多个 cluster 构成,扩容即分配新的 cluster。相当于文件系统的block group。 +4. page: IO单元,一个 cluster 等于多个 page。 -## Collaborate with your team +文件系统 -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) +## 架构设计 +```scss +| 应用程序 + | (POSIX API: open/read/write/close) +| LD_PRELOAD 拦截层 + | (简单路径判断和转发到zvfs) +| zvfs 文件系统层 + | (blob 操作) +| SPDK Blobstore +| 块设备 (Malloc0) +``` -## Test and Deploy +### 磁盘布局 +```scss +BlobStore: +|—— Super Blob(元数据,使用SPDK的Super Blob锚定) + |——超级块 + |——目录项/目录日志 +|—— Blob 1 (文件A...) +|—— Blob 2 (文件B...) +|—— Blob N (文件C...) +``` -Use the built-in continuous integration in GitLab. -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) +### 数据结构 +#### Super Blob(元数据) +```scss +[超级块] +- magic_number: 0x5A563146 (ZV1F) +- version: 1 -*** +[目录项] +- filename[256]: 文件名 +- blob_id: 对应的数据blob ID +- file_size: 文件实际大小(字节) +- allocated_clusters: 已分配的cluster数量 +- is_valid: 标记是否有效(用于删除) +``` -# Editing this README +```c +/* 目录项(内存中的目录) */ +typedef struct { + char filename[256]; + spdk_blob_id blob_id; + uint64_t file_size; // 文件逻辑大小(字节) + uint32_t allocated_clusters; // 已分配的cluster数量 + bool is_valid; // false 表示已删除 + int32_t open_count; // 打开的文件句柄数量 +} zvfs_dirent_t; -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. +/* 文件系统全局结构 */ +typedef struct zvfs { + struct spdk_blob_store *bs; + struct spdk_io_channel *channel; + struct spdk_blob *super_blob; // 承载目录日志的blob + uint64_t io_unit_size; // page大小,单位字节 -## Suggestions for a good README -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. + /* 目录 */ + zvfs_dirent_t *dirents; // 目录项数组 #define ZVFS_MAX_FILES 1024 + uint32_t dirent_count; // 当前有效项数 -## Name -Choose a self-explaining name for your project. + /* 伪FD表 */ + struct zvfs_file *fd_table[ZVFS_MAX_FD]; // // e.g., #define ZVFS_MAX_FD 64 + int fd_base; // 伪FD起始值,如10000 + int openfd_count; -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. + /* 元数据 */ + uint32_t magic; // 0x5A563146 (ZV1F) + uint32_t version; // 1 +} zvfs_t; -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. +/* 打开的文件句柄 */ +typedef struct zvfs_file { + zvfs_t *fs; + struct spdk_blob *blob; + zvfs_dirent_t *dirent; // 指回目录项 file_size/allocated_clusters + + uint64_t current_offset; // 当前读写位置 + int flags; // O_RDONLY / O_RDWR / O_CREAT 等 + int pseudo_fd; -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. + /* 临时DMA缓冲区(可选:每个file一个,避免每次malloc) */ + void *dma_buf; + uint64_t dma_buf_size; +} zvfs_file_t; +``` -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. +### 工作流程 +#### mount +hook POSIX API没有很好的调用时机,单线程目前采用懒加载。 +```scss +1. [创建块设备] + - spdk_bdev_create_bs_dev_ext +2. [初始化文件系统] + - spdk_bs_init 或者 spdk_bs_load(已有数据时) + - spdk_bs_get_io_unit_size 获取io单元大小(page) + - spdk_bs_alloc_io_channel 分配blobstore的读写入口 +3. [读取元数据] + - spdk_bs_get_super_blob 获取 Super Blob ID + - spdk_bs_open_blob 打开 Super Blob + - 读取超级块,校验 magic + - 读取目录项数组,加载到内存 dirents +4. [创建zvfs_t结构体] + - 创建 zvfs_t 结构体 + - 填充 bs/channel/super_blob/dirents 等字段 +``` +#### open +##### O_RDONLY / O_RDWR +```scss +1. [文件名查找] + - 遍历 dirents,匹配 filename 且 is_valid=true + - 找不到返回 -ENOENT +2. [打开blob] + - spdk_bs_open_blob(dirent->blob_id) + - dirent->open_count++ + - fs->openfd_count++ +3. [分配文件句柄] + - 创建 zvfs_file_t,dirent 指针指向目录项 + - 分配伪FD,写入 fd_table +5. [返回伪FD] +``` -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. +##### O_CREAT +```scss +1. [文件名查找] + - 遍历 dirents,若 filename 已存在且 is_valid=true,返回 -EEXIST + - 找一个 is_valid=false 的空槽位;没有空槽则追加(dirent_count < max_files) +2. [创建blob] + - spdk_bs_create_blob → 得到 blob_id + - spdk_bs_open_blob → 得到 blob 句柄 + - spdk_blob_resize 初始分配空间 + - spdk_blob_sync_md 持久化 cluster 分配 +3. [写目录] + - 填充 filename/blob_id/file_size=0/is_valid=true + - dirent->open_count = 1 +4. [创建文件句柄] + - 创建 zvfs_file_t + - 分配伪FD,写入 fd_table +5. [返回伪FD] -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. +``` +> 说明:目录变更只写内存,unmount 时统一持久化。 -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. +### read +读写都以字节为单位,offset / count 单位为字节;根据 io_unit_size 做对齐计算。 -## Contributing -State if you are open to contributions and what your requirements are for accepting them. +```scss +1. [参数] + - fd + - buffer + - count + - offset(隐含) +2. [边界检查] + - 实际可读 = min(count, dirent->file_size - current_offset) + - 实际可读为0则返回0 +3. [计算Blob位置] + - start_page = current_offset / io_unit_size + - page_offset = current_offset % io_unit_size + - num_pages = (page_offset + 实际可读 + io_unit_size - 1) / io_unit_size +4. [DMA读取] + - 非对齐读(offset != 0 || count 不是整页) + - 需要DMA临时缓冲区(spdk_dma_zmalloc) + - spdk_blob_io_read(blob, channel, dma_buffer, start_page, num_pages, ...) + - 从 dma_buffer + page_offset 拷贝到用户 buffer + - 对齐 + - 仍使用DMA缓冲区执行读取,再拷贝到用户buffer +5. [更新offset] + - current_offset += 实际可读 +6. [返回实际读取字节数] +``` +> 说明:SPDK需要DMA可用的内存,应用提供的用户缓冲区通常不满足要求。即便对齐也不能直接提交给spdk_blob_io_*,应使用DMA缓冲作为跳板;未来通过注册内存池可优化直传。 -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. +### write +```scss +1. [参数] + - fd + - buffer + - count + - offset(隐含) +2. [检查空间是否足够] + - 需要大小 = current_offset + count + - 若超过 allocated_clusters 对应容量: + - spdk_blob_resize 扩容 + - spdk_blob_sync_md + - 更新 dirent->allocated_clusters +3. [计算写入位置] + - start_page / page_offset / num_pages(同read) +4. [DMA写入] + - 非对齐写(offset != 0 || count 不是整页) + - 读取涉及的首尾page到DMA临时缓冲区 + - 修改对应位置的数据 + - 写回:spdk_blob_io_write(blob, channel, dma_buffer, start_page, num_pages, ...) + - 对齐 + - 仍通过DMA缓冲区提交写入 +5. [更新状态] + - current_offset += count + - dirent->file_size = max(dirent->file_size, current_offset) +6. [返回写入字节数] +``` -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. +### close +```scss +1. [关闭Blob] + - spdk_blob_close(file->blob) + - dirent->open_count-- + - fs->openfd_count++ + - 若 open_count == 0 且 is_valid == false(已unlink):spdk_bs_delete_blob, 清空dirent + - 若 openfd_count == 0 则 unmount +2. [释放缓冲区] + - 释放 dma_buf + - 清除 fd_table[pseudo_fd] + - free(zvfs_file_t) +3. [返回0] +``` +### unlink +```scss +1. [查找目录项] + - 遍历 dirents,匹配 filename 且 is_valid=true + - 找不到返回 -ENOENT +2. [标记删除] + - dirent->is_valid = false +3. [判断是否立即删除] + - open_count == 0:spdk_bs_delete_blob,清空该槽位 + - open_count > 0:延迟,最后一个 close 负责删除 +4. [返回0] +``` -## License -For open source projects, say how it is licensed. +### unmount +```scss +1. [关闭channel] + - spdk_bs_free_io_channel +2. [关闭BlobStore] + - spdk_bs_unload +3. [释放FS] + - free(fs) +``` -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. + +### 其他方案 +如果不使用`LD_PRELOAD`hook,可以使用FUSE。\ +FUSE是一种内核文件系统程序,挂载在文件目录上,对这个目录的访问,会使用这个文件系统程序。\ +文件系统程序会将请求转发给应用层程序,这里的应用层程序可以是SPDK。这样就不用管其他的操作。 diff --git a/func_test.c b/func_test.c new file mode 100644 index 0000000..018b455 --- /dev/null +++ b/func_test.c @@ -0,0 +1,40 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + const char *path = "/zvfs/func_test.dat"; + if (argc > 2 && strcmp(argv[1], "-f") == 0) path = argv[2]; + setenv("ZVFS_ROOT", "/zvfs", 0); + + printf("open: %s\n", path); + int fd = open(path, O_CREAT|O_RDWR, 0644); + if (fd < 0) { perror("open"); return 1; } + + const char *msg = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + ssize_t w = write(fd, msg, strlen(msg)); + if (w < 0) { perror("write"); return 2; } + printf("write: %zd\n", w); + + /* Rewind by closing and reopening for read */ + close(fd); + fd = open(path, O_RDONLY); + if (fd < 0) { perror("open R"); return 3; } + + char buf[256]; memset(buf, 0, sizeof(buf)); + ssize_t r = read(fd, buf, sizeof(buf)); + if (r < 0) { perror("read"); return 4; } + printf("read: %zd bytes: %.*s\n", r, (int)r, buf); + close(fd); + + if (unlink(path) != 0) { perror("unlink"); return 5; } + printf("unlink: ok\n"); + return 0; +} diff --git a/success-case/.gitkeep b/success-case/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/success-case/Makefile b/success-case/Makefile deleted file mode 100644 index 4f7d0d3..0000000 --- a/success-case/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright (c) Intel Corporation. -# All rights reserved. -# - -SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..) -include $(SPDK_ROOT_DIR)/mk/spdk.common.mk - -SO_VER := 1 -SO_MINOR := 2 -SO_SUFFIX := $(SO_VER).$(SO_MINOR) - -LIBNAME = zvfs -C_SRCS = zvfs.c - -SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_zvfs.map) - -include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk diff --git a/success-case/zvfs.c b/success-case/zvfs.c deleted file mode 100644 index 9819b54..0000000 --- a/success-case/zvfs.c +++ /dev/null @@ -1,869 +0,0 @@ - - -#include -#include -#include -#include -#include -#include - -#include -#include - - - -#define FILENAME_LENGTH 1024 - -typedef struct zfs_ctx_s { - - struct spdk_bs_dev *bsdev; - struct spdk_blob_store *bs; - spdk_blob_id blobid; - struct spdk_blob *blob; - struct spdk_io_channel *channel; - - uint8_t *write_buff; - uint8_t *read_buff; - - uint64_t io_unit_size; - bool finished; - -} zfs_ctx_t; - -typedef struct zvfs_file_s { - - char filename[FILENAME_LENGTH]; - - struct spdk_blob *blob; - spdk_blob_id blobid; - - struct zvfs_s *fs; - - uint8_t *write_buff; // - uint8_t *read_buff; // - - bool finished; - -} zvfs_file_t; - - -typedef struct zvfs_file_operation_s { - int (*open)(void); - int (*write)(void); - int (*read)(void); - int (*close)(void); -} zvfs_file_operation_t; - - -typedef struct zvfs_s { - - struct spdk_bs_dev *bsdev; - struct spdk_blob_store *bs; - struct spdk_io_channel *channel; - uint64_t io_unit_size; - - bool finished; - -} zvfs_t; - - -typedef struct zvfs_operation_s { - int (*load)(zvfs_t *fs); - int (*unload)(zvfs_t *fs); -} zvfs_operation_t; - - - -struct spdk_thread *global_thread; -zvfs_t *fs; - - -static void zvfs_spdk_bdev_complete(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, - void *event_ctx) { - - printf("blobstore create success\n"); - -} - -static void zvfs_spdk_bs_unload_complete(void *arg, int bserrno) { - - zvfs_t *ctx = arg; -#if 0 - if (ctx->read_buff) { - spdk_free(ctx->read_buff); - ctx->read_buff = NULL; - } - if (ctx->write_buff) { - spdk_free(ctx->write_buff); - ctx->write_buff = NULL; - } -#endif - - ctx->finished = true; -} - - -static void zvfs_spdk_bs_destroy_complete(void *arg, int bserrno) { - - zvfs_t *ctx = arg; - if (ctx->bs) { - if (ctx->channel) { - spdk_bs_free_io_channel(ctx->channel); - } - spdk_bs_unload(ctx->bs, zvfs_spdk_bs_unload_complete, ctx); - } - -} - - -static void zvfs_spdk_blob_close_complete(void *arg, int bserrno) { - - zvfs_file_t *file = arg; - - -#if 1 - if (file->read_buff) { - spdk_free(file->read_buff); - file->read_buff = NULL; - } - if (file->write_buff) { - spdk_free(file->write_buff); - file->write_buff = NULL; - } -#endif - file->finished = true; - -} - - -static void zvfs_spdk_blob_read_complete(void *arg, int bserrno) { - - zvfs_file_t *file = arg; - - //SPDK_NOTICELOG("read : %s\n", file->read_buff); -#if 0 - int match_res = memcmp(file->write_buff, file->read_buff, - file->fs->io_unit_size); - if (!match_res) { - SPDK_NOTICELOG("read SUCCESS and data matches!\n"); - } -#endif - - file->finished = true; - -} - - -static void zvfs_spdk_blob_write_complete(void *arg, int bserrno) { - - zvfs_file_t *file = arg; - - - file->finished = true; - //SPDK_NOTICELOG("ctx->finished = true\n"); - -} - - -static void zvfs_spdk_blob_sync_complete(void *arg, int bserrno) { - - zvfs_file_t *file = arg; -#if 1 - file->write_buff = spdk_malloc(file->fs->io_unit_size, 0x1000, NULL, - SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (file->write_buff == NULL) { - return ; - } - - file->read_buff = spdk_malloc(file->fs->io_unit_size, 0x1000, NULL, - SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (file->read_buff == NULL) { - return ; - } -#endif - - file->finished = true; - - //SPDK_NOTICELOG("ctx->finished = true\n"); - -} - - - -static void zvfs_spdk_bdev_resize_blob_complete(void *arg, int bserrno) { - - zvfs_file_t *file = arg; - - spdk_blob_sync_md(file->blob, zvfs_spdk_blob_sync_complete, file); - -} - - - -static void zvfs_spdk_bdev_open_blob_complete(void *arg, struct spdk_blob *blb, int bserrno) { - - zvfs_file_t *file = arg; - file->blob = blb; - - uint64_t numfreed = spdk_bs_free_cluster_count(file->fs->bs); - - //SPDK_NOTICELOG("numfreed: %"PRIu64"\n", numfreed); - spdk_blob_resize(blb, numfreed, zvfs_spdk_bdev_resize_blob_complete, file); - -} - -// create -// open - -static void zvfs_spdk_bdev_create_blob_complete(void *arg, spdk_blob_id blobid, int bserrno) { - - //SPDK_NOTICELOG("spdk_blob_id: %"PRIu64"\n", blobid); - - zvfs_file_t *file = arg; - - file->blobid = blobid; - -#if 1 - spdk_bs_open_blob(file->fs->bs, blobid, zvfs_spdk_bdev_open_blob_complete, file); -#endif -} - - - -static void zvfs_spdk_bdev_init_complete(void *arg, struct spdk_blob_store *bs, - int bserrno) { - - - zvfs_t *ctx = arg; - ctx->bs = bs; - ctx->io_unit_size = spdk_bs_get_io_unit_size(bs); - -#if 1 - ctx->channel = spdk_bs_alloc_io_channel(ctx->bs); - if (ctx->channel == NULL) { - return ; - } - -#endif - - //SPDK_NOTICELOG("io_unit_size --> %" PRIu64 "\n", ctx->io_unit_size); - - ctx->finished = true; -} - - -// zvfs -static void zvfs_do_load(void *arg) { - - zvfs_t *ctx = arg; - struct spdk_bs_dev *bsdev = NULL; - - const char * bdev_name = "Malloc0"; - int res = spdk_bdev_create_bs_dev_ext(bdev_name, zvfs_spdk_bdev_complete, NULL, &bsdev); - if (res != 0) { - spdk_app_stop(-1); - return ; - } - - ctx->bsdev = bsdev; - spdk_bs_init(bsdev, NULL, zvfs_spdk_bdev_init_complete, ctx); - - return ; -} - - - -// unload -static void zvfs_do_unload(void *arg) { - - zvfs_t *ctx = arg; - //spdk_bs_delete_blob(ctx->bs, ctx->blobid, zvfs_spdk_bs_delete_complete, ctx); - spdk_bs_destroy(ctx->bs, zvfs_spdk_bs_destroy_complete, ctx); - - return ; -} - - - -/// zvfs file api -// - -static const int POLLER_MAX_TIME = 100000; - - -static bool poller(struct spdk_thread *thread, spdk_msg_fn start_fn, void *ctx, bool *finished) { - - - spdk_thread_send_msg(thread, start_fn, ctx); - int poller_count = 0; - - do { - spdk_thread_poll(thread, 0, 0); - - poller_count ++; - } while (!(*finished) && poller_count < POLLER_MAX_TIME); - - - if (!(*finished) && poller_count >= POLLER_MAX_TIME) { //timeout - return false; - } - - return true; -} - - -/// -static void zvfs_do_open(void *arg) { - - zvfs_file_t *ctx = arg; -#if 0 - spdk_bs_open_blob(ctx->fs->bs, ctx->blobid, zvfs_spdk_bdev_open_blob_complete, ctx); -#else - spdk_bs_create_blob(ctx->fs->bs, zvfs_spdk_bdev_create_blob_complete, ctx); -#endif - return ; -} - - - -static void zvfs_do_write(void *arg) { - - - zvfs_file_t *file = arg; -#if 0 - ctx->write_buff = spdk_malloc(ctx->io_unit_size, 0x1000, NULL, - SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (ctx->write_buff == NULL) { - return ; - } - - memset(ctx->write_buff, 'K', ctx->io_unit_size); - ctx->write_buff[ctx->io_unit_size-1] = '\0'; -#endif - - - spdk_blob_io_write(file->blob, file->fs->channel, file->write_buff, 0, 1, zvfs_spdk_blob_write_complete, file); - - - return ; -} - -static void zvfs_do_read(void *arg) { - - zvfs_file_t *file = arg; -#if 0 - ctx->read_buff = spdk_malloc(ctx->io_unit_size, 0x1000, NULL, - SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (ctx->read_buff == NULL) { - return ; - } -#endif - spdk_blob_io_read(file->blob, file->fs->channel, file->read_buff, 0, 1, zvfs_spdk_blob_read_complete, file); - - return ; -} - -static void zvfs_do_close(void *arg) { - zvfs_file_t *file = arg; - spdk_blob_close(file->blob, zvfs_spdk_blob_close_complete, file); - return ; -} - - -// errno -// 1. -// strerr -// - -//// zvfs_file_open -static int zvfs_file_open(zvfs_file_t *file) { - - file->finished = false; - if (!poller(global_thread, zvfs_do_open, file, &file->finished)) { - return -1; - } - return 0; -} - - -static int zvfs_file_close(zvfs_file_t *file) { - - file->finished = false; - if (!poller(global_thread, zvfs_do_close, file, &file->finished)) { - return -1; - } - return 0; -} - -static int zvfs_file_write(zvfs_file_t *file, const void *buf, size_t size) { - - file->finished = false; - - memcpy(file->write_buff, buf, size); // - - if (!poller(global_thread, zvfs_do_write, file, &file->finished)) { - return -1; - } - return 0; -} - - -static int zvfs_file_read(zvfs_file_t *file, void *buf, size_t size) { - - file->finished = false; - if (!poller(global_thread, zvfs_do_read, file, &file->finished)) { - return -1; - } - - memcpy(buf, file->read_buff, size); - - return 0; - -} - - - - -//// zvfs - -static int zvfs_load(zvfs_t *fs) { - - fs->finished = false; - if (!poller(global_thread, zvfs_do_load, fs, &fs->finished)) { - return -1; - } - - return 0; -} - -static int zvfs_unload(zvfs_t *fs) { - - fs->finished = false; - if (!poller(global_thread, zvfs_do_unload, fs, &fs->finished)) { - return -1; - } - return 0; -} - - - -// fd - -#define MAX_FD_COUNT 1024 -#define DEFAULT_FD_NUM 3 - - -static unsigned char fd_table[MAX_FD_COUNT / 8] = {0}; -zvfs_file_t *files[MAX_FD_COUNT] = {0}; - - -static int get_fd_frombitmap(void) { - - int fd = DEFAULT_FD_NUM; - for ( ;fd < MAX_FD_COUNT;fd ++) { - if ((fd_table[fd/8] & (0x1 << (fd % 8))) == 0) { - fd_table[fd/8] |= (0x1 << (fd % 8)); - return fd; - } - } - - return -1; - -} - -static int set_fd_frombitmap(int fd) { - - if (fd >= MAX_FD_COUNT) return -1; - - fd_table[fd/8] &= ~(0x1 << (fd % 8)); - - return 0; -} - - -static int zvfs_open(const char *filename, int flag) { - - zvfs_file_t *file = (zvfs_file_t*)malloc(sizeof(zvfs_file_t)); - if (file == NULL) return -1; - - int fd = get_fd_frombitmap(); - file->fs = fs; - files[fd] = file; - - zvfs_file_open(file); - - return fd; - -} - -static int zvfs_write(int fd,const void *buf, size_t count) { - - zvfs_file_t *file = files[fd]; - zvfs_file_write(file, buf, count); - - return 0; -} - -static int zvfs_read(int fd, void *buf, size_t count) { - zvfs_file_t *file = files[fd]; - zvfs_file_read(file, buf, count); - - - return strlen(buf); -} - -static int zvfs_close(int fd) { - - zvfs_file_t *file = files[fd]; - zvfs_file_close(file); - set_fd_frombitmap(fd); - - free(file); - - return 0; -} - -/// hook -#if 0 -typedef int (*open_t)(const char *pathname, int flags); -open_t open_f = NULL; - -typedef ssize_t (*write_t)(int fd, const void *buf, size_t n); -write_t write_f = NULL; - -typedef ssize_t (*read_t)(int fd, void *buf, size_t n); -read_t read_f = NULL; - -typedef int (*close_t)(int fd); -close_t close_f; - - -int zvfs_initilize = false; - -static int zvfs_setup(void); - -int open(const char *pathname, int flags, ...) { - int ret = 0; - - ret = syscall(__NR_open, pathname, flags); - - return ret; -} - - -ssize_t write(int fd, const void *buf, size_t n) { - - int ret = 0; - - ret = syscall(__NR_write, buf, n); - - return ret; -} - -ssize_t read(int fd, void *buf, size_t n) { - - int ret = 0; - - ret = syscall(__NR_read, buf, n); - - return ret; -} - -int close (int fd) { - - int ret = 0; - - ret = syscall(__NR_close, fd); - - return ret; - -} - - -#else - - -#include - - -#define DEBUG_ENABLE 1 - -#if DEBUG_ENABLE -#define dblog(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else -#define dblog(fmt, ...) -#endif - -typedef int (*open_t)(const char *pathname, int flags); -open_t open_f = NULL; - -typedef ssize_t (*write_t)(int fd, const void *buf, size_t n); -write_t write_f = NULL; - -typedef ssize_t (*read_t)(int fd, void *buf, size_t n); -read_t read_f = NULL; - -typedef int (*close_t)(int fd); -close_t close_f = NULL; - -int open(const char *pathname, int flags, ...) { - - if (!open_f) { - open_f = dlsym(RTLD_NEXT, "open"); - } - - dblog("open.. %s\n", pathname); - - return open_f(pathname, flags); -} - -ssize_t read(int fd, void *buf, size_t count) { - - ssize_t ret; - - if (!read_f) { - read_f = dlsym(RTLD_NEXT, "read"); - } - - ret = read_f(fd, buf, count); - dblog("read.. : %ld, %ld\n", ret, count); - - return ret; -} - -ssize_t write(int fd, const void *buf, size_t count) { - - if (!write_f) { - write_f = dlsym(RTLD_NEXT, "write"); - } - - dblog("write.. : %ld\n", count); - - return write_f(fd, buf, count); - -} - -int close(int fd) { - - if (!close_f) { - close_f = dlsym(RTLD_NEXT, "close"); - } - - dblog("close..\n"); - - return close_f(fd); - -} -#endif - -#if 1 - - -static const char *json_file = "/home/king/share/spdk/examples/mysql/hello_blob.json"; - -static void json_app_load_done(int rc, void *ctx) { - - bool *done = ctx; - *done = true; -// SPDK_NOTICELOG("json_app_load_done\n"); - -} - - -static void zvfs_json_load_fn(void *arg) { - - spdk_subsystem_init_from_json_config(json_file, SPDK_DEFAULT_RPC_ADDR, - json_app_load_done, arg, true); - -} - - -static int zvfs_env_setup(void) { - struct spdk_env_opts opts; - spdk_env_opts_init(&opts); - - if (spdk_env_init(&opts) != 0) { - return -1; - } - - spdk_log_set_print_level(SPDK_LOG_NOTICE); - spdk_log_set_level(SPDK_LOG_NOTICE); - spdk_log_open(NULL); - - spdk_thread_lib_init(NULL, 0); - global_thread = spdk_thread_create("global", NULL); - spdk_set_thread(global_thread); - - bool done = false; - poller(global_thread, zvfs_json_load_fn, &done, &done); - - return 0; -} - -// blob --> json - -static int zvfs_setup(void) { - zvfs_env_setup(); - - zvfs_t *ctx = calloc(1, sizeof(zvfs_t)); - zvfs_load(ctx); - fs = ctx; - - return 0; -} - -#if 0 - -int main(int argc, char *argv[]) { - printf("zvfs_env_setup111\n"); - -#if 0 - zvfs_env_setup(); - // load --> bs_init, blob_create, blob_open, blob_resize - zfs_ctx_t *ctx = calloc(1, sizeof(zfs_ctx_t)); - ctx->finished = false; - poller(global_thread, zvfs_do_load, ctx, &ctx->finished); - - // open - ctx->finished = false; - poller(global_thread, zvfs_do_open, ctx, &ctx->finished); - - // write - ctx->finished = false; - poller(global_thread, zvfs_do_write, ctx, &ctx->finished); - - // read - ctx->finished = false; - poller(global_thread, zvfs_do_read, ctx, &ctx->finished); - - // close - ctx->finished = false; - poller(global_thread, zvfs_do_close, ctx, &ctx->finished); - - // unload - ctx->finished = false; - poller(global_thread, zvfs_do_unload, ctx, &ctx->finished); - -#elif 0 - zvfs_env_setup(); - - zvfs_t *ctx = calloc(1, sizeof(zvfs_t)); - zvfs_load(ctx); - fs = ctx; - - zvfs_file_t *file = calloc(1, sizeof(zvfs_file_t)); - file->fs = ctx; - zvfs_file_open(file); - - char *buffer = "zvoice.king"; - zvfs_file_write(file, buffer, strlen(buffer)); - - char rbuffer[1024] = {0}; - zvfs_file_read(file, rbuffer, 1024); - - printf("rbuffer: %s\n", rbuffer); - - zvfs_file_close(file); - - - zvfs_unload(ctx); - -#elif 0 - - zvfs_t *ctx = calloc(1, sizeof(zvfs_t)); - zvfs_load(ctx); - fs = ctx; - - int fd = zvfs_open("king.txt", 0x666); - - char *buffer = "zvoice.king"; - zvfs_write(fd, buffer, strlen(buffer)); - - char rbuffer[1024] = {0}; - zvfs_read(fd, rbuffer, 1024); - printf("rbuffer: %s\n", rbuffer); - - zvfs_close(fd); - - zvfs_unload(ctx); - -#else - - printf("zvfs_env_setup\n"); - //zvfs_t *ctx = calloc(1, sizeof(zvfs_t)); - //zvfs_load(ctx); - //fs = ctx; - printf("zvfs_load\n"); - - int fd = open("/home/king/share/spdk/examples/mysql/a.txt", O_RDWR | O_CREAT); - - printf("fd: %d, %s\n", fd, strerror(errno)); - char *buffer = "zvoice.king"; - int ret = write(fd, buffer, strlen(buffer)); - - lseek(fd, 0, SEEK_SET); - - char rbuffer[1024] = {0}; - ret = read(fd, rbuffer, 1024); - printf("ret : %d, rbuffer: %s\n", ret, rbuffer); - - close(fd); - - - //zvfs_unload(fs); - - return 0; -#endif - -} - -#endif - -#elif 0 - - -int main() { - - int fd = open("./a.txt", RW); - - char *buffer = "zvoice.king"; - write(fd, buffer, strlen(buffer)); - - char rbuffer[1024] = {0}; - read(fd, rbuffer, 1024); - - close(fd); - -} - -#else - -int main(int argc, char *argv[]) { - - if (argc < 2) { - return -1; - } - - struct spdk_app_opts opts= {0}; - spdk_app_opts_init(&opts, sizeof(opts)); - opts.name = "zvfs"; - opts.json_config_file = argv[1]; - - printf("spdk_set_thread --> \n"); - - zfs_ctx_t *ctx = calloc(1, sizeof(zfs_ctx_t)); - spdk_app_start(&opts, zvfs_entry, ctx); - - spdk_app_fini(); - - free(ctx); - - return 0; -} - - -#endif - - - - diff --git a/test_so/posix.c b/test_so/posix.c deleted file mode 100755 index fd900cc..0000000 --- a/test_so/posix.c +++ /dev/null @@ -1,79 +0,0 @@ - - -// hook --> - -// open - - -// write - - -// read - - -// close - -#define _GNU_SOURCE -#include - - -#include - - - -typedef int (*open_t)(const char *pathname, int flags); -open_t open_f = NULL; - -typedef ssize_t (*read_t)(int fd, void *buf, size_t count); -read_t read_f = NULL; - - -typedef ssize_t (*write_t)(int fd, const void *buf, size_t count); -write_t write_f = NULL; - -typedef int (*close_t)(int fd); -close_t close_f = NULL; - - -int open(const char *pathname, int flags) { - - if (open_f == NULL) { - open_f = dlsym(RTLD_NEXT, "open"); - } - - printf("open .. %s\n", pathname); - - return open_f(pathname, flags); -} - -ssize_t read(int fd, void *buf, size_t count) { - - if (read_f == NULL) { - read_f = dlsym(RTLD_NEXT, "read"); - } - - printf("read ..\n"); - return read_f(fd, buf, count); -} - -ssize_t write(int fd, const void *buf, size_t count) { - - if (write_f == NULL) { - write_f = dlsym(RTLD_NEXT, "write"); - } - - printf("write ..\n"); - return write_f(fd, buf, count); -} - -int close(int fd) { - if (close_f == NULL) { - close_f = dlsym(RTLD_NEXT, "close"); - } - - printf("close ..\n"); - return close_f(fd); -} - - - diff --git a/test_so/test_so.c b/test_so/test_so.c deleted file mode 100755 index 35b7c5b..0000000 --- a/test_so/test_so.c +++ /dev/null @@ -1,29 +0,0 @@ - - -#include -#include -#include -#include -#include -#include - -// posix -int main() { - - int fd = open("a.txt", O_CREAT | O_RDWR); - - char *buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - write(fd, buffer, strlen(buffer)); - - char rbuffer[128] = {0}; - read(fd, buffer, 128); - - printf("rbuffer: %s\n", buffer); - - close(fd); -} - - - - diff --git a/zv2404fs.c b/zv2404fs.c deleted file mode 100755 index 892eac3..0000000 --- a/zv2404fs.c +++ /dev/null @@ -1,664 +0,0 @@ - - -#include - -#include -#include -#include -#include -#include - - - -#define BUFFER_SIZE 512 - - -#if 0 - -struct spdk_blob_store *blobstore; -spdk_blob_id blob_id; -struct spdk_blob *blob; -uint64_t free_cluster_count; -uint64_t num_cluster; -uint8_t *write_buffer; -uint8_t *read_buffer; -struct spdk_io_channel *channel; - -#else - -#define FILENAME_LENGTH 128 - -// -typedef struct zv2404fs_context_s { - - struct spdk_blob_store *blobstore; - spdk_blob_id blob_id; - struct spdk_blob *blob; - uint64_t unit_size; - uint64_t free_cluster_count; - uint64_t num_cluster; - uint8_t *write_buffer; - uint8_t *read_buffer; - struct spdk_io_channel *channel; - -} zv2404fs_context_t; - -typedef struct zv2404fs_s { - - struct spdk_blob_store *blobstore; - uint64_t unit_size; - uint64_t free_cluster_count; - uint64_t num_cluster; - - struct spdk_io_channel *channel; - bool finished; - -} zv2404fs_t; - -typedef struct zv2404fs_operation_s { - int (*mount)(struct zv2404fs_s *fs); - int (*umount)(struct zv2404fs_s *fs); -} zv2404fs_operation_t; - - -typedef struct zv2404fs_file_s { - - uint8_t filename[FILENAME_LENGTH]; - - spdk_blob_id blob_id; - struct spdk_blob *blob; - zv2404fs_t *fs; - - uint8_t *write_buffer; - uint8_t *read_buffer; - - bool finished; - -} zv2404fs_file_t; - -typedef struct zv2404fs_file_operation_s { - - int (*open)(struct zv2404fs_file_s *file); - int (*read)(struct zv2404fs_file_s *file); - int (*write)(struct zv2404fs_file_s *file); - int (*close)(struct zv2404fs_file_s *file); - -} zv2404fs_file_operation_t; - - -#endif - -struct spdk_thread *global_thread = NULL; - -static const int WAITER_MAX_TIME = 100000; - -static bool waiter(struct spdk_thread *thread, spdk_msg_fn start_fn, void *ctx, bool *finished) { - - spdk_thread_send_msg(thread, start_fn, ctx); - - int waiter_count = 0; - - do { - spdk_thread_poll(thread, 0, 0); - waiter_count ++; - } while(!(*finished) && waiter_count < WAITER_MAX_TIME); - - if (!(*finished) && waiter_count >= WAITER_MAX_TIME) { - return false; // timeout - } - - return true; -} - - - -static void zv2404fs_spdk_bs_unload_cb(void *arg, int bserrno) { - - zv2404fs_t *fs = (zv2404fs_t *)arg; - fs->finished = true; - -} - - - -static void zv2404fs_do_umount(void *arg) { - - zv2404fs_t *fs = (zv2404fs_t *)arg; - - if (fs->blobstore) { - if (fs->channel) { - spdk_bs_free_io_channel(fs->channel); - } - spdk_bs_unload(fs->blobstore, zv2404fs_spdk_bs_unload_cb, fs); - } - -} - -static void zv2404fs_spdk_blob_delete_cb(void *arg, int bserrno) { -#if 0 - zv2404fs_t *fs = (zv2404fs_t *)arg; - - if (ctx->blobstore) { - if (ctx->channel) { - spdk_bs_free_io_channel(ctx->channel); - } - spdk_bs_unload(ctx->blobstore, zv2404fs_spdk_bs_unload_cb, ctx); - } -#else - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - spdk_free(file->write_buffer); - spdk_free(file->read_buffer); - - SPDK_NOTICELOG("close complete\n"); - file->finished = true; - -#endif -} - - -static void zv2404fs_spdk_blob_close_cb(void *arg, int bserrno) { -#if 0 - zv2404fs_context_t *ctx = (zv2404fs_context_t*)arg; - - -#else - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - spdk_bs_delete_blob(file->fs->blobstore, file->blob_id, zv2404fs_spdk_blob_delete_cb, file); - - -#endif -} - - -static void zv2404fs_do_close(void *arg) { - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - spdk_blob_close(file->blob, zv2404fs_spdk_blob_close_cb, file); - -} - - -static void zv2404fs_spdk_blob_read_cb(void *arg, int bserrno) { - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - SPDK_NOTICELOG("READ BUFFER : %s\n", file->read_buffer); - - file->finished = true; - - //spdk_blob_close(ctx->blob, zv2404fs_spdk_blob_close_cb, ctx); - -} - - -static void zv2404fs_do_read(void *arg) { - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - memset(file->read_buffer, 0x0, BUFFER_SIZE); - - spdk_blob_io_read(file->blob, file->fs->channel, file->read_buffer, - 0, 1, zv2404fs_spdk_blob_read_cb, file); - -} - - -static void zv2404fs_spdk_blob_write_cb(void *arg, int bserrno) { -#if 0 - zv2404fs_context_t *ctx = (zv2404fs_context_t*)arg; - - SPDK_NOTICELOG("WRITE COMPLETE\n"); - - uint8_t *rbuffer = spdk_malloc(512, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (rbuffer == NULL) { - spdk_app_stop(0); - return ; - } - memset(rbuffer, 0x0, BUFFER_SIZE); - - ctx->read_buffer = rbuffer; - - spdk_blob_io_read(ctx->blob, ctx->channel, rbuffer, 0, 1, zv2404fs_spdk_blob_read_cb, ctx); - -#else - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - SPDK_NOTICELOG("write complete\n"); - - file->finished = true; - - -#endif -} - - -static void zv2404fs_do_write(void *arg) { - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - spdk_blob_io_write(file->blob, file->fs->channel, file->write_buffer, - 0, 1, zv2404fs_spdk_blob_write_cb, file); - -} - -static void zv2404fs_spdk_blob_sync_cb(void *arg, int bserrno) { -#if 0 - zv2404fs_context_t *ctx = (zv2404fs_context_t*)arg; - - uint8_t *wbuffer = spdk_malloc(512, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (wbuffer == NULL) { - spdk_app_stop(0); - return ; - } - memset(wbuffer, 'A', BUFFER_SIZE); - *(wbuffer+BUFFER_SIZE-1) = '\0'; - - ctx->write_buffer = wbuffer; - - struct spdk_io_channel *chan = spdk_bs_alloc_io_channel(ctx->blobstore); - if (chan == NULL) { - spdk_app_stop(0); - return ; - } - ctx->channel = chan; - - spdk_blob_io_write(ctx->blob, ctx->channel, wbuffer, 0, 1, zv2404fs_spdk_blob_write_cb, ctx); -#else - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - file->write_buffer = spdk_malloc(BUFFER_SIZE, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (file->write_buffer == NULL) { - return ; - } - - file->read_buffer = spdk_malloc(BUFFER_SIZE, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (file->read_buffer == NULL) { - return ; - } - - - SPDK_NOTICELOG("open complete\n"); - - file->finished = true; - -#endif -} - - - -static void zv2404fs_spdk_blob_resize_cb(void *arg, int bserrno) { - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - uint64_t total = spdk_blob_get_num_clusters(file->blob); - file->fs->num_cluster = total; - - SPDK_NOTICELOG("resize blob :%"PRIu64"\n", total); - - spdk_blob_sync_md(file->blob, zv2404fs_spdk_blob_sync_cb, file); - -} - - - -static void zv2404fs_spdk_bs_open_blob_cb(void *arg, struct spdk_blob *blb, int bserrno) { - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - file->blob = blb; - - uint64_t free_cluster = spdk_bs_free_cluster_count(file->fs->blobstore); // - SPDK_NOTICELOG("free_cluster : %"PRIu64"\n", free_cluster); - file->fs->free_cluster_count = free_cluster; - - spdk_blob_resize(blb, free_cluster, zv2404fs_spdk_blob_resize_cb, file); - -} - - - -static void zv2404fs_spdk_bs_create_blob_cb(void *arg, spdk_blob_id blobid, int bserrno) { - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - file->blob_id = blobid; - SPDK_NOTICELOG("blobid : %"PRIu64"\n", blobid); - - spdk_bs_open_blob(file->fs->blobstore, blobid, zv2404fs_spdk_bs_open_blob_cb, file); -} - - -static void zv2404fs_do_open(void *arg) { - - zv2404fs_file_t *file = (zv2404fs_file_t *)arg; - - spdk_bs_create_blob(file->fs->blobstore, zv2404fs_spdk_bs_create_blob_cb, file); - -} - -static void zv2404fs_spdk_bs_init_cb(void *arg, struct spdk_blob_store *bs, - int bserrno) { - - zv2404fs_t *fs = (zv2404fs_t*)arg; - - uint64_t io_unit_size = spdk_bs_get_io_unit_size(bs); - SPDK_NOTICELOG("io_unit_size : %"PRIu64"\n", io_unit_size); - - fs->unit_size = io_unit_size; - fs->blobstore = bs; - - fs->channel = spdk_bs_alloc_io_channel(fs->blobstore); - if (fs->channel == NULL) { - return ; - } - - fs->finished = true; - - SPDK_NOTICELOG("mount finished\n"); - - // -} - - - -static void zv2404_spdk_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, - void *event_ctx) { - - SPDK_NOTICELOG("zv2404_spdk_bdev_event_cb\n"); - -} - - - - -static void zv2404fs_do_mount(void *arg) { - - zv2404fs_t *fs = (zv2404fs_t*)arg; - - struct spdk_bs_dev *bs_dev = NULL; - - int rc = spdk_bdev_create_bs_dev_ext("Malloc0", zv2404_spdk_bdev_event_cb, NULL, &bs_dev); - if (rc != 0) { - spdk_app_stop(0); - } - - //int *count = malloc(sizeof(int)); - //*count = 2404; - - spdk_bs_init(bs_dev, NULL, zv2404fs_spdk_bs_init_cb, fs); - - //sleep(10); - SPDK_NOTICELOG("zv2404fs_entry\n"); - -} - - -// filesystem -// load -static int zv2404fs_mount(struct zv2404fs_s *fs) { - - fs->finished = false; - - return waiter(global_thread, zv2404fs_do_mount, fs, &fs->finished); -} - - -// unload -static int zv2404fs_umount(struct zv2404fs_s *fs) { - - fs->finished = false; - - return waiter(global_thread, zv2404fs_do_umount, fs, &fs->finished); -} - - -// file -// open -static int zv2404fs_open(struct zv2404fs_file_s *file) { - - file->finished = false; - - return waiter(global_thread, zv2404fs_do_open, file, &file->finished); - -} - - -// read - -static int zv2404fs_read(struct zv2404fs_file_s *file, uint8_t *buffer, size_t count) { - - file->finished = false; - waiter(global_thread, zv2404fs_do_read, file, &file->finished); - - int len = strlen(file->read_buffer); - memcpy(buffer, file->read_buffer, len); // - - return len; -} - - -// write - -static int zv2404fs_write(struct zv2404fs_file_s *file, const uint8_t *buffer, size_t count) { - - file->finished = false; - - memcpy(file->write_buffer, buffer, count); // count / 512 - - return waiter(global_thread, zv2404fs_do_write, file, &file->finished); -} - -// close -static int zv2404fs_close(struct zv2404fs_file_s *file) { - - file->finished = false; - - return waiter(global_thread, zv2404fs_do_close, file, &file->finished); -} - - -// fd --> file - - -#if 1 - - - -// zvfs.json - -static const char *json_file = "/home/king/share/spdk/examples/5.3.1-zv2404fs/zvfs.json"; - - -static void json_app_load_done(int rc, void *ctx) { - - bool *done = ctx; - *done = true; - - SPDK_NOTICELOG("json_app_load_done\n"); -} - -static void zv2404fs_json_load_fn(void *arg) { - - spdk_subsystem_init_from_json_config(json_file, SPDK_DEFAULT_RPC_ADDR, json_app_load_done, - arg, true); - -} - - -static int zv2404fs_env_setup(void) { - - struct spdk_env_opts opts; - spdk_env_opts_init(&opts); - - if (0 != spdk_env_init(&opts)) { - return -1; - } - - spdk_log_set_print_level(SPDK_LOG_NOTICE); - spdk_log_set_level(SPDK_LOG_NOTICE); - spdk_log_open(NULL); - - spdk_thread_lib_init(NULL, 0); - global_thread = spdk_thread_create("global", NULL); - spdk_set_thread(global_thread); - - bool done = false; - //zv2404fs_json_load_fn(&done); - - waiter(global_thread, zv2404fs_json_load_fn, &done, &done); - SPDK_NOTICELOG("json_app_load_done complete\n"); - - - return 0; - -} - - -int main(int argc, char *argv[]) { - - if (zv2404fs_env_setup()) { - return -1; - } - - SPDK_NOTICELOG("zv2404fs_env_setup success\n"); - - SPDK_NOTICELOG("\n\n zv2404fs mount start \n\n"); - zv2404fs_t *fs = calloc(1, sizeof(zv2404fs_t)); - zv2404fs_mount(fs); - - SPDK_NOTICELOG("\n\n zv2404fs open start \n\n"); - zv2404fs_file_t *file = calloc(1, sizeof(zv2404fs_file_t)); - file->fs = fs; - zv2404fs_open(file); - - - SPDK_NOTICELOG("\n\n zv2404fs write start \n\n"); - char *buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - zv2404fs_write(file, buffer, strlen(buffer)); - - - SPDK_NOTICELOG("\n\n zv2404fs read start \n\n"); - char rbuffer[BUFFER_SIZE] = {0}; - zv2404fs_read(file, rbuffer, BUFFER_SIZE); - SPDK_NOTICELOG("READ BUFFER: %s\n", rbuffer); - - SPDK_NOTICELOG("\n\n zv2404fs close start \n\n"); - zv2404fs_close(file); - - free(file); - - SPDK_NOTICELOG("\n\n zv2404fs umount start \n\n"); - zv2404fs_umount(fs); - free(fs); - -} - - -#elif 0 - -int main(int argc, char *argv[]) { - - if (argc != 2) return -1; - - struct spdk_app_opts opts = {}; - - spdk_app_opts_init(&opts, sizeof(opts)); - opts.name = "zv2404fs"; - opts.json_config_file = argv[1]; - - zv2404fs_context_t *ctx = calloc(1, sizeof(zv2404fs_context_t)); - - spdk_app_start(&opts, zv2404fs_entry, ctx); - - SPDK_NOTICELOG("hello spdk\n"); - -} - - - - -#else - - - -typedef int (*open_t)(const char *pathname, int flags); -open_t open_f = NULL; - -typedef ssize_t (*read_t)(int fd, void *buf, size_t count); -read_t read_f = NULL; - - -typedef ssize_t (*write_t)(int fd, const void *buf, size_t count); -write_t write_f = NULL; - -typedef int (*close_t)(int fd); -close_t close_f = NULL; - - -int open(const char *pathname, int flags) { - - if (open_f == NULL) { - open_f = dlsym(RTLD_NEXT, "open"); - } - - printf("open .. %s\n", pathname); - - return open_f(pathname, flags); -} - -ssize_t read(int fd, void *buf, size_t count) { - - if (read_f == NULL) { - read_f = dlsym(RTLD_NEXT, "read"); - } - - printf("read ..\n"); - return read_f(fd, buf, count); -} - -ssize_t write(int fd, const void *buf, size_t count) { - - if (write_f == NULL) { - write_f = dlsym(RTLD_NEXT, "write"); - } - - printf("write ..\n"); - return write_f(fd, buf, count); -} - -int close(int fd) { - if (close_f == NULL) { - close_f = dlsym(RTLD_NEXT, "close"); - } - - printf("close ..\n"); - return close_f(fd); -} - - - - -// posix -int main() { - - int fd = open("a.txt", O_CREAT | O_RDWR); - - char *buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - write(fd, buffer, strlen(buffer)); - - char rbuffer[128] = {0}; - read(fd, buffer, 128); - - close(); -} - -#endif - - - diff --git a/zvfs.c b/zvfs.c new file mode 100755 index 0000000..ce1c723 --- /dev/null +++ b/zvfs.c @@ -0,0 +1,553 @@ + + +#include "zvfs.h" + +struct spdk_thread *global_thread = NULL; + +// mount +void zvfs_do_mount(void *arg); +void zvfs_spdk_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx); +void zvfs_spdk_bs_init_cb(void *arg, struct spdk_blob_store *bs, int bserrno); + +// create +void zvfs_do_create(void *arg); +void zvfs_spdk_bs_create_blob_cb(void *arg, spdk_blob_id blobid, int bserrno); +void zvfs_spdk_bs_open_blob_cb(void *arg, struct spdk_blob *blb, int bserrno); +void zvfs_spdk_blob_resize_cb(void *arg, int bserrno); +void zvfs_spdk_blob_sync_cb(void *arg, int bserrno); +// open +void zvfs_do_open(void *arg); +void zvfs_spdk_bs_open_blob_cb2(void *arg, struct spdk_blob *blb, int bserrno); + +// read +void zvfs_do_read(void *arg); +void zvfs_spdk_blob_read_cb(void *arg, int bserrno); + +// write +void zvfs_do_write(void *arg); +void zvfs_do_write_io(zvfs_file_t *file); +void zvfs_spdk_blob_write_resize_cb(void *arg, int bserrno); +void zvfs_spdk_blob_write_sync_cb(void *arg, int bserrno); +void zvfs_spdk_blob_write_cb(void *arg, int bserrno); + +// close +void zvfs_do_close(void *arg); +void zvfs_spdk_blob_close_cb(void *arg, int bserrno); + +// delete +void zvfs_do_delete(void *arg); +void zvfs_spdk_blob_delete_cb(void *arg, int bserrno); + +// setup +void zvfs_json_load_fn(void *arg); +void json_app_load_done(int rc, void *ctx); + + +// unmount +void zvfs_do_umount(void *arg); +void zvfs_spdk_bs_unload_cb(void *arg, int bserrno); + +/* ========== helpers ========== */ + +static uint64_t zvfs_need_clusters(zvfs_t *fs, uint64_t end_byte) { + uint64_t cluster_size = spdk_bs_get_cluster_size(fs->bs); + return (end_byte + cluster_size - 1) / cluster_size; +} + +// mount +void zvfs_do_mount(void *arg) { + + zvfs_t *fs = (zvfs_t*)arg; + + struct spdk_bs_dev *bs_dev = NULL; + + int rc = spdk_bdev_create_bs_dev_ext("Malloc0", zvfs_spdk_bdev_event_cb, NULL, &bs_dev); + if (rc != 0) { + spdk_app_stop(0); + } + + spdk_bs_init(bs_dev, NULL, zvfs_spdk_bs_init_cb, fs); + + SPDK_NOTICELOG("zvfs_entry\n"); + +} + +void zvfs_spdk_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, + void *event_ctx) { + SPDK_NOTICELOG("zvfs_spdk_bdev_event_cb\n"); +} + +void zvfs_spdk_bs_init_cb(void *arg, struct spdk_blob_store *bs, int bserrno) { + zvfs_t *fs = (zvfs_t*)arg; + + uint64_t io_unit_size = spdk_bs_get_io_unit_size(bs); + SPDK_NOTICELOG("io_unit_size : %"PRIu64"\n", io_unit_size); + + fs->io_unit_size = io_unit_size; + fs->bs = bs; + + fs->channel = spdk_bs_alloc_io_channel(fs->bs); + if (fs->channel == NULL) { + return ; + } + + fs->finished = true; + + SPDK_NOTICELOG("mount finished\n"); +} + +// create +void zvfs_do_create(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + spdk_bs_create_blob(file->fs->bs, zvfs_spdk_bs_create_blob_cb, file); + +} + +void zvfs_spdk_bs_create_blob_cb(void *arg, spdk_blob_id blobid, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + file->blob_id = blobid; + SPDK_NOTICELOG("blobid : %"PRIu64"\n", blobid); + + spdk_bs_open_blob(file->fs->bs, blobid, zvfs_spdk_bs_open_blob_cb, file); +} + +void zvfs_spdk_bs_open_blob_cb(void *arg, struct spdk_blob *blb, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + if (bserrno) { + SPDK_ERRLOG("load blob error: %d\n", bserrno); + file->finished = true; + return; + } + + file->blob = blb; + + uint64_t free_cluster = spdk_bs_free_cluster_count(file->fs->bs); // + SPDK_NOTICELOG("free_cluster : %"PRIu64"\n", free_cluster); + + spdk_blob_resize(blb, free_cluster, zvfs_spdk_blob_resize_cb, file); +} + +void zvfs_spdk_blob_resize_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + uint64_t total = spdk_blob_get_num_clusters(file->blob); + SPDK_NOTICELOG("resize blob :%"PRIu64"\n", total); + + if (file->dirent) { + file->dirent->allocated_clusters = total; + } + + spdk_blob_sync_md(file->blob, zvfs_spdk_blob_sync_cb, file); +} + +void zvfs_spdk_blob_sync_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + file->dma_buf = spdk_malloc(BUFFER_SIZE, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if (file->dma_buf == NULL) { + SPDK_ERRLOG("spdk_malloc failed\n"); + file->finished = true; + return ; + } + + file->dma_buf_size = BUFFER_SIZE; + SPDK_NOTICELOG("open complete\n"); + file->finished = true; +} + +// open +void zvfs_do_open(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + spdk_bs_open_blob(file->fs->bs, file->blob_id, zvfs_spdk_bs_open_blob_cb2, file); +} + +void zvfs_spdk_bs_open_blob_cb2(void *arg, struct spdk_blob *blb, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + if (bserrno) { + SPDK_ERRLOG("load blob error: %d\n", bserrno); + file->finished = true; + return; + } + + file->blob = blb; + + file->dma_buf = spdk_malloc(BUFFER_SIZE, 0x1000, NULL, + SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if (!file->dma_buf) { + SPDK_ERRLOG("spdk_malloc failed\n"); + file->finished = true; + return; + } + + file->dma_buf_size = BUFFER_SIZE; + file->finished = true; +} + +// read +void zvfs_do_read(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + uint64_t io_unit_size = file->fs->io_unit_size; + uint64_t offset = file->current_offset; + uint64_t file_size = file->dirent ? file->dirent->file_size : 0; + + if (offset >= file_size) { + SPDK_NOTICELOG("read: EOF\n"); + file->io_count = 0; + file->finished = true; + return; + } + + if (offset + file->io_count > file_size) { + file->io_count = file_size - offset; + } + + uint64_t lba = offset / io_unit_size; + uint64_t page_off = offset % io_unit_size; + uint64_t lba_count = (page_off + file->io_count + io_unit_size - 1) / io_unit_size; + + spdk_blob_io_read(file->blob, file->fs->channel, + file->dma_buf, + lba, lba_count, + zvfs_spdk_blob_read_cb, file); +} + +void zvfs_spdk_blob_read_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + if (bserrno) { + SPDK_ERRLOG("blob_read error: %d\n", bserrno); + file->io_count = 0; + file->finished = true; + return; + } + + file->current_offset += file->io_count; + SPDK_NOTICELOG("read complete, new offset=%" PRIu64 "\n", file->current_offset); + file->finished = true; +} + + +// write +/* + * callback 链: + * + * zvfs_do_write + * ├─(需要扩容)─→ spdk_blob_resize → zvfs_spdk_blob_write_resize_cb + * │ → spdk_blob_sync_md → zvfs_spdk_blob_write_sync_cb + * │ → zvfs_do_write_io + * │ → zvfs_spdk_blob_write_cb + * └─(不需扩容)─→ zvfs_do_write_io + * → zvfs_spdk_blob_write_cb + */ +void zvfs_do_write_io(zvfs_file_t *file) { + uint64_t io_unit_size = file->fs->io_unit_size; + uint64_t lba = file->current_offset / io_unit_size; + uint64_t page_off = file->current_offset % io_unit_size; + uint64_t lba_count = (page_off + file->io_count + io_unit_size - 1) / io_unit_size; + + spdk_blob_io_write(file->blob, file->fs->channel, + file->dma_buf, + lba, lba_count, + zvfs_spdk_blob_write_cb, file); +} + +void zvfs_spdk_blob_write_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + if (bserrno) { + SPDK_ERRLOG("blob_write error: %d\n", bserrno); + file->finished = true; + return; + } + + uint64_t new_end = file->current_offset + file->io_count; + if (file->dirent && new_end > file->dirent->file_size) { + file->dirent->file_size = new_end; + } + file->current_offset = new_end; + + SPDK_NOTICELOG("write complete, new offset=%" PRIu64 "\n", file->current_offset); + file->finished = true; +} + +void zvfs_spdk_blob_write_sync_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + if (bserrno) { + SPDK_ERRLOG("write sync error: %d\n", bserrno); + file->finished = true; + return; + } + + if (file->dirent) { + file->dirent->allocated_clusters = + (uint32_t)spdk_blob_get_num_clusters(file->blob); + } + + zvfs_do_write_io(file); +} + +void zvfs_spdk_blob_write_resize_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + if (bserrno) { + SPDK_ERRLOG("write resize error: %d\n", bserrno); + file->finished = true; + return; + } + + spdk_blob_sync_md(file->blob, zvfs_spdk_blob_write_sync_cb, file); +} + +void zvfs_do_write(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + uint64_t end_byte = file->current_offset + file->io_count; + uint64_t need_clusters = zvfs_need_clusters(file->fs, end_byte); + uint64_t cur_clusters = file->dirent ? file->dirent->allocated_clusters + : spdk_blob_get_num_clusters(file->blob); + + SPDK_NOTICELOG("endbyte:%ld, needcluster:%ld, curcluster:%ld\n", end_byte, need_clusters, cur_clusters); + if (need_clusters > cur_clusters) { + uint64_t free_clusters = spdk_bs_free_cluster_count(file->fs->bs); + SPDK_NOTICELOG("free_cluster : %"PRIu64"\n", free_clusters); + if (need_clusters - cur_clusters > free_clusters) { + SPDK_ERRLOG("no free clusters\n"); + file->finished = true; + return; + } + spdk_blob_resize(file->blob, need_clusters, + zvfs_spdk_blob_write_resize_cb, file); + } else { + zvfs_do_write_io(file); + } +} + +// close +void zvfs_do_close(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + spdk_blob_close(file->blob, zvfs_spdk_blob_close_cb, file); +} + +void zvfs_spdk_blob_close_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + if (bserrno) { + SPDK_ERRLOG("blob_close error: %d\n", bserrno); + } + spdk_free(file->dma_buf); + file->dma_buf = NULL; + file->current_offset = 0; + + SPDK_NOTICELOG("close complete\n"); + file->finished = true; +} + +// delete +void zvfs_do_delete(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + spdk_bs_delete_blob(file->fs->bs, file->blob_id, zvfs_spdk_blob_delete_cb, file); +} + +void zvfs_spdk_blob_delete_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + if (bserrno) { + SPDK_ERRLOG("blob_delete error: %d\n", bserrno); + } + + SPDK_NOTICELOG("delete complete\n"); + file->finished = true; +} + +// unmount +void zvfs_do_umount(void *arg) { + + zvfs_t *fs = (zvfs_t *)arg; + + if (fs->bs) { + if (fs->channel) { + spdk_bs_free_io_channel(fs->channel); + } + spdk_bs_unload(fs->bs, zvfs_spdk_bs_unload_cb, fs); + } + +} + +void zvfs_spdk_bs_unload_cb(void *arg, int bserrno) { + + zvfs_t *fs = (zvfs_t *)arg; + fs->finished = true; +} + +// waiter +bool waiter(struct spdk_thread *thread, spdk_msg_fn start_fn, void *ctx, bool *finished) { + + spdk_thread_send_msg(thread, start_fn, ctx); + + int waiter_count = 0; + + do { + spdk_thread_poll(thread, 0, 0); + waiter_count ++; + } while(!(*finished) && waiter_count < WAITER_MAX_TIME); + + while (spdk_thread_poll(thread, 0, 0) > 0) {} + + if (!(*finished) && waiter_count >= WAITER_MAX_TIME) { + return false; // timeout + } + + return true; +} + +// setup +// zvfs.json + +int zvfs_env_setup(void) { + struct spdk_env_opts opts; + spdk_env_opts_init(&opts); + + if (0 != spdk_env_init(&opts)) { + return -1; + } + + spdk_log_set_print_level(SPDK_LOG_NOTICE); + spdk_log_set_level(SPDK_LOG_NOTICE); + spdk_log_open(NULL); + + spdk_thread_lib_init(NULL, 0); + global_thread = spdk_thread_create("global", NULL); + spdk_set_thread(global_thread); + + bool done = false; + + waiter(global_thread, zvfs_json_load_fn, &done, &done); + SPDK_NOTICELOG("json_app_load_done complete\n"); + + return 0; +} + +void zvfs_json_load_fn(void *arg) { + spdk_subsystem_init_from_json_config(json_file, SPDK_DEFAULT_RPC_ADDR, json_app_load_done, + arg, true); + +} + +void json_app_load_done(int rc, void *ctx) { + bool *done = ctx; + *done = true; + + SPDK_NOTICELOG("json_app_load_done\n"); +} + + + + + +// filesystem +// load +int zvfs_mount(struct zvfs_s *fs) { + fs->finished = false; + return waiter(global_thread, zvfs_do_mount, fs, &fs->finished); +} +// unload +int zvfs_umount(struct zvfs_s *fs) { + fs->finished = false; + return waiter(global_thread, zvfs_do_umount, fs, &fs->finished); +} +// file +// create +int zvfs_create(struct zvfs_file_s *file) { + file->finished = false; + return waiter(global_thread, zvfs_do_create, file, &file->finished); +} +// open +int zvfs_open(struct zvfs_file_s *file) { + file->finished = false; + return waiter(global_thread, zvfs_do_open, file, &file->finished); +} +// read +int zvfs_read(struct zvfs_file_s *file, uint8_t *buffer, size_t count) { + file->io_count = count; + file->finished = false; + + bool ok = waiter(global_thread, zvfs_do_read, file, &file->finished); + uint64_t page_off = (file->current_offset - file->io_count) % file->fs->io_unit_size; + memcpy(buffer, (uint8_t *)file->dma_buf + page_off, file->io_count); + + return ok ? (int)file->io_count : -1; +} +// write +int zvfs_write(struct zvfs_file_s *file, const uint8_t *buffer, size_t count) { + file->io_count = count; + file->finished = false; + + memcpy(file->dma_buf, buffer, count); + bool ok = waiter(global_thread, zvfs_do_write, file, &file->finished); + return ok ? (int)count : -1; +} +// close +int zvfs_close(struct zvfs_file_s *file) { + file->finished = false; + return waiter(global_thread, zvfs_do_close, file, &file->finished); +} +// delete +int zvfs_delete(struct zvfs_file_s *file) { + file->finished = false; + return waiter(global_thread, zvfs_do_delete, file, &file->finished); +} + +int main(int argc, char *argv[]) { + + if (zvfs_env_setup()) { + return -1; + } + + SPDK_NOTICELOG("zvfs_env_setup success\n"); + + SPDK_NOTICELOG("\n\n zvfs mount start \n\n"); + zvfs_t *fs = calloc(1, sizeof(zvfs_t)); + zvfs_mount(fs); + + + SPDK_NOTICELOG("\n\n zvfs open start \n\n"); + zvfs_file_t *file = calloc(1, sizeof(zvfs_file_t)); + file->fs = fs; + zvfs_dirent_t *dirent = calloc(1, sizeof(zvfs_dirent_t)); + file->dirent = dirent; + zvfs_create(file); + + SPDK_NOTICELOG("\n\n zvfs write start \n\n"); + char *buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + zvfs_write(file, buffer, strlen(buffer)); + char *buffer2 = "abcdefghijklmnopqrstuvwxyz"; + zvfs_write(file, buffer, strlen(buffer2)); + + + SPDK_NOTICELOG("\n\n zvfs read start \n\n"); + file->current_offset = 0; + char rbuffer[BUFFER_SIZE] = {0}; + int n = zvfs_read(file, rbuffer, BUFFER_SIZE); + SPDK_NOTICELOG("READ BUFFER:%d, %s\n", n, rbuffer); + + SPDK_NOTICELOG("\n\n zvfs close start \n\n"); + zvfs_close(file); + + SPDK_NOTICELOG("\n\n zvfs delete start \n\n"); + zvfs_delete(file); + + free(dirent); + free(file); + + SPDK_NOTICELOG("\n\n zvfs umount start \n\n"); + zvfs_umount(fs); + free(fs); + +} + + diff --git a/zvfs.h b/zvfs.h new file mode 100644 index 0000000..1ccab33 --- /dev/null +++ b/zvfs.h @@ -0,0 +1,91 @@ +#ifndef __ZVFS_HOOK_H__ +#define __ZVFS_HOOK_H__ + +#include + +#include +#include +#include +#include +#include + +#define ZVFS_MAX_FILES 1024 +#define ZVFS_MAX_FD 64 +#define BUFFER_SIZE (1024*8) + +static const char *json_file = "/home/lian/share/10.1-spdk/zvfs/zvfs.json"; +extern struct spdk_thread *global_thread; +static const int WAITER_MAX_TIME = 100000; + +/* 目录项(内存中的目录) */ +typedef struct { + char filename[256]; + spdk_blob_id blob_id; + uint64_t file_size; // 文件逻辑大小(字节) + uint64_t allocated_clusters; // 已分配的cluster数量 + bool is_valid; // false 表示已删除 + int32_t open_count; // 打开的文件句柄数量 +} zvfs_dirent_t; + +/* 文件系统全局结构 */ +typedef struct zvfs_s { + struct spdk_blob_store *bs; + struct spdk_io_channel *channel; + struct spdk_blob *super_blob; // 承载目录日志的blob + uint64_t io_unit_size; // page大小,单位字节 + + /* 目录 */ + zvfs_dirent_t *dirents[ZVFS_MAX_FILES]; // 目录项数组 #define ZVFS_MAX_FILES 1024 + uint32_t dirent_count; // 当前有效项数 + + /* 伪FD表 */ + struct zvfs_file *fd_table[ZVFS_MAX_FD]; // // e.g., #define ZVFS_MAX_FD 64 + int fd_base; // 伪FD起始值,如1000 + int openfd_count; + + /* 元数据 */ + uint32_t magic; // 0x5A563146 (ZV1F) + uint32_t version; // 1 + + + bool finished; +} zvfs_t; + +/* 打开的文件句柄 */ +typedef struct zvfs_file_s { + zvfs_t *fs; + spdk_blob_id blob_id; + struct spdk_blob *blob; + zvfs_dirent_t *dirent; // 指回目录项 file_size/allocated_clusters + + uint64_t current_offset; // 当前读写位置 + int flags; // O_RDONLY / O_RDWR / O_CREAT 等 + int pseudo_fd; + + /* 临时DMA缓冲区(可选:每个file一个,避免每次malloc) */ + void *dma_buf; + uint64_t dma_buf_size; + + size_t io_count; + bool finished; +} zvfs_file_t; + +bool waiter(struct spdk_thread *thread, spdk_msg_fn start_fn, void *ctx, bool *finished); + +int zvfs_env_setup(void); +int zvfs_mount(struct zvfs_s *fs); +int zvfs_umount(struct zvfs_s *fs); +int zvfs_create(struct zvfs_file_s *file); +int zvfs_open(struct zvfs_file_s *file); +int zvfs_read(struct zvfs_file_s *file, uint8_t *buffer, size_t count); +int zvfs_write(struct zvfs_file_s *file, const uint8_t *buffer, size_t count); +int zvfs_close(struct zvfs_file_s *file); +int zvfs_delete(struct zvfs_file_s *file); + +/* POSIX hook API(zvfs_hook.c 实现) */ +int zvfs_open_hook(const char *path, int flags, ...); +ssize_t zvfs_read_hook(int fd, void *buf, size_t count); +ssize_t zvfs_write_hook(int fd, const void *buf, size_t count); +int zvfs_close_hook(int fd); + +#endif \ No newline at end of file diff --git a/zvfs.old/Makefile b/zvfs.old/Makefile new file mode 100755 index 0000000..f609ed0 --- /dev/null +++ b/zvfs.old/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (C) 2017 Intel Corporation +# All rights reserved. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../spdk) +include $(SPDK_ROOT_DIR)/mk/spdk.common.mk +include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk + +APP = zvfs + +C_SRCS := zvfs.c + +SPDK_LIB_LIST = $(ALL_MODULES_LIST) event event_bdev + +include $(SPDK_ROOT_DIR)/mk/spdk.app.mk \ No newline at end of file diff --git a/zvfs.old/zvfs.c b/zvfs.old/zvfs.c new file mode 100755 index 0000000..a415fa1 --- /dev/null +++ b/zvfs.old/zvfs.c @@ -0,0 +1,442 @@ + + +#include + +#include +#include +#include +#include +#include + + + +#define BUFFER_SIZE 512 + + +#define FILENAME_LENGTH 128 + +typedef struct zvfs_s { + + struct spdk_blob_store *blobstore; + uint64_t unit_size; + uint64_t free_cluster_count; + uint64_t num_cluster; + + struct spdk_io_channel *channel; + + bool finished; +} zvfs_t; + +typedef struct zvfs_operation_s { + int (*mount)(struct zvfs_s *fs); + int (*umount)(struct zvfs_s *fs); +} zvfs_operation_t; + +typedef struct zvfs_file_s { + + uint8_t filename[FILENAME_LENGTH]; + + spdk_blob_id blob_id; + struct spdk_blob *blob; + zvfs_t *fs; + + uint8_t *write_buffer; + uint8_t *read_buffer; + + bool finished; + +} zvfs_file_t; + +typedef struct zvfs_file_operation_s { + + int (*open)(struct zvfs_file_s *file); + int (*read)(struct zvfs_file_s *file); + int (*write)(struct zvfs_file_s *file); + int (*close)(struct zvfs_file_s *file); + +} zvfs_file_operation_t; + + + +struct spdk_thread *global_thread = NULL; +static const int WAITER_MAX_TIME = 100000; + +// mount +void zvfs_do_mount(void *arg); +void zvfs_spdk_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx); +void zvfs_spdk_bs_init_cb(void *arg, struct spdk_blob_store *bs, int bserrno); + +// open +void zvfs_do_create(void *arg); +void zvfs_spdk_bs_create_blob_cb(void *arg, spdk_blob_id blobid, int bserrno); +void zvfs_spdk_bs_open_blob_create_cb(void *arg, struct spdk_blob *blb, int bserrno); +void zvfs_spdk_blob_resize_cb(void *arg, int bserrno); +void zvfs_spdk_blob_sync_cb(void *arg, int bserrno); + +// read +void zvfs_do_read(void *arg); +void zvfs_spdk_blob_read_cb(void *arg, int bserrno); + +// write +void zvfs_do_write(void *arg); +void zvfs_spdk_blob_write_cb(void *arg, int bserrno); + + +// close +void zvfs_do_close(void *arg); +void zvfs_spdk_blob_close_cb(void *arg, int bserrno); +void zvfs_spdk_blob_delete_cb(void *arg, int bserrno); + +// waiter +bool waiter(struct spdk_thread *thread, spdk_msg_fn start_fn, void *ctx, bool *finished); + +// setup +int zvfs_env_setup(void); +void zvfs_json_load_fn(void *arg); +void json_app_load_done(int rc, void *ctx); + +// unmount +void zvfs_do_umount(void *arg); +void zvfs_spdk_bs_unload_cb(void *arg, int bserrno); + +// mount +void zvfs_do_mount(void *arg) { + + zvfs_t *fs = (zvfs_t*)arg; + + struct spdk_bs_dev *bs_dev = NULL; + + int rc = spdk_bdev_create_bs_dev_ext("Malloc0", zvfs_spdk_bdev_event_cb, NULL, &bs_dev); + if (rc != 0) { + spdk_app_stop(0); + } + + spdk_bs_init(bs_dev, NULL, zvfs_spdk_bs_init_cb, fs); + + SPDK_NOTICELOG("zvfs_entry\n"); + +} + +void zvfs_spdk_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, + void *event_ctx) { + SPDK_NOTICELOG("zvfs_spdk_bdev_event_cb\n"); +} + +void zvfs_spdk_bs_init_cb(void *arg, struct spdk_blob_store *bs, int bserrno) { + zvfs_t *fs = (zvfs_t*)arg; + + uint64_t io_unit_size = spdk_bs_get_io_unit_size(bs); + SPDK_NOTICELOG("io_unit_size : %"PRIu64"\n", io_unit_size); + + fs->unit_size = io_unit_size; + fs->blobstore = bs; + + fs->channel = spdk_bs_alloc_io_channel(fs->blobstore); + if (fs->channel == NULL) { + return ; + } + + fs->finished = true; + + SPDK_NOTICELOG("mount finished\n"); +} + + +// open +void zvfs_do_create(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + spdk_bs_create_blob(file->fs->blobstore, zvfs_spdk_bs_create_blob_cb, file); + +} + +void zvfs_spdk_bs_create_blob_cb(void *arg, spdk_blob_id blobid, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + file->blob_id = blobid; + SPDK_NOTICELOG("blobid : %"PRIu64"\n", blobid); + + spdk_bs_open_blob(file->fs->blobstore, blobid, zvfs_spdk_bs_open_blob_create_cb, file); +} + +void zvfs_spdk_bs_open_blob_create_cb(void *arg, struct spdk_blob *blb, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + file->blob = blb; + + uint64_t free_cluster = spdk_bs_free_cluster_count(file->fs->blobstore); // + SPDK_NOTICELOG("free_cluster : %"PRIu64"\n", free_cluster); + file->fs->free_cluster_count = free_cluster; + + spdk_blob_resize(blb, free_cluster, zvfs_spdk_blob_resize_cb, file); + +} + +void zvfs_spdk_blob_resize_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + uint64_t total = spdk_blob_get_num_clusters(file->blob); + file->fs->num_cluster = total; + + SPDK_NOTICELOG("resize blob :%"PRIu64"\n", total); + + spdk_blob_sync_md(file->blob, zvfs_spdk_blob_sync_cb, file); + +} + +void zvfs_spdk_blob_sync_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + file->write_buffer = spdk_malloc(BUFFER_SIZE, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if (file->write_buffer == NULL) { + return ; + } + + file->read_buffer = spdk_malloc(BUFFER_SIZE, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if (file->read_buffer == NULL) { + return ; + } + + + SPDK_NOTICELOG("open complete\n"); + + file->finished = true; +} + +// read +void zvfs_do_read(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + memset(file->read_buffer, 0x0, BUFFER_SIZE); + spdk_blob_io_read(file->blob, file->fs->channel, file->read_buffer, + 0, 1, zvfs_spdk_blob_read_cb, file); +} + +void zvfs_spdk_blob_read_cb(void *arg, int bserrno) { + + zvfs_file_t *file = (zvfs_file_t *)arg; + + SPDK_NOTICELOG("READ BUFFER : %s\n", file->read_buffer); + + file->finished = true; +} + + +// write +void zvfs_do_write(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + spdk_blob_io_write(file->blob, file->fs->channel, file->write_buffer, + 0, 1, zvfs_spdk_blob_write_cb, file); +} + +void zvfs_spdk_blob_write_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + SPDK_NOTICELOG("write complete\n"); + + file->finished = true; +} + +// close +void zvfs_do_close(void *arg) { + zvfs_file_t *file = (zvfs_file_t *)arg; + spdk_blob_close(file->blob, zvfs_spdk_blob_close_cb, file); +} + +void zvfs_spdk_blob_close_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + spdk_bs_delete_blob(file->fs->blobstore, file->blob_id, zvfs_spdk_blob_delete_cb, file); +} + +void zvfs_spdk_blob_delete_cb(void *arg, int bserrno) { + zvfs_file_t *file = (zvfs_file_t *)arg; + + spdk_free(file->write_buffer); + spdk_free(file->read_buffer); + + SPDK_NOTICELOG("close complete\n"); + file->finished = true; +} + +// unmount +void zvfs_do_umount(void *arg) { + + zvfs_t *fs = (zvfs_t *)arg; + + if (fs->blobstore) { + if (fs->channel) { + spdk_bs_free_io_channel(fs->channel); + } + spdk_bs_unload(fs->blobstore, zvfs_spdk_bs_unload_cb, fs); + } + +} + +void zvfs_spdk_bs_unload_cb(void *arg, int bserrno) { + + zvfs_t *fs = (zvfs_t *)arg; + fs->finished = true; +} + +// waiter +bool waiter(struct spdk_thread *thread, spdk_msg_fn start_fn, void *ctx, bool *finished) { + + spdk_thread_send_msg(thread, start_fn, ctx); + + int waiter_count = 0; + + do { + spdk_thread_poll(thread, 0, 0); + waiter_count ++; + } while(!(*finished) && waiter_count < WAITER_MAX_TIME); + + if (!(*finished) && waiter_count >= WAITER_MAX_TIME) { + return false; // timeout + } + + return true; +} + +// setup +// zvfs.json +static const char *json_file = "/home/lian/share/10.1-spdk/zvfs/zvfs.json"; + +int zvfs_env_setup(void) { + struct spdk_env_opts opts; + spdk_env_opts_init(&opts); + + if (0 != spdk_env_init(&opts)) { + return -1; + } + + spdk_log_set_print_level(SPDK_LOG_NOTICE); + spdk_log_set_level(SPDK_LOG_NOTICE); + spdk_log_open(NULL); + + spdk_thread_lib_init(NULL, 0); + global_thread = spdk_thread_create("global", NULL); + spdk_set_thread(global_thread); + + bool done = false; + + waiter(global_thread, zvfs_json_load_fn, &done, &done); + SPDK_NOTICELOG("json_app_load_done complete\n"); + + + return 0; + +} + +void zvfs_json_load_fn(void *arg) { + spdk_subsystem_init_from_json_config(json_file, SPDK_DEFAULT_RPC_ADDR, json_app_load_done, + arg, true); + +} + +void json_app_load_done(int rc, void *ctx) { + bool *done = ctx; + *done = true; + + SPDK_NOTICELOG("json_app_load_done\n"); +} + + +// filesystem +// load +static int zvfs_mount(struct zvfs_s *fs) { + + fs->finished = false; + + return waiter(global_thread, zvfs_do_mount, fs, &fs->finished); +} + + +// unload +static int zvfs_umount(struct zvfs_s *fs) { + + fs->finished = false; + + return waiter(global_thread, zvfs_do_umount, fs, &fs->finished); +} + + +// file +// open +static int zvfs_create(struct zvfs_file_s *file) { + + file->finished = false; + + return waiter(global_thread, zvfs_do_create, file, &file->finished); + +} + + +// read +static int zvfs_read(struct zvfs_file_s *file, uint8_t *buffer, size_t count) { + + file->finished = false; + waiter(global_thread, zvfs_do_read, file, &file->finished); + + int len = strlen(file->read_buffer); + memcpy(buffer, file->read_buffer, len); // + + return len; +} + + +// write +static int zvfs_write(struct zvfs_file_s *file, const uint8_t *buffer, size_t count) { + + file->finished = false; + + memcpy(file->write_buffer, buffer, count); // count / 512 + + return waiter(global_thread, zvfs_do_write, file, &file->finished); +} + +// close +static int zvfs_close(struct zvfs_file_s *file) { + + file->finished = false; + + return waiter(global_thread, zvfs_do_close, file, &file->finished); +} + + +int main(int argc, char *argv[]) { + + if (zvfs_env_setup()) { + return -1; + } + + SPDK_NOTICELOG("zvfs_env_setup success\n"); + + SPDK_NOTICELOG("\n\n zvfs mount start \n\n"); + zvfs_t *fs = calloc(1, sizeof(zvfs_t)); + zvfs_mount(fs); + + SPDK_NOTICELOG("\n\n zvfs open start \n\n"); + zvfs_file_t *file = calloc(1, sizeof(zvfs_file_t)); + file->fs = fs; + zvfs_create(file); + + + SPDK_NOTICELOG("\n\n zvfs write start \n\n"); + char *buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + zvfs_write(file, buffer, strlen(buffer)); + + + SPDK_NOTICELOG("\n\n zvfs read start \n\n"); + char rbuffer[BUFFER_SIZE] = {0}; + zvfs_read(file, rbuffer, BUFFER_SIZE); + SPDK_NOTICELOG("READ BUFFER: %s\n", rbuffer); + + SPDK_NOTICELOG("\n\n zvfs close start \n\n"); + zvfs_close(file); + + free(file); + + SPDK_NOTICELOG("\n\n zvfs umount start \n\n"); + zvfs_umount(fs); + free(fs); + +} + + diff --git a/zvfs.old/zvfs.json b/zvfs.old/zvfs.json new file mode 100644 index 0000000..10ded9d --- /dev/null +++ b/zvfs.old/zvfs.json @@ -0,0 +1,17 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "method": "bdev_malloc_create", + "params": { + "name": "Malloc0", + "num_blocks": 32768, + "block_size": 512 + } + } + ] + } + ] +} diff --git a/zvfs.old/zvfs.old.c b/zvfs.old/zvfs.old.c new file mode 100644 index 0000000..9fadc41 --- /dev/null +++ b/zvfs.old/zvfs.old.c @@ -0,0 +1,176 @@ + + +#include "spdk/event.h" +#include "spdk/blob.h" +#include "spdk/bdev.h" +#include "spdk/blob_bdev.h" + +#define BUFFER_SIZE 512 + +typedef struct zv1ianfs_ctx_s { + struct spdk_blob_store *blobstore; + uint64_t unit_size; + spdk_blob_id blob_id; + struct spdk_blob *blob; + uint64_t free_cluster_count; + uint64_t num_cluster; + uint8_t *write_buffer; + uint8_t *read_buffer; + struct spdk_io_channel *channel; +} zv1ianfs_ctx_t; + +void zv1ianfs_spdk_bs_unload_cb(void *cb_arg, int bserrno); +void zv1ianfs_spdk_delete_blob_cb(void *cb_arg, int bserrno); +void zv1ianfs_spdk_blob_close_cb(void *cb_arg, int bserrno); +void zv1ianfs_spdk_blob_io_read_cb(void *cb_arg, int bserrno); +void zv1ianfs_spdk_blob_io_write_cb(void *cb_arg, int bserrno); +void zv1ianfs_spdk_blob_sync_cb(void *cb_arg, int bserrno); +void zv1ianfs_spdk_blob_resize(void *cb_arg, int bserrno); +void zv1ianfs_spdk_bs_open_blob_cb(void *cb_arg, struct spdk_blob *blb, int bserrno); +void zv1ianfs_spdk_bs_create_blob_cb(void *cb_arg, spdk_blob_id blobid, int bserrno); +void zv1ianfs_spdk_bs_init_cb(void *cb_arg, struct spdk_blob_store *bs, int bserrno); +void zv1ianfs_spdk_bdev_event_cb (enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx); +void zv1ianfs_do_mount(void *ctx); + +void zv1ianfs_spdk_bs_unload_cb(void *cb_arg, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + spdk_app_stop(0); + + spdk_free(ctx->write_buffer); + spdk_free(ctx->read_buffer); + free(ctx); +} + +void zv1ianfs_spdk_delete_blob_cb(void *cb_arg, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + if(ctx->blobstore) { + if(ctx->channel) { + spdk_bs_free_io_channel(ctx->channel); + } + spdk_bs_unload(ctx->blobstore, zv1ianfs_spdk_bs_unload_cb, ctx); + } +} + +void zv1ianfs_spdk_blob_close_cb(void *cb_arg, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + spdk_bs_delete_blob(ctx->blobstore, ctx->blob_id, zv1ianfs_spdk_delete_blob_cb, ctx); +} + +void zv1ianfs_spdk_blob_io_read_cb(void *cb_arg, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + SPDK_NOTICELOG("READ BUFFER : %s\n", ctx->read_buffer); + + spdk_blob_close(ctx->blob, zv1ianfs_spdk_blob_close_cb ,ctx); +} + +void zv1ianfs_spdk_blob_io_write_cb(void *cb_arg, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + SPDK_NOTICELOG("WRITE COMPLETE\n"); + + uint8_t *rbuffer = spdk_malloc(512, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if(rbuffer == NULL){ + spdk_app_stop(-1); + return ; + } + memset(rbuffer, 0x0, BUFFER_SIZE); + ctx->read_buffer = rbuffer; + + spdk_blob_io_read(ctx->blob, ctx->channel, rbuffer, 0, 1, zv1ianfs_spdk_blob_io_read_cb, ctx); +} + +void zv1ianfs_spdk_blob_sync_cb(void *cb_arg, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + uint8_t *wbuffer = spdk_malloc(512, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if(wbuffer == NULL){ + spdk_app_stop(-1); + return ; + } + memset(wbuffer, 'A', BUFFER_SIZE); + *(wbuffer+BUFFER_SIZE-1) = '\0'; + ctx->write_buffer = wbuffer; + + ctx->channel = spdk_bs_alloc_io_channel(ctx->blobstore); + if(ctx->channel == NULL){ + spdk_app_stop(-1); + } + + spdk_blob_io_write(ctx->blob, ctx->channel, wbuffer, 0, 1, zv1ianfs_spdk_blob_io_write_cb, ctx); +} + +void zv1ianfs_spdk_blob_resize(void *cb_arg, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + + uint64_t total = spdk_blob_get_num_clusters(ctx->blob); + ctx->num_cluster = total; + + SPDK_NOTICELOG("resize blob : %"PRIu64"\n", total); + + spdk_blob_sync_md(ctx->blob, zv1ianfs_spdk_blob_sync_cb, ctx); +} + +void zv1ianfs_spdk_bs_open_blob_cb(void *cb_arg, struct spdk_blob *blb, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + ctx->blob = blb; + + uint64_t free_cluster = spdk_bs_free_cluster_count(ctx->blobstore); + ctx->free_cluster_count = free_cluster; + + SPDK_NOTICELOG("free_cluster : %"PRIu64"\n", free_cluster); + spdk_blob_resize(blb, free_cluster, zv1ianfs_spdk_blob_resize, ctx); +} + +void zv1ianfs_spdk_bs_create_blob_cb(void *cb_arg, spdk_blob_id blobid, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + ctx->blob_id = blobid; + + SPDK_NOTICELOG("blobid : %"PRIu64"\n", blobid); + spdk_bs_open_blob(ctx->blobstore, blobid, zv1ianfs_spdk_bs_open_blob_cb, ctx); +} + +void zv1ianfs_spdk_bs_init_cb(void *cb_arg, struct spdk_blob_store *bs, int bserrno){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)cb_arg; + ctx->blobstore = bs; + + uint64_t io_unit_size = spdk_bs_get_io_unit_size(bs); + ctx->unit_size = io_unit_size; + + SPDK_NOTICELOG("io_unit_size: %"PRIu64"\n", io_unit_size); + spdk_bs_create_blob(bs, zv1ianfs_spdk_bs_create_blob_cb, ctx); +} + +void zv1ianfs_spdk_bdev_event_cb (enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx){ + SPDK_NOTICELOG("zv1ianfs_spdk_bdev_event_cb called\n"); +} + +void zv1ianfs_do_mount(void *arg){ + zv1ianfs_ctx_t *ctx = (zv1ianfs_ctx_t *)arg; + + struct spdk_bs_dev *bs_dev = NULL; + + int rc = spdk_bdev_create_bs_dev_ext("Malloc0", zv1ianfs_spdk_bdev_event_cb, NULL, &bs_dev); + if(rc != 0){ + SPDK_NOTICELOG("错误: 无法创建 bs_dev, 错误码 = %d\n", rc); + spdk_app_stop(-1); + return; + } + + spdk_bs_init(bs_dev, NULL, zv1ianfs_spdk_bs_init_cb, ctx); + + SPDK_NOTICELOG("zv1ianfs_entry called\n"); +} + + +int main(int argc, char *argv[]){ + + struct spdk_app_opts opts = {}; + + spdk_app_opts_init(&opts, sizeof(opts)); + opts.name = "zv1ianfs"; + opts.json_config_file = argv[1]; + + zv1ianfs_ctx_t *ctx = calloc(1, sizeof(zv1ianfs_ctx_t)); + + spdk_app_start(&opts, zv1ianfs_do_mount, ctx); + + SPDK_NOTICELOG("hello spdk\n"); +} \ No newline at end of file diff --git a/zvfs_hook.c b/zvfs_hook.c new file mode 100644 index 0000000..a1e95fd --- /dev/null +++ b/zvfs_hook.c @@ -0,0 +1,359 @@ +#include "zvfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/* ------------------------------------------------------------------ */ +/* 全局状态 */ +/* ------------------------------------------------------------------ */ + +static zvfs_t *g_fs = NULL; /* 全局文件系统,NULL 表示未初始化 */ +static bool g_mounted = false; + +/* 元数据文件路径 */ +static const char *META_FILE = "/home/lian/share/10.1-spdk/zvfs/zvfs_meta.txt"; + +/* 伪 fd 起始值,避免和真实 fd 冲突 */ +#define FD_BASE 1000 + + +/* ------------------------------------------------------------------ */ +/* 元数据文件 I/O */ +/* ------------------------------------------------------------------ */ + +/* + * 格式:每行一条记录,字段用空格分隔 + * filename blob_id file_size allocated_clusters + * + * 例: + * hello.txt 4294967296 26 1 + */ + +static int meta_load(zvfs_t *fs) { + int fd = open(META_FILE, O_RDONLY); + if (fd < 0) { + /* 文件不存在,当作空目录 */ + fs->dirent_count = 0; + return 0; + } + + /* 一次性读进来 */ + char buf[4096] = {0}; + ssize_t n = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (n <= 0) return 0; + + char *line = buf; + while (*line) { + /* 找行尾 */ + char *nl = strchr(line, '\n'); + if (nl) *nl = '\0'; + + if (*line == '\0') { + line = nl ? nl + 1 : line + strlen(line); + continue; + } + + if (fs->dirent_count >= ZVFS_MAX_FILES) break; + + zvfs_dirent_t *d = calloc(1, sizeof(zvfs_dirent_t)); + if (!d) break; + + int ret = sscanf(line, "%255s %"PRIu64" %"PRIu64" %"PRIu32, + d->filename, + &d->blob_id, + &d->file_size, + &d->allocated_clusters); + if (ret == 4) { + d->is_valid = true; + d->open_count = 0; + fs->dirents[fs->dirent_count++] = d; + } else { + free(d); + } + + line = nl ? nl + 1 : line + strlen(line); + } + + return 0; +} + +static int meta_save(zvfs_t *fs) { + int fd = open(META_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) return -1; + + for (uint32_t i = 0; i < fs->dirent_count; i++) { + zvfs_dirent_t *d = fs->dirents[i]; + if (!d || !d->is_valid) continue; + + char line[512]; + int len = snprintf(line, sizeof(line), "%s %"PRIu64" %"PRIu64" %"PRIu32"\n", + d->filename, d->blob_id, d->file_size, d->allocated_clusters); + write(fd, line, len); + } + + close(fd); + return 0; +} + + +/* ------------------------------------------------------------------ */ +/* 初始化(第一次 open 时调用) */ +/* ------------------------------------------------------------------ */ + +static int zvfs_ensure_mounted(void) { + if (g_mounted) return 0; + + g_fs = calloc(1, sizeof(zvfs_t)); + if (!g_fs) return -1; + + g_fs->fd_base = FD_BASE; + + /* 加载元数据 */ + if (meta_load(g_fs) != 0) { + free(g_fs); + g_fs = NULL; + return -1; + } + + /* 初始化 SPDK 环境并 mount */ + if (zvfs_env_setup() != 0) { + free(g_fs); + g_fs = NULL; + return -1; + } + + if (!zvfs_mount(g_fs)) { + free(g_fs); + g_fs = NULL; + return -1; + } + + g_mounted = true; + return 0; +} + + +/* ------------------------------------------------------------------ */ +/* 目录查找 / 分配 */ +/* ------------------------------------------------------------------ */ + +static zvfs_dirent_t *dirent_find(const char *filename) { + for (uint32_t i = 0; i < g_fs->dirent_count; i++) { + zvfs_dirent_t *d = g_fs->dirents[i]; + if (d && d->is_valid && strcmp(d->filename, filename) == 0) + return d; + } + return NULL; +} + +static zvfs_dirent_t *dirent_alloc(const char *filename) { + if (g_fs->dirent_count >= ZVFS_MAX_FILES) return NULL; + + zvfs_dirent_t *d = calloc(1, sizeof(zvfs_dirent_t)); + if (!d) return NULL; + + strncpy(d->filename, filename, sizeof(d->filename) - 1); + d->is_valid = true; + d->open_count = 0; + d->file_size = 0; + d->allocated_clusters = 0; + + g_fs->dirents[g_fs->dirent_count++] = d; + return d; +} + + +/* ------------------------------------------------------------------ */ +/* fd 表管理 */ +/* ------------------------------------------------------------------ */ + +/* 分配一个空闲 slot,返回伪 fd;失败返回 -1 */ +static int fd_alloc(zvfs_file_t *file) { + for (int i = 0; i < ZVFS_MAX_FD; i++) { + if (g_fs->fd_table[i] == NULL) { + g_fs->fd_table[i] = file; + file->pseudo_fd = FD_BASE + i; + g_fs->openfd_count++; + return file->pseudo_fd; + } + } + return -1; +} + +/* 释放 slot */ +static void fd_free(int pseudo_fd) { + int idx = pseudo_fd - FD_BASE; + if (idx < 0 || idx >= ZVFS_MAX_FD) return; + g_fs->fd_table[idx] = NULL; + g_fs->openfd_count--; +} + +/* 通过伪 fd 查找 file */ +static zvfs_file_t *fd_lookup(int pseudo_fd) { + int idx = pseudo_fd - FD_BASE; + if (idx < 0 || idx >= ZVFS_MAX_FD) return NULL; + return g_fs->fd_table[idx]; +} + +/* ------------------------------------------------------------------ */ +/* POSIX hook: open */ +/* ------------------------------------------------------------------ */ + +int zvfs_open_hook(const char *path, int flags, ...) { + + /* 确保 fs 已经 mount */ + if (zvfs_ensure_mounted() != 0) { + errno = EIO; + return -1; + } + + /* 查找 dirent */ + zvfs_dirent_t *dirent = dirent_find(path); + + if (!dirent) { + /* 文件不存在 */ + if (!(flags & O_CREAT)) { + errno = ENOENT; + return -1; + } + /* 新建 dirent */ + dirent = dirent_alloc(path); + if (!dirent) { + errno = ENOMEM; + return -1; + } + } + + /* 创建 file 句柄 */ + zvfs_file_t *file = calloc(1, sizeof(zvfs_file_t)); + if (!file) { + errno = ENOMEM; + return -1; + } + + file->fs = g_fs; + file->dirent = dirent; + file->flags = flags; + file->current_offset = 0; + + int ok; + if (dirent->blob_id == 0) { + /* 新文件:create blob,open 时不 resize,write 时按需扩容 */ + file->blob_id = 0; + ok = zvfs_create(file); /* 内部 create → open → (no resize) → alloc dma_buf */ + /* 把新分配的 blob_id 写回 dirent */ + dirent->blob_id = file->blob_id; + } else { + /* 已有文件:直接 open 已有 blob */ + file->blob_id = dirent->blob_id; + ok = zvfs_open(file); + } + + if (!ok) { + free(file); + errno = EIO; + return -1; + } + + /* 分配伪 fd */ + int fd = fd_alloc(file); + if (fd < 0) { + zvfs_close(file); + free(file); + errno = EMFILE; + return -1; + } + + dirent->open_count++; + return fd; +} + + +/* ------------------------------------------------------------------ */ +/* POSIX hook: read */ +/* ------------------------------------------------------------------ */ +ssize_t zvfs_read_hook(int fd, void *buf, size_t count) { + zvfs_file_t *file = fd_lookup(fd); + if (!file) { + errno = EBADF; + return -1; + } + + if (!(file->flags & O_RDWR) && (file->flags & O_WRONLY)) { + errno = EBADF; + return -1; + } + + return zvfs_read(file, (uint8_t *)buf, count); +} + + +/* ------------------------------------------------------------------ */ +/* POSIX hook: write */ +/* ------------------------------------------------------------------ */ + +ssize_t zvfs_write_hook(int fd, const void *buf, size_t count) { + zvfs_file_t *file = fd_lookup(fd); + if (!file) { + errno = EBADF; + return -1; + } + + return zvfs_write(file, (const uint8_t *)buf, count); +} + + +/* ------------------------------------------------------------------ */ +/* POSIX hook: close */ +/* ------------------------------------------------------------------ */ + +int zvfs_close_hook(int fd) { + zvfs_file_t *file = fd_lookup(fd); + if (!file) { + errno = EBADF; + return -1; + } + + zvfs_dirent_t *dirent = file->dirent; + + /* 关闭 blob */ + zvfs_close(file); + + /* 释放 fd slot */ + fd_free(fd); + + /* 更新引用计数 */ + if (dirent) { + dirent->open_count--; + if(dirent->open_count == 0 && !dirent->is_valid){ + zvfs_delete(file); + } + } + + free(file); + + /* 如果没有任何打开的文件了,保存元数据并 unmount */ + if (g_fs->openfd_count == 0) { + meta_save(g_fs); + zvfs_umount(g_fs); + + /* 释放所有 dirent */ + for (uint32_t i = 0; i < g_fs->dirent_count; i++) { + free(g_fs->dirents[i]); + g_fs->dirents[i] = NULL; + } + + free(g_fs); + g_fs = NULL; + g_mounted = false; + } + + return 0; +} \ No newline at end of file