zvfs: 重构核心读写逻辑并新增 POSIX hook;引入目录元数据与伪 fd;分离创建、打开、关闭、删除的逻辑;

This commit is contained in:
2026-02-22 14:46:17 +00:00
parent f216f73dda
commit 31dc307d0b
17 changed files with 1931 additions and 1727 deletions

359
zvfs_hook.c Normal file
View File

@@ -0,0 +1,359 @@
#include "zvfs.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
/* ------------------------------------------------------------------ */
/* 全局状态 */
/* ------------------------------------------------------------------ */
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 blobopen 时不 resizewrite 时按需扩容 */
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;
}