This commit is contained in:
2026-03-09 07:53:06 +00:00
parent 975afaf3f0
commit 470412a1c2
82 changed files with 7094 additions and 5234 deletions

301
src/hook/zvfs_hook_seek.c Normal file
View File

@@ -0,0 +1,301 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "zvfs_hook_seek.h"
#include "zvfs_hook_init.h"
#include "zvfs_hook_reentrant.h"
#include "fs/zvfs.h"
#include "fs/zvfs_open_file.h"
#include "fs/zvfs_inode.h"
#include "fs/zvfs_path_entry.h"
#include "spdk_engine/io_engine.h"
#include <errno.h>
#include <fcntl.h>
#include <linux/falloc.h> /* FALLOC_FL_* */
#include <pthread.h>
#include <stdint.h>
/* ------------------------------------------------------------------ */
/* lseek / lseek64 */
/* ------------------------------------------------------------------ */
off_t
lseek(int fd, off_t offset, int whence)
{
ZVFS_HOOK_ENTER();
struct zvfs_open_file *of = NULL;
if (!ZVFS_IN_HOOK()) {
pthread_mutex_lock(&g_fs.fd_mu);
of = openfile_lookup(fd);
pthread_mutex_unlock(&g_fs.fd_mu);
}
if (!of) {
off_t r = real_lseek(fd, offset, whence);
ZVFS_HOOK_LEAVE();
return r;
}
zvfs_ensure_init();
/*
* O_APPEND fd 的 lseekPOSIX 允许 lseek但下次 write 时
* 仍会从文件末尾写。lseek 只影响 read 的位置。
* 我们照常更新 of->offset。
*/
pthread_mutex_lock(&of->inode->mu); /* SEEK_END 需读 logical_size */
uint64_t new_off = openfile_seek(of, (int64_t)offset, whence);
pthread_mutex_unlock(&of->inode->mu);
if (new_off == (uint64_t)-1) {
ZVFS_HOOK_LEAVE();
return (off_t)-1;
}
ZVFS_HOOK_LEAVE();
return (off_t)new_off;
}
off_t lseek64(int fd, off_t offset, int whence)
{
return lseek(fd, offset, whence);
}
/* ------------------------------------------------------------------ */
/* 内部:按 inode 指针做 truncatepath / fd 路径共用) */
/* ------------------------------------------------------------------ */
/*
* zvfs_truncate_by_inode - 对有 handle 的 openfile 做 truncate。
* 找到任意一个打开该 inode 的 openfile 取其 handle。
*/
static int
zvfs_truncate_inode_with_handle(struct zvfs_inode *inode,
int real_fd, uint64_t new_size)
{
/* 在 fd_table 里找一个指向该 inode 的 openfile 取 handle */
struct zvfs_blob_handle *handle = NULL;
pthread_mutex_lock(&g_fs.fd_mu);
struct zvfs_open_file *of, *tmp;
HASH_ITER(hh, g_fs.fd_table, of, tmp) {
(void)tmp;
if (of->inode == inode) {
handle = of->handle;
break;
}
}
pthread_mutex_unlock(&g_fs.fd_mu);
pthread_mutex_lock(&inode->mu);
uint64_t old_size = inode->logical_size;
pthread_mutex_unlock(&inode->mu);
if (new_size != old_size && handle) {
if (blob_resize(handle, new_size) < 0) {
errno = EIO;
return -1;
}
} else if (new_size != old_size && !handle) {
/*
* 文件未被打开:需要临时 blob_open。
* 这种情况下 truncate(path, ...) 被调用但文件没有 fd。
*/
handle = blob_open(inode->blob_id);
if (!handle) { errno = EIO; return -1; }
int rc = blob_resize(handle, new_size);
blob_close(handle);
if (rc < 0) { errno = EIO; return -1; }
}
pthread_mutex_lock(&inode->mu);
inode_update_size(inode, real_fd, new_size);
pthread_mutex_unlock(&inode->mu);
return 0;
}
/* ------------------------------------------------------------------ */
/* ftruncate / ftruncate64 */
/* ------------------------------------------------------------------ */
int
ftruncate(int fd, off_t length)
{
ZVFS_HOOK_ENTER();
struct zvfs_open_file *of = NULL;
if (!ZVFS_IN_HOOK()) {
pthread_mutex_lock(&g_fs.fd_mu);
of = openfile_lookup(fd);
pthread_mutex_unlock(&g_fs.fd_mu);
}
if (!of) {
int r = real_ftruncate(fd, length);
ZVFS_HOOK_LEAVE();
return r;
}
zvfs_ensure_init();
if (length < 0) { errno = EINVAL; ZVFS_HOOK_LEAVE(); return -1; }
int r = zvfs_truncate_inode_with_handle(of->inode, fd, (uint64_t)length);
ZVFS_HOOK_LEAVE();
return r;
}
int ftruncate64(int fd, off_t length) { return ftruncate(fd, length); }
/* ------------------------------------------------------------------ */
/* truncate / truncate64按路径 */
/* ------------------------------------------------------------------ */
int
truncate(const char *path, off_t length)
{
ZVFS_HOOK_ENTER();
if (ZVFS_IN_HOOK() || !zvfs_is_zvfs_path(path)) {
int r = real_truncate(path, length);
ZVFS_HOOK_LEAVE();
return r;
}
zvfs_ensure_init();
if (length < 0) { errno = EINVAL; ZVFS_HOOK_LEAVE(); return -1; }
/* 查 path_cache 拿 inode */
pthread_mutex_lock(&g_fs.path_mu);
struct zvfs_path_entry *pe = path_cache_lookup(path);
struct zvfs_inode *inode = pe ? pe->inode : NULL;
pthread_mutex_unlock(&g_fs.path_mu);
if (!inode) {
/*
* inode 不在缓存:文件存在于 FS 但从未被 open。
* 需要读 xattr 拿 blob_id临时构建 inode。
* 最简单的做法:先 real_open再走 zvfs 路径,再 real_close。
* 这里直接调 real_truncate 改 st_size但 blob 不会被截断。
*
* 更正确的做法open + ftruncate + close。
* 调用方通常不会在 file 未被打开的情况下做 truncate
* 所以这里先报 ENOENT找不到 zvfs inode作为安全兜底。
*/
errno = ENOENT;
ZVFS_HOOK_LEAVE();
return -1;
}
int r = zvfs_truncate_inode_with_handle(inode, -1, (uint64_t)length);
/* 同步真实文件 st_sizereal_truncate 更新磁盘元数据) */
if (r == 0)
real_truncate(path, length);
ZVFS_HOOK_LEAVE();
return r;
}
int truncate64(const char *path, off_t length) { return truncate(path, length); }
/* ------------------------------------------------------------------ */
/* fallocate */
/* ------------------------------------------------------------------ */
int
fallocate(int fd, int mode, off_t offset, off_t len)
{
ZVFS_HOOK_ENTER();
struct zvfs_open_file *of = NULL;
if (!ZVFS_IN_HOOK()) {
pthread_mutex_lock(&g_fs.fd_mu);
of = openfile_lookup(fd);
pthread_mutex_unlock(&g_fs.fd_mu);
}
if (!of) {
int r = real_fallocate(fd, mode, offset, len);
ZVFS_HOOK_LEAVE();
return r;
}
zvfs_ensure_init();
if (offset < 0 || len <= 0) { errno = EINVAL; ZVFS_HOOK_LEAVE(); return -1; }
/* FALLOC_FL_PUNCH_HOLE打孔暂不支持 */
if (mode & FALLOC_FL_PUNCH_HOLE) {
errno = ENOTSUP;
ZVFS_HOOK_LEAVE();
return -1;
}
/* FALLOC_FL_KEEP_SIZE预分配但不改变文件逻辑大小直接返回 0 */
if (mode & FALLOC_FL_KEEP_SIZE) {
ZVFS_HOOK_LEAVE();
return 0;
}
/*
* 普通 fallocatemode == 0
* 确保 [offset, offset+len) 范围内的空间被"分配"。
* zvfs 的语义:把 logical_size 扩展到 max(logical_size, offset+len)。
* 不提前 blob_resize因为 SPDK cluster 按写入时分配更高效。
*/
uint64_t new_end = (uint64_t)offset + (uint64_t)len;
pthread_mutex_lock(&of->inode->mu);
if (new_end > of->inode->logical_size)
inode_update_size(of->inode, fd, new_end);
pthread_mutex_unlock(&of->inode->mu);
ZVFS_HOOK_LEAVE();
return 0;
}
/* ------------------------------------------------------------------ */
/* posix_fallocate */
/* ------------------------------------------------------------------ */
int
posix_fallocate(int fd, off_t offset, off_t len)
{
ZVFS_HOOK_ENTER();
struct zvfs_open_file *of = NULL;
if (!ZVFS_IN_HOOK()) {
pthread_mutex_lock(&g_fs.fd_mu);
of = openfile_lookup(fd);
pthread_mutex_unlock(&g_fs.fd_mu);
}
if (!of) {
int r = real_posix_fallocate(fd, offset, len);
ZVFS_HOOK_LEAVE();
return r;
}
zvfs_ensure_init();
/*
* posix_fallocate 不接受 mode 参数,语义等价于 fallocate(fd, 0, ...)。
* 注意posix_fallocate 出错时返回错误码(正值),不设置 errno。
*/
if (offset < 0 || len <= 0) { ZVFS_HOOK_LEAVE(); return EINVAL; }
uint64_t new_end = (uint64_t)offset + (uint64_t)len;
pthread_mutex_lock(&of->inode->mu);
if (new_end > of->inode->logical_size)
inode_update_size(of->inode, fd, new_end);
pthread_mutex_unlock(&of->inode->mu);
ZVFS_HOOK_LEAVE();
return 0;
}