#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; }