bugfix: OFD:FLAGS
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <spdk/blob_bdev.h>
|
||||
#include <spdk/thread.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@@ -133,6 +134,31 @@ static void push_err_resp(struct zvfs_req *req, int status) {
|
||||
zvfs_conn_submit_resp(resp);
|
||||
}
|
||||
|
||||
static uint32_t handle_status_flags_from_open_flags(uint32_t open_flags) {
|
||||
const uint32_t keep_mask = O_ACCMODE | O_APPEND | O_NONBLOCK | O_ASYNC;
|
||||
return open_flags & keep_mask;
|
||||
}
|
||||
|
||||
static int handle_state_init(struct zvfs_blob_handle *handle, uint32_t open_flags) {
|
||||
if (!handle) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
handle->current_offset = 0;
|
||||
handle->status_flags = handle_status_flags_from_open_flags(open_flags);
|
||||
if (pthread_mutex_init(&handle->state_mu, NULL) != 0) {
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_state_destroy(struct zvfs_blob_handle *handle) {
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
pthread_mutex_destroy(&handle->state_mu);
|
||||
}
|
||||
|
||||
/** ===========================================================
|
||||
* bdev / blobstore 初始化(仅在 md 线程上执行)
|
||||
* 初始化阶段使用同步等待是必要的,因为此时还没有其他线程可以 poll
|
||||
@@ -631,6 +657,13 @@ static void create_sync_cb(void *arg, int bserrno) {
|
||||
handle->blob_id = cctx->blob_id;
|
||||
handle->blob = cctx->blob;
|
||||
atomic_init(&handle->ref_count, 1);
|
||||
if (handle_state_init(handle, cctx->req->open_flags) != 0) {
|
||||
spdk_blob_close(cctx->blob, blob_close_noop_cb, NULL);
|
||||
free(handle);
|
||||
push_err_resp(cctx->req, -ENOMEM);
|
||||
free(cctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 构造响应 */
|
||||
struct zvfs_resp *resp = calloc(1, sizeof(*resp));
|
||||
@@ -688,6 +721,13 @@ static void blob_open_done_cb(void *arg, struct spdk_blob *blob, int bserrno) {
|
||||
handle->blob_id = octx->req->blob_id;
|
||||
handle->blob = blob;
|
||||
atomic_init(&handle->ref_count, 1);
|
||||
if (handle_state_init(handle, octx->req->open_flags) != 0) {
|
||||
spdk_blob_close(blob, blob_close_noop_cb, NULL);
|
||||
free(handle);
|
||||
push_err_resp(octx->req, -ENOMEM);
|
||||
free(octx);
|
||||
return;
|
||||
}
|
||||
|
||||
struct zvfs_resp *resp = calloc(1, sizeof(*resp));
|
||||
if (!resp) {
|
||||
@@ -733,6 +773,93 @@ int blob_open(struct zvfs_req *req) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_shared_read(struct zvfs_req *req, struct zvfs_blob_handle *handle) {
|
||||
uint64_t logical_size;
|
||||
uint64_t cur;
|
||||
uint64_t remaining;
|
||||
uint64_t actual_len;
|
||||
|
||||
if ((req->write_flags & ZVFS_RW_F_USE_HANDLE_POS) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
logical_size = req->offset;
|
||||
pthread_mutex_lock(&handle->state_mu);
|
||||
cur = handle->current_offset;
|
||||
if (cur >= logical_size) {
|
||||
actual_len = 0;
|
||||
} else {
|
||||
remaining = logical_size - cur;
|
||||
actual_len = req->length;
|
||||
if (actual_len > remaining) {
|
||||
actual_len = remaining;
|
||||
}
|
||||
}
|
||||
handle->current_offset = cur + actual_len;
|
||||
pthread_mutex_unlock(&handle->state_mu);
|
||||
|
||||
req->offset = cur;
|
||||
req->length = actual_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_shared_write(struct zvfs_req *req, struct zvfs_blob_handle *handle) {
|
||||
uint64_t base_offset;
|
||||
uint64_t logical_size;
|
||||
uint64_t new_offset;
|
||||
|
||||
if ((req->write_flags & ZVFS_RW_F_USE_HANDLE_POS) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
logical_size = req->offset;
|
||||
pthread_mutex_lock(&handle->state_mu);
|
||||
if ((handle->status_flags & O_APPEND) != 0) {
|
||||
base_offset = logical_size;
|
||||
} else {
|
||||
base_offset = handle->current_offset;
|
||||
}
|
||||
if (__builtin_add_overflow(base_offset, req->length, &new_offset)) {
|
||||
pthread_mutex_unlock(&handle->state_mu);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
handle->current_offset = new_offset;
|
||||
pthread_mutex_unlock(&handle->state_mu);
|
||||
|
||||
req->offset = base_offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_seek_locked(struct zvfs_blob_handle *handle, int64_t offset, uint32_t whence,
|
||||
uint64_t logical_size, uint64_t *new_offset_out) {
|
||||
int64_t base;
|
||||
int64_t new_offset;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
base = 0;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
base = (int64_t)handle->current_offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
base = (int64_t)logical_size;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (__builtin_add_overflow(base, offset, &new_offset) || new_offset < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
handle->current_offset = (uint64_t)new_offset;
|
||||
if (new_offset_out) {
|
||||
*new_offset_out = (uint64_t)new_offset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** ===========================================================
|
||||
* blob_resize
|
||||
* ============================================================ */
|
||||
@@ -816,6 +943,7 @@ static void blob_close_done_cb(void *arg, int bserrno) {
|
||||
struct close_ctx *cctx = arg;
|
||||
if (bserrno == 0) {
|
||||
engine_cache_remove((zvfs_handle_id_t)(uintptr_t)cctx->handle);
|
||||
handle_state_destroy(cctx->handle);
|
||||
free(cctx->handle);
|
||||
}
|
||||
|
||||
@@ -871,6 +999,124 @@ int blob_close(struct zvfs_req *req) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_seek(struct zvfs_req *req) {
|
||||
struct zvfs_blob_handle *handle = req->handle;
|
||||
struct zvfs_resp *resp;
|
||||
int rc;
|
||||
|
||||
if (!handle) {
|
||||
push_err_resp(req, -EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
resp = calloc(1, sizeof(*resp));
|
||||
if (!resp) {
|
||||
push_err_resp(req, -ENOMEM);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&handle->state_mu);
|
||||
rc = handle_seek_locked(handle, req->seek_offset, req->seek_whence, req->size_hint, &resp->offset);
|
||||
pthread_mutex_unlock(&handle->state_mu);
|
||||
if (rc != 0) {
|
||||
free(resp);
|
||||
push_err_resp(req, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
resp->opcode = req->opcode;
|
||||
resp->status = 0;
|
||||
resp->conn = req->conn;
|
||||
free(req);
|
||||
zvfs_conn_submit_resp(resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_get_pos(struct zvfs_req *req) {
|
||||
struct zvfs_blob_handle *handle = req->handle;
|
||||
struct zvfs_resp *resp;
|
||||
|
||||
if (!handle) {
|
||||
push_err_resp(req, -EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
resp = calloc(1, sizeof(*resp));
|
||||
if (!resp) {
|
||||
push_err_resp(req, -ENOMEM);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&handle->state_mu);
|
||||
resp->offset = handle->current_offset;
|
||||
pthread_mutex_unlock(&handle->state_mu);
|
||||
|
||||
resp->opcode = req->opcode;
|
||||
resp->status = 0;
|
||||
resp->conn = req->conn;
|
||||
free(req);
|
||||
zvfs_conn_submit_resp(resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_get_flags(struct zvfs_req *req) {
|
||||
struct zvfs_blob_handle *handle = req->handle;
|
||||
struct zvfs_resp *resp;
|
||||
|
||||
if (!handle) {
|
||||
push_err_resp(req, -EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
resp = calloc(1, sizeof(*resp));
|
||||
if (!resp) {
|
||||
push_err_resp(req, -ENOMEM);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&handle->state_mu);
|
||||
resp->handle_flags = handle->status_flags;
|
||||
pthread_mutex_unlock(&handle->state_mu);
|
||||
|
||||
resp->opcode = req->opcode;
|
||||
resp->status = 0;
|
||||
resp->conn = req->conn;
|
||||
free(req);
|
||||
zvfs_conn_submit_resp(resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_set_flags(struct zvfs_req *req) {
|
||||
struct zvfs_blob_handle *handle = req->handle;
|
||||
const uint32_t mutable_mask = O_APPEND | O_NONBLOCK | O_ASYNC;
|
||||
uint32_t new_flags;
|
||||
struct zvfs_resp *resp;
|
||||
|
||||
if (!handle) {
|
||||
push_err_resp(req, -EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
resp = calloc(1, sizeof(*resp));
|
||||
if (!resp) {
|
||||
push_err_resp(req, -ENOMEM);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&handle->state_mu);
|
||||
new_flags = handle->status_flags & ~mutable_mask;
|
||||
new_flags |= req->handle_flags & mutable_mask;
|
||||
handle->status_flags = new_flags;
|
||||
pthread_mutex_unlock(&handle->state_mu);
|
||||
|
||||
resp->opcode = req->opcode;
|
||||
resp->status = 0;
|
||||
resp->conn = req->conn;
|
||||
free(req);
|
||||
zvfs_conn_submit_resp(resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** ===========================================================
|
||||
* blob_delete
|
||||
* ============================================================ */
|
||||
@@ -1073,6 +1319,21 @@ static void do_blob_read(void *arg) {
|
||||
int blob_read(struct zvfs_req *req) {
|
||||
struct zvfs_blob_handle *handle = req->handle;
|
||||
if (!handle || !req->data) { push_err_resp(req, -EINVAL); return -EINVAL; }
|
||||
prepare_shared_read(req, handle);
|
||||
|
||||
if (req->length == 0) {
|
||||
struct zvfs_resp *resp = calloc(1, sizeof(*resp));
|
||||
if (!resp) { push_err_resp(req, -ENOMEM); return -ENOMEM; }
|
||||
resp->opcode = req->opcode;
|
||||
resp->status = 0;
|
||||
resp->conn = req->conn;
|
||||
resp->length = 0;
|
||||
free(req->data);
|
||||
req->data = NULL;
|
||||
free(req);
|
||||
zvfs_conn_submit_resp(resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct zvfs_io_thread *iot = pick_io_thread();
|
||||
if (!iot || !iot->ready || !iot->channel) {
|
||||
@@ -1236,6 +1497,13 @@ static void do_write_autogrow_resize(void *arg) {
|
||||
int blob_write(struct zvfs_req *req) {
|
||||
struct zvfs_blob_handle *handle = req->handle;
|
||||
if (!handle || !req->data) { push_err_resp(req, -EINVAL); return -EINVAL; }
|
||||
{
|
||||
int rc = prepare_shared_write(req, handle);
|
||||
if (rc != 0) {
|
||||
push_err_resp(req, rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
struct zvfs_io_thread *iot = pick_io_thread();
|
||||
if (!iot || !iot->ready || !iot->channel) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdatomic.h>
|
||||
#include <pthread.h>
|
||||
#include <spdk/blob.h>
|
||||
|
||||
|
||||
@@ -14,6 +15,9 @@ typedef struct zvfs_blob_handle {
|
||||
spdk_blob_id blob_id;
|
||||
struct spdk_blob *blob;
|
||||
atomic_uint ref_count;
|
||||
uint64_t current_offset;
|
||||
uint32_t status_flags;
|
||||
pthread_mutex_t state_mu;
|
||||
} zvfs_blob_handle_t;
|
||||
|
||||
struct zvfs_io_thread {
|
||||
@@ -76,6 +80,10 @@ int blob_resize(struct zvfs_req *req);
|
||||
int blob_sync_md(struct zvfs_req *req);
|
||||
int blob_close(struct zvfs_req *req);
|
||||
int blob_delete(struct zvfs_req *req);
|
||||
int blob_seek(struct zvfs_req *req);
|
||||
int blob_get_pos(struct zvfs_req *req);
|
||||
int blob_get_flags(struct zvfs_req *req);
|
||||
int blob_set_flags(struct zvfs_req *req);
|
||||
int blobstore_reset(struct zvfs_req *req);
|
||||
bool io_engine_reset_in_progress(void);
|
||||
|
||||
|
||||
@@ -182,6 +182,26 @@ static int zvfs_add_ref_batch(struct zvfs_req *req) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zvfs_seek(struct zvfs_req *req) {
|
||||
if (fill_handle(req, "zvfs_seek") != 0) return -EBADF;
|
||||
return blob_seek(req);
|
||||
}
|
||||
|
||||
static int zvfs_get_pos(struct zvfs_req *req) {
|
||||
if (fill_handle(req, "zvfs_get_pos") != 0) return -EBADF;
|
||||
return blob_get_pos(req);
|
||||
}
|
||||
|
||||
static int zvfs_get_flags(struct zvfs_req *req) {
|
||||
if (fill_handle(req, "zvfs_get_flags") != 0) return -EBADF;
|
||||
return blob_get_flags(req);
|
||||
}
|
||||
|
||||
static int zvfs_set_flags(struct zvfs_req *req) {
|
||||
if (fill_handle(req, "zvfs_set_flags") != 0) return -EBADF;
|
||||
return blob_set_flags(req);
|
||||
}
|
||||
|
||||
static int zvfs_reset_blobstore(struct zvfs_req *req) {
|
||||
return blobstore_reset(req);
|
||||
}
|
||||
@@ -214,6 +234,14 @@ int dispatch_to_worker(struct zvfs_req *req){
|
||||
return zvfs_add_ref(req);
|
||||
case ZVFS_OP_ADD_REF_BATCH:
|
||||
return zvfs_add_ref_batch(req);
|
||||
case ZVFS_OP_SEEK:
|
||||
return zvfs_seek(req);
|
||||
case ZVFS_OP_GET_POS:
|
||||
return zvfs_get_pos(req);
|
||||
case ZVFS_OP_GET_FLAGS:
|
||||
return zvfs_get_flags(req);
|
||||
case ZVFS_OP_SET_FLAGS:
|
||||
return zvfs_set_flags(req);
|
||||
case ZVFS_OP_RESET_BLOBSTORE:
|
||||
return zvfs_reset_blobstore(req);
|
||||
default:
|
||||
|
||||
Binary file not shown.
@@ -14,7 +14,6 @@
|
||||
|
||||
struct zvfs_open_file *openfile_alloc(int fd,
|
||||
struct zvfs_inode *inode,
|
||||
int flags,
|
||||
uint64_t handle_id)
|
||||
{
|
||||
struct zvfs_open_file *of = calloc(1, sizeof(*of));
|
||||
@@ -24,9 +23,7 @@ struct zvfs_open_file *openfile_alloc(int fd,
|
||||
of->fd = fd;
|
||||
of->inode = inode;
|
||||
of->handle_id = handle_id;
|
||||
of->flags = flags;
|
||||
of->fd_flags = 0;
|
||||
of->offset = 0;
|
||||
|
||||
return of;
|
||||
}
|
||||
@@ -58,39 +55,3 @@ void openfile_remove(int fd)
|
||||
if (of)
|
||||
HASH_DEL(g_fs.fd_table, of);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* lseek (调用方持有 of->inode->mu) */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
uint64_t openfile_seek(struct zvfs_open_file *of, int64_t offset, int whence)
|
||||
{
|
||||
int64_t new_off;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
new_off = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
new_off = (int64_t)of->offset + offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
/* logical_size 由调用方在持锁状态下保证可见 */
|
||||
new_off = (int64_t)of->inode->logical_size + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return (uint64_t)-1;
|
||||
}
|
||||
|
||||
if (new_off < 0) {
|
||||
errno = EINVAL;
|
||||
return (uint64_t)-1;
|
||||
}
|
||||
|
||||
of->offset = (uint64_t)new_off;
|
||||
return of->offset;
|
||||
}
|
||||
|
||||
@@ -10,17 +10,14 @@ struct zvfs_open_file {
|
||||
struct zvfs_inode *inode;
|
||||
uint64_t handle_id;
|
||||
|
||||
int flags;
|
||||
int fd_flags;
|
||||
|
||||
uint64_t offset; // 非 APPEND 模式的当前位置
|
||||
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
// 分配 openfile,不插入全局表
|
||||
struct zvfs_open_file *openfile_alloc(int fd, struct zvfs_inode *inode,
|
||||
int flags, uint64_t handle_id);
|
||||
uint64_t handle_id);
|
||||
|
||||
// 释放内存
|
||||
void openfile_free(struct zvfs_open_file *of);
|
||||
@@ -34,8 +31,4 @@ struct zvfs_open_file *openfile_lookup(int fd);
|
||||
// 从全局表移除(需持有 fd_mu,不释放内存)
|
||||
void openfile_remove(int fd);
|
||||
|
||||
// lseek 语义:返回新 offset,出错返回 (uint64_t)-1
|
||||
// 需持有 of->inode->mu(读 logical_size)
|
||||
uint64_t openfile_seek(struct zvfs_open_file *of, int64_t offset, int whence);
|
||||
|
||||
#endif // __ZVFS_OPEN_FILE_H__
|
||||
|
||||
@@ -58,23 +58,32 @@ zvfs_fcntl_impl(int fd, int cmd, va_list ap)
|
||||
switch (cmd) {
|
||||
|
||||
/* ---- 文件状态 flags ------------------------------------------ */
|
||||
case F_GETFL:
|
||||
return of->flags;
|
||||
case F_GETFL: {
|
||||
uint32_t flags = 0;
|
||||
if (blob_get_flags(of->handle_id, &flags) < 0)
|
||||
return -1;
|
||||
return (int)flags;
|
||||
}
|
||||
|
||||
case F_SETFL: {
|
||||
int newfl = va_arg(ap, int);
|
||||
uint32_t cur_flags = 0;
|
||||
/*
|
||||
* 只允许修改可变位:O_APPEND、O_NONBLOCK、O_ASYNC。
|
||||
* O_RDONLY / O_WRONLY / O_RDWR 是 open 时决定的,不能改。
|
||||
* 同步给真实 fd,保持内核状态一致(影响 real_read/write)。
|
||||
*/
|
||||
int mutable_mask = O_APPEND | O_NONBLOCK | O_ASYNC;
|
||||
of->flags = (of->flags & ~mutable_mask) | (newfl & mutable_mask);
|
||||
if (blob_get_flags(of->handle_id, &cur_flags) < 0)
|
||||
return -1;
|
||||
cur_flags = (cur_flags & ~((uint32_t)mutable_mask)) | ((uint32_t)newfl & (uint32_t)mutable_mask);
|
||||
if (blob_set_flags(of->handle_id, cur_flags) < 0)
|
||||
return -1;
|
||||
/*
|
||||
* 也透传给真实 fd——虽然真实 fd 上的读写被我们拦截了,
|
||||
* 但 O_NONBLOCK 可能影响 pipe / socket 等透传路径。
|
||||
*/
|
||||
real_fcntl(fd, F_SETFL, of->flags);
|
||||
real_fcntl(fd, F_SETFL, (int)cur_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -238,7 +247,8 @@ ioctl(int fd, unsigned long request, ...)
|
||||
uint64_t size = of->inode->logical_size;
|
||||
pthread_mutex_unlock(&of->inode->mu);
|
||||
|
||||
uint64_t off = of->offset;
|
||||
uint64_t off = 0;
|
||||
if (blob_get_pos(of->handle_id, &off) < 0) { ret = -1; break; }
|
||||
int avail = (off < size) ? (int)(size - off) : 0;
|
||||
if (arg) *(int *)arg = avail;
|
||||
ret = 0;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
/*
|
||||
* fcntl cmd 处理策略:
|
||||
*
|
||||
* F_GETFL → 返回 of->flags
|
||||
* F_SETFL → 更新 of->flags(只允许改 O_APPEND / O_NONBLOCK)
|
||||
* F_GETFL → 返回 daemon handle 上的共享 status flags
|
||||
* F_SETFL → 更新 daemon handle 上的共享 status flags
|
||||
* F_GETFD → 返回 of->fd_flags
|
||||
* F_SETFD → 更新 of->fd_flags(FD_CLOEXEC)
|
||||
* F_DUPFD → 等价于 dup,分配 >= arg 的最小可用 fd,走 dup 路径
|
||||
@@ -16,7 +16,7 @@
|
||||
* 其他 cmd → 透传给 real_fcntl(同时透传给内核,保持真实 fd 状态同步)
|
||||
*
|
||||
* ioctl cmd 处理策略:
|
||||
* FIONREAD → 返回 logical_size - cur_offset(可读字节数)
|
||||
* FIONREAD → 返回 logical_size - daemon handle 当前 offset
|
||||
* 其他 → 透传,或对 zvfs fd 返回 ENOTTY
|
||||
*/
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
/* ---- 创建路径 -------------------------------------------- */
|
||||
|
||||
/* 1. 创建 blob */
|
||||
if (blob_create(0, &blob_id, &handle_id) != 0) {
|
||||
if (blob_create(0, flags, &blob_id, &handle_id) != 0) {
|
||||
int saved = errno;
|
||||
if (saved == 0) saved = EIO;
|
||||
fprintf(stderr,
|
||||
@@ -311,7 +311,7 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
(unsigned long)inode->blob_id);
|
||||
/* path_cache 命中:直接用缓存的 inode,重新 blob_open */
|
||||
blob_id = inode->blob_id;
|
||||
if (blob_open(blob_id, &handle_id) != 0) {
|
||||
if (blob_open(blob_id, flags, &handle_id) != 0) {
|
||||
if (errno == 0) errno = EIO;
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing path_cache-hit blob_open fail errno=%d(%s)",
|
||||
@@ -344,7 +344,7 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing inode_table hit blob_id=%lu",
|
||||
(unsigned long)blob_id);
|
||||
if (blob_open(blob_id, &handle_id) != 0) {
|
||||
if (blob_open(blob_id, flags, &handle_id) != 0) {
|
||||
if (errno == 0) errno = EIO;
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing inode_table-hit blob_open fail errno=%d(%s)",
|
||||
@@ -381,7 +381,7 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
pthread_mutex_lock(&g_fs.path_mu);
|
||||
path_cache_insert(abspath, inode);
|
||||
pthread_mutex_unlock(&g_fs.path_mu);
|
||||
if (blob_open(blob_id, &handle_id) != 0) {
|
||||
if (blob_open(blob_id, flags, &handle_id) != 0) {
|
||||
if (errno == 0) errno = EIO;
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing new-inode blob_open fail errno=%d(%s)",
|
||||
@@ -397,7 +397,7 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
}
|
||||
|
||||
/* ---- 分配 openfile,插入 fd_table ---------------------------- */
|
||||
struct zvfs_open_file *of = openfile_alloc(real_fd, inode, flags, handle_id);
|
||||
struct zvfs_open_file *of = openfile_alloc(real_fd, inode, handle_id);
|
||||
if (!of) { errno = ENOMEM; goto fail_handle; }
|
||||
|
||||
pthread_mutex_lock(&g_fs.fd_mu);
|
||||
@@ -1150,7 +1150,7 @@ zvfs_dup_attach_newfd(int oldfd, int newfd, int new_fd_flags)
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_of = openfile_alloc(newfd, old_of->inode, old_of->flags, old_of->handle_id);
|
||||
new_of = openfile_alloc(newfd, old_of->inode, old_of->handle_id);
|
||||
if (!new_of) {
|
||||
saved = (errno != 0) ? errno : ENOMEM;
|
||||
(void)blob_close(old_of->handle_id);
|
||||
@@ -1159,7 +1159,6 @@ zvfs_dup_attach_newfd(int oldfd, int newfd, int new_fd_flags)
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_of->offset = old_of->offset;
|
||||
fd_flags = (new_fd_flags >= 0) ? new_fd_flags : old_of->fd_flags;
|
||||
new_of->fd_flags = fd_flags;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#define zvfs_debug_rw_log(...) ((void)0)
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 内部:单段 pread / pwrite(不修改 of->offset) */
|
||||
/* 内部:单段 pread / pwrite(不修改 daemon handle offset) */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
@@ -90,6 +90,52 @@ zvfs_pwrite_impl(struct zvfs_open_file *of,
|
||||
return (ssize_t)count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
zvfs_read_shared_impl(struct zvfs_open_file *of, void *buf, size_t count)
|
||||
{
|
||||
uint64_t size;
|
||||
ssize_t nr;
|
||||
|
||||
pthread_mutex_lock(&of->inode->mu);
|
||||
size = of->inode->logical_size;
|
||||
pthread_mutex_unlock(&of->inode->mu);
|
||||
|
||||
nr = blob_read_shared(of->handle_id, size, buf, count);
|
||||
if (nr < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
zvfs_write_shared_impl(struct zvfs_open_file *of, const void *buf, size_t count)
|
||||
{
|
||||
uint64_t logical_size;
|
||||
uint64_t new_pos = 0;
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
pthread_mutex_lock(&of->inode->mu);
|
||||
logical_size = of->inode->logical_size;
|
||||
pthread_mutex_unlock(&of->inode->mu);
|
||||
|
||||
if (blob_write_shared(of->handle_id, logical_size, buf, count, ZVFS_WRITE_F_AUTO_GROW) < 0)
|
||||
return -1;
|
||||
|
||||
if (blob_get_pos(of->handle_id, &new_pos) < 0)
|
||||
return -1;
|
||||
|
||||
pthread_mutex_lock(&of->inode->mu);
|
||||
if (new_pos > of->inode->logical_size)
|
||||
inode_update_size(of->inode, of->fd, new_pos);
|
||||
pthread_mutex_unlock(&of->inode->mu);
|
||||
|
||||
return (ssize_t)count;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 内部:iov 合并辅助 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -189,6 +235,63 @@ zvfs_iov_pwrite(struct zvfs_open_file *of,
|
||||
return r;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
zvfs_iov_read_shared(struct zvfs_open_file *of, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
size_t total_len = iov_total_len(iov, iovcnt);
|
||||
ssize_t nr;
|
||||
size_t copied = 0;
|
||||
char *tmp;
|
||||
|
||||
if (total_len == 0)
|
||||
return 0;
|
||||
|
||||
tmp = malloc(total_len);
|
||||
if (!tmp) { errno = ENOMEM; return -1; }
|
||||
|
||||
nr = zvfs_read_shared_impl(of, tmp, total_len);
|
||||
if (nr <= 0) {
|
||||
free(tmp);
|
||||
return nr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < iovcnt && copied < (size_t)nr; i++) {
|
||||
size_t seg = iov[i].iov_len;
|
||||
if (seg == 0) continue;
|
||||
if (copied + seg > (size_t)nr) seg = (size_t)nr - copied;
|
||||
memcpy(iov[i].iov_base, tmp + copied, seg);
|
||||
copied += seg;
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
return nr;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
zvfs_iov_write_shared(struct zvfs_open_file *of, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
size_t total_len = iov_total_len(iov, iovcnt);
|
||||
size_t pos = 0;
|
||||
char *tmp;
|
||||
ssize_t nr;
|
||||
|
||||
if (total_len == 0)
|
||||
return 0;
|
||||
|
||||
tmp = malloc(total_len);
|
||||
if (!tmp) { errno = ENOMEM; return -1; }
|
||||
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
if (iov[i].iov_len == 0) continue;
|
||||
memcpy(tmp + pos, iov[i].iov_base, iov[i].iov_len);
|
||||
pos += iov[i].iov_len;
|
||||
}
|
||||
|
||||
nr = zvfs_write_shared_impl(of, tmp, total_len);
|
||||
free(tmp);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 内部:取出 of,处理重入/非 zvfs 判断 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -237,9 +340,9 @@ zvfs_fread_impl(void *ptr, size_t size, size_t nmemb, FILE *stream, int unlocked
|
||||
}
|
||||
|
||||
zvfs_debug_rw_log(fd,
|
||||
"fread hooked unlocked=%d size=%zu nmemb=%zu offset=%lu handle_id=%lu logical_size=%lu target=%s",
|
||||
"fread hooked unlocked=%d size=%zu nmemb=%zu handle_id=%lu logical_size=%lu target=%s",
|
||||
unlocked, size, nmemb,
|
||||
(unsigned long)of->offset, (unsigned long)of->handle_id,
|
||||
(unsigned long)of->handle_id,
|
||||
(unsigned long)zvfs_debug_logical_size(of),
|
||||
zvfs_debug_fd_target(fd));
|
||||
zvfs_ensure_init();
|
||||
@@ -255,9 +358,7 @@ zvfs_fread_impl(void *ptr, size_t size, size_t nmemb, FILE *stream, int unlocked
|
||||
}
|
||||
|
||||
size_t total = size * nmemb;
|
||||
ssize_t n = zvfs_pread_impl(of, ptr, total, of->offset);
|
||||
if (n > 0)
|
||||
of->offset += (uint64_t)n;
|
||||
ssize_t n = zvfs_read_shared_impl(of, ptr, total);
|
||||
|
||||
/* Keep stdio state machine consistent for callers that check feof/ferror. */
|
||||
if (n < 0) {
|
||||
@@ -266,9 +367,8 @@ zvfs_fread_impl(void *ptr, size_t size, size_t nmemb, FILE *stream, int unlocked
|
||||
stream->_flags |= _IO_EOF_SEEN;
|
||||
}
|
||||
zvfs_debug_rw_log(fd,
|
||||
"fread hooked ret_bytes=%zd ret_nmemb=%zu new_offset=%lu errno=%d(%s)",
|
||||
"fread hooked ret_bytes=%zd ret_nmemb=%zu errno=%d(%s)",
|
||||
n, (n <= 0) ? 0 : ((size_t)n / size),
|
||||
(unsigned long)of->offset,
|
||||
(n < 0) ? errno : 0, (n < 0) ? strerror(errno) : "OK");
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return (n <= 0) ? 0 : ((size_t)n / size);
|
||||
@@ -323,9 +423,15 @@ zvfs_vfscanf_impl(FILE *stream, const char *format, va_list ap, int use_isoc99)
|
||||
return EOF;
|
||||
}
|
||||
|
||||
uint64_t cur_off = of->offset;
|
||||
uint64_t cur_off = 0;
|
||||
uint64_t logical_size;
|
||||
|
||||
if (blob_get_pos(of->handle_id, &cur_off) < 0) {
|
||||
stream->_flags |= _IO_ERR_SEEN;
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return EOF;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&of->inode->mu);
|
||||
logical_size = of->inode->logical_size;
|
||||
pthread_mutex_unlock(&of->inode->mu);
|
||||
@@ -384,8 +490,14 @@ zvfs_vfscanf_impl(FILE *stream, const char *format, va_list ap, int use_isoc99)
|
||||
|
||||
ret = zvfs_vfscanf_passthrough(mem, format, ap, use_isoc99);
|
||||
long consumed = ftell(mem);
|
||||
if (consumed > 0) {
|
||||
of->offset = cur_off + (uint64_t)consumed;
|
||||
if (consumed > 0 &&
|
||||
blob_seek(of->handle_id, (int64_t)(cur_off + (uint64_t)consumed), SEEK_SET,
|
||||
logical_size, &cur_off) < 0) {
|
||||
stream->_flags |= _IO_ERR_SEEN;
|
||||
fclose(mem);
|
||||
free(buf);
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return EOF;
|
||||
}
|
||||
|
||||
fclose(mem);
|
||||
@@ -397,7 +509,7 @@ zvfs_vfscanf_impl(FILE *stream, const char *format, va_list ap, int use_isoc99)
|
||||
|
||||
zvfs_debug_rw_log(fd,
|
||||
"fscanf hooked ret=%d consumed=%ld new_offset=%lu errno=%d(%s)",
|
||||
ret, consumed, (unsigned long)of->offset, errno, strerror(errno));
|
||||
ret, consumed, (unsigned long)cur_off, errno, strerror(errno));
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return ret;
|
||||
}
|
||||
@@ -440,19 +552,17 @@ read(int fd, void *buf, size_t count)
|
||||
}
|
||||
|
||||
zvfs_debug_rw_log(fd,
|
||||
"read hooked count=%zu offset=%lu handle_id=%lu logical_size=%lu target=%s",
|
||||
count, (unsigned long)of->offset,
|
||||
"read hooked count=%zu handle_id=%lu logical_size=%lu target=%s",
|
||||
count,
|
||||
(unsigned long)of->handle_id,
|
||||
(unsigned long)zvfs_debug_logical_size(of),
|
||||
zvfs_debug_fd_target(fd));
|
||||
zvfs_ensure_init();
|
||||
|
||||
ssize_t r = zvfs_pread_impl(of, buf, count, of->offset);
|
||||
if (r > 0)
|
||||
of->offset += (uint64_t)r;
|
||||
ssize_t r = zvfs_read_shared_impl(of, buf, count);
|
||||
zvfs_debug_rw_log(fd,
|
||||
"read hooked ret=%zd new_offset=%lu errno=%d(%s)",
|
||||
r, (unsigned long)of->offset,
|
||||
"read hooked ret=%zd errno=%d(%s)",
|
||||
r,
|
||||
(r < 0) ? errno : 0, (r < 0) ? strerror(errno) : "OK");
|
||||
|
||||
ZVFS_HOOK_LEAVE();
|
||||
@@ -577,9 +687,7 @@ readv(int fd, const struct iovec *iov, int iovcnt)
|
||||
|
||||
zvfs_ensure_init();
|
||||
|
||||
ssize_t r = zvfs_iov_pread(of, iov, iovcnt, of->offset);
|
||||
if (r > 0)
|
||||
of->offset += (uint64_t)r;
|
||||
ssize_t r = zvfs_iov_read_shared(of, iov, iovcnt);
|
||||
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return r;
|
||||
@@ -630,10 +738,9 @@ preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags)
|
||||
* 忽略该 flag,按普通 preadv 处理。
|
||||
* RWF_HIPRI / RWF_DSYNC / RWF_SYNC:同上,忽略。
|
||||
*/
|
||||
uint64_t off = (offset == (off_t)-1) ? of->offset : (uint64_t)offset;
|
||||
ssize_t r = zvfs_iov_pread(of, iov, iovcnt, off);
|
||||
if (offset == (off_t)-1 && r > 0)
|
||||
of->offset += (uint64_t)r;
|
||||
ssize_t r = (offset == (off_t)-1)
|
||||
? zvfs_iov_read_shared(of, iov, iovcnt)
|
||||
: zvfs_iov_pread(of, iov, iovcnt, (uint64_t)offset);
|
||||
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return r;
|
||||
@@ -657,28 +764,9 @@ write(int fd, const void *buf, size_t count)
|
||||
|
||||
zvfs_ensure_init();
|
||||
|
||||
uint64_t write_off;
|
||||
|
||||
if (of->flags & O_APPEND) {
|
||||
/* O_APPEND:每次写入位置 = 当前 logical_size。 */
|
||||
pthread_mutex_lock(&of->inode->mu);
|
||||
write_off = of->inode->logical_size; /* 重新取,防止 TOCTOU */
|
||||
pthread_mutex_unlock(&of->inode->mu);
|
||||
|
||||
ssize_t r = zvfs_pwrite_impl(of, buf, count, write_off);
|
||||
if (r > 0)
|
||||
of->offset = write_off + (uint64_t)r;
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return r;
|
||||
|
||||
} else {
|
||||
write_off = of->offset;
|
||||
ssize_t r = zvfs_pwrite_impl(of, buf, count, write_off);
|
||||
if (r > 0)
|
||||
of->offset += (uint64_t)r;
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return r;
|
||||
}
|
||||
ssize_t r = zvfs_write_shared_impl(of, buf, count);
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return r;
|
||||
}
|
||||
|
||||
ssize_t __write(int fd, const void *buf, size_t count) { return write(fd, buf, count); }
|
||||
@@ -733,20 +821,7 @@ writev(int fd, const struct iovec *iov, int iovcnt)
|
||||
|
||||
zvfs_ensure_init();
|
||||
|
||||
ssize_t r;
|
||||
if (of->flags & O_APPEND) {
|
||||
/* O_APPEND + writev:以当前 logical_size 作为写入起点。 */
|
||||
pthread_mutex_lock(&of->inode->mu);
|
||||
uint64_t write_off = of->inode->logical_size;
|
||||
pthread_mutex_unlock(&of->inode->mu);
|
||||
|
||||
r = zvfs_iov_pwrite(of, iov, iovcnt, write_off);
|
||||
if (r > 0)
|
||||
of->offset = write_off + (uint64_t)r;
|
||||
} else {
|
||||
r = zvfs_iov_pwrite(of, iov, iovcnt, of->offset);
|
||||
if (r > 0) of->offset += (uint64_t)r;
|
||||
}
|
||||
ssize_t r = zvfs_iov_write_shared(of, iov, iovcnt);
|
||||
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return r;
|
||||
@@ -794,11 +869,10 @@ pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags)
|
||||
|
||||
/* flags(RWF_SYNC/RWF_DSYNC/RWF_APPEND 等):
|
||||
* zvfs 无缓冲区,所有写均同步落盘,忽略 flags。
|
||||
* offset == -1:使用并更新 of->offset。 */
|
||||
uint64_t off = (offset == (off_t)-1) ? of->offset : (uint64_t)offset;
|
||||
ssize_t r = zvfs_iov_pwrite(of, iov, iovcnt, off);
|
||||
if (offset == (off_t)-1 && r > 0)
|
||||
of->offset += (uint64_t)r;
|
||||
* offset == -1:使用并更新 daemon handle offset。 */
|
||||
ssize_t r = (offset == (off_t)-1)
|
||||
? zvfs_iov_write_shared(of, iov, iovcnt)
|
||||
: zvfs_iov_pwrite(of, iov, iovcnt, (uint64_t)offset);
|
||||
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return r;
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
* zvfs_pwrite_impl(fd, buf, count, offset)
|
||||
*
|
||||
* offset 语义:
|
||||
* - pread/pwrite 系列:直接使用传入 offset,不修改 of->offset
|
||||
* - read/write 系列:使用 of->offset,完成后更新
|
||||
* - O_APPEND write :每次写前持 inode->mu 取 logical_size 作为 offset
|
||||
* - pread/pwrite 系列:直接使用传入 offset,不修改 daemon handle offset
|
||||
* - read/write 系列:使用并更新 daemon handle offset
|
||||
* - O_APPEND write :由 daemon handle 上的共享 status flags 决定
|
||||
*
|
||||
* iov 系列(readv/writev/preadv/pwritev):
|
||||
* 展开 iovec 后逐段调用 pread/pwrite impl,合并结果。
|
||||
|
||||
@@ -40,16 +40,12 @@ lseek(int fd, off_t offset, int whence)
|
||||
|
||||
zvfs_ensure_init();
|
||||
|
||||
/*
|
||||
* O_APPEND fd 的 lseek:POSIX 允许 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_lock(&of->inode->mu);
|
||||
uint64_t logical_size = of->inode->logical_size;
|
||||
pthread_mutex_unlock(&of->inode->mu);
|
||||
|
||||
if (new_off == (uint64_t)-1) {
|
||||
uint64_t new_off = 0;
|
||||
if (blob_seek(of->handle_id, (int64_t)offset, whence, logical_size, &new_off) != 0) {
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return (off_t)-1;
|
||||
}
|
||||
@@ -104,7 +100,7 @@ zvfs_truncate_inode_with_handle(struct zvfs_inode *inode,
|
||||
* 这种情况下 truncate(path, ...) 被调用但文件没有 fd。
|
||||
*/
|
||||
uint64_t temp_handle_id = 0;
|
||||
if (blob_open(inode->blob_id, &temp_handle_id) < 0) {
|
||||
if (blob_open(inode->blob_id, O_RDWR, &temp_handle_id) < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* lseek:更新 of->offset(非 O_APPEND fd)。
|
||||
* lseek:更新 daemon handle 上的共享 offset。
|
||||
*
|
||||
* truncate / ftruncate:
|
||||
* 更新 inode->logical_size,同步 st_size(ftruncate 到真实 fd),
|
||||
|
||||
@@ -39,6 +39,14 @@ static int read_s32(const uint8_t **p, size_t *remaining, int32_t *v) {
|
||||
return read_bytes(p, remaining, v, sizeof(*v));
|
||||
}
|
||||
|
||||
static int write_s64(uint8_t **p, size_t *remaining, int64_t v) {
|
||||
return write_bytes(p, remaining, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static int read_s64(const uint8_t **p, size_t *remaining, int64_t *v) {
|
||||
return read_bytes(p, remaining, v, sizeof(*v));
|
||||
}
|
||||
|
||||
static int write_u64(uint8_t **p, size_t *remaining, uint64_t v) {
|
||||
return write_bytes(p, remaining, &v, sizeof(v));
|
||||
}
|
||||
@@ -176,7 +184,8 @@ size_t zvfs_serialize_req_create(const struct zvfs_req_create_body *body, uint8_
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (write_u64(&p, &remaining, body->size_hint) != 0) {
|
||||
if (write_u64(&p, &remaining, body->size_hint) != 0 ||
|
||||
write_u32(&p, &remaining, body->open_flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return (size_t)(p - buf);
|
||||
@@ -189,7 +198,8 @@ size_t zvfs_deserialize_req_create(const uint8_t *buf, size_t buf_len, struct zv
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (read_u64(&p, &remaining, &body->size_hint) != 0) {
|
||||
if (read_u64(&p, &remaining, &body->size_hint) != 0 ||
|
||||
read_u32(&p, &remaining, &body->open_flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return (size_t)(p - buf);
|
||||
@@ -202,7 +212,8 @@ size_t zvfs_serialize_req_open(const struct zvfs_req_open_body *body, uint8_t *b
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (write_u64(&p, &remaining, body->blob_id) != 0) {
|
||||
if (write_u64(&p, &remaining, body->blob_id) != 0 ||
|
||||
write_u32(&p, &remaining, body->open_flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return (size_t)(p - buf);
|
||||
@@ -215,7 +226,8 @@ size_t zvfs_deserialize_req_open(const uint8_t *buf, size_t buf_len, struct zvfs
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (read_u64(&p, &remaining, &body->blob_id) != 0) {
|
||||
if (read_u64(&p, &remaining, &body->blob_id) != 0 ||
|
||||
read_u32(&p, &remaining, &body->open_flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return (size_t)(p - buf);
|
||||
@@ -230,7 +242,8 @@ size_t zvfs_serialize_req_read(const struct zvfs_req_read_body *body, uint8_t *b
|
||||
}
|
||||
if (write_u64(&p, &remaining, body->handle_id) != 0 ||
|
||||
write_u64(&p, &remaining, body->offset) != 0 ||
|
||||
write_u64(&p, &remaining, body->length) != 0) {
|
||||
write_u64(&p, &remaining, body->length) != 0 ||
|
||||
write_u32(&p, &remaining, body->flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return (size_t)(p - buf);
|
||||
@@ -245,7 +258,8 @@ size_t zvfs_deserialize_req_read(const uint8_t *buf, size_t buf_len, struct zvfs
|
||||
}
|
||||
if (read_u64(&p, &remaining, &body->handle_id) != 0 ||
|
||||
read_u64(&p, &remaining, &body->offset) != 0 ||
|
||||
read_u64(&p, &remaining, &body->length) != 0) {
|
||||
read_u64(&p, &remaining, &body->length) != 0 ||
|
||||
read_u32(&p, &remaining, &body->flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return (size_t)(p - buf);
|
||||
@@ -527,6 +541,106 @@ size_t zvfs_deserialize_req_add_ref_batch(const uint8_t *buf, size_t buf_len, st
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_serialize_req_seek(const struct zvfs_req_seek_body *body, uint8_t *buf, size_t buf_len) {
|
||||
uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (write_u64(&p, &remaining, body->handle_id) != 0 ||
|
||||
write_s64(&p, &remaining, body->offset) != 0 ||
|
||||
write_u32(&p, &remaining, body->whence) != 0 ||
|
||||
write_u64(&p, &remaining, body->logical_size) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_deserialize_req_seek(const uint8_t *buf, size_t buf_len, struct zvfs_req_seek_body *body) {
|
||||
const uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (read_u64(&p, &remaining, &body->handle_id) != 0 ||
|
||||
read_s64(&p, &remaining, &body->offset) != 0 ||
|
||||
read_u32(&p, &remaining, &body->whence) != 0 ||
|
||||
read_u64(&p, &remaining, &body->logical_size) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_serialize_req_get_pos(const struct zvfs_req_get_pos_body *body, uint8_t *buf, size_t buf_len) {
|
||||
uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (write_u64(&p, &remaining, body->handle_id) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_deserialize_req_get_pos(const uint8_t *buf, size_t buf_len, struct zvfs_req_get_pos_body *body) {
|
||||
const uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (read_u64(&p, &remaining, &body->handle_id) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_serialize_req_get_flags(const struct zvfs_req_get_flags_body *body, uint8_t *buf, size_t buf_len) {
|
||||
return zvfs_serialize_req_get_pos((const struct zvfs_req_get_pos_body *)body, buf, buf_len);
|
||||
}
|
||||
|
||||
size_t zvfs_deserialize_req_get_flags(const uint8_t *buf, size_t buf_len, struct zvfs_req_get_flags_body *body) {
|
||||
return zvfs_deserialize_req_get_pos(buf, buf_len, (struct zvfs_req_get_pos_body *)body);
|
||||
}
|
||||
|
||||
size_t zvfs_serialize_req_set_flags(const struct zvfs_req_set_flags_body *body, uint8_t *buf, size_t buf_len) {
|
||||
uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (write_u64(&p, &remaining, body->handle_id) != 0 ||
|
||||
write_u32(&p, &remaining, body->flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_deserialize_req_set_flags(const uint8_t *buf, size_t buf_len, struct zvfs_req_set_flags_body *body) {
|
||||
const uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (read_u64(&p, &remaining, &body->handle_id) != 0 ||
|
||||
read_u32(&p, &remaining, &body->flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
/* -------------------- response body -------------------- */
|
||||
|
||||
size_t zvfs_serialize_resp_create(const struct zvfs_resp_create_body *body, uint8_t *buf, size_t buf_len) {
|
||||
@@ -663,6 +777,72 @@ size_t zvfs_deserialize_resp_write(const uint8_t *buf, size_t buf_len, struct zv
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_serialize_resp_seek(const struct zvfs_resp_seek_body *body, uint8_t *buf, size_t buf_len) {
|
||||
uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (write_u64(&p, &remaining, body->offset) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_deserialize_resp_seek(const uint8_t *buf, size_t buf_len, struct zvfs_resp_seek_body *body) {
|
||||
const uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
memset(body, 0, sizeof(*body));
|
||||
if (read_u64(&p, &remaining, &body->offset) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_serialize_resp_get_pos(const struct zvfs_resp_get_pos_body *body, uint8_t *buf, size_t buf_len) {
|
||||
return zvfs_serialize_resp_seek((const struct zvfs_resp_seek_body *)body, buf, buf_len);
|
||||
}
|
||||
|
||||
size_t zvfs_deserialize_resp_get_pos(const uint8_t *buf, size_t buf_len, struct zvfs_resp_get_pos_body *body) {
|
||||
return zvfs_deserialize_resp_seek(buf, buf_len, (struct zvfs_resp_seek_body *)body);
|
||||
}
|
||||
|
||||
size_t zvfs_serialize_resp_get_flags(const struct zvfs_resp_get_flags_body *body, uint8_t *buf, size_t buf_len) {
|
||||
uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
if (write_u32(&p, &remaining, body->flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_deserialize_resp_get_flags(const uint8_t *buf, size_t buf_len, struct zvfs_resp_get_flags_body *body) {
|
||||
const uint8_t *p = buf;
|
||||
size_t remaining = buf_len;
|
||||
|
||||
if (!body || !buf) {
|
||||
return 0;
|
||||
}
|
||||
memset(body, 0, sizeof(*body));
|
||||
if (read_u32(&p, &remaining, &body->flags) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
size_t zvfs_serialize_resp_resize(uint8_t *buf, size_t buf_len) {
|
||||
(void)buf;
|
||||
(void)buf_len;
|
||||
@@ -741,13 +921,19 @@ size_t zvfs_serialize_req(struct zvfs_req *req, uint8_t *buf, size_t buf_len) {
|
||||
|
||||
switch (req->opcode) {
|
||||
case ZVFS_OP_CREATE: {
|
||||
struct zvfs_req_create_body body = { .size_hint = req->size_hint };
|
||||
struct zvfs_req_create_body body = {
|
||||
.size_hint = req->size_hint,
|
||||
.open_flags = req->open_flags,
|
||||
};
|
||||
body_len = zvfs_serialize_req_create(&body, buf + ZVFS_REQ_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_REQ_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_OPEN: {
|
||||
struct zvfs_req_open_body body = { .blob_id = req->blob_id };
|
||||
struct zvfs_req_open_body body = {
|
||||
.blob_id = req->blob_id,
|
||||
.open_flags = req->open_flags,
|
||||
};
|
||||
body_len = zvfs_serialize_req_open(&body, buf + ZVFS_REQ_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_REQ_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
@@ -757,6 +943,7 @@ size_t zvfs_serialize_req(struct zvfs_req *req, uint8_t *buf, size_t buf_len) {
|
||||
.handle_id = req->handle_id,
|
||||
.offset = req->offset,
|
||||
.length = req->length,
|
||||
.flags = req->write_flags,
|
||||
};
|
||||
body_len = zvfs_serialize_req_read(&body, buf + ZVFS_REQ_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_REQ_HEADER_WIRE_SIZE);
|
||||
@@ -819,6 +1006,38 @@ size_t zvfs_serialize_req(struct zvfs_req *req, uint8_t *buf, size_t buf_len) {
|
||||
buf_len - ZVFS_REQ_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_SEEK: {
|
||||
struct zvfs_req_seek_body body = {
|
||||
.handle_id = req->handle_id,
|
||||
.offset = req->seek_offset,
|
||||
.whence = req->seek_whence,
|
||||
.logical_size = req->size_hint,
|
||||
};
|
||||
body_len = zvfs_serialize_req_seek(&body, buf + ZVFS_REQ_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_REQ_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_GET_POS: {
|
||||
struct zvfs_req_get_pos_body body = { .handle_id = req->handle_id };
|
||||
body_len = zvfs_serialize_req_get_pos(&body, buf + ZVFS_REQ_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_REQ_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_GET_FLAGS: {
|
||||
struct zvfs_req_get_flags_body body = { .handle_id = req->handle_id };
|
||||
body_len = zvfs_serialize_req_get_flags(&body, buf + ZVFS_REQ_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_REQ_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_SET_FLAGS: {
|
||||
struct zvfs_req_set_flags_body body = {
|
||||
.handle_id = req->handle_id,
|
||||
.flags = req->handle_flags,
|
||||
};
|
||||
body_len = zvfs_serialize_req_set_flags(&body, buf + ZVFS_REQ_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_REQ_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_RESET_BLOBSTORE:
|
||||
body_len = 0;
|
||||
break;
|
||||
@@ -871,6 +1090,7 @@ size_t zvfs_deserialize_req(uint8_t *buf, size_t buf_len, struct zvfs_req *req)
|
||||
consumed = zvfs_deserialize_req_create(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
req->size_hint = body.size_hint;
|
||||
req->open_flags = body.open_flags;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -879,6 +1099,7 @@ size_t zvfs_deserialize_req(uint8_t *buf, size_t buf_len, struct zvfs_req *req)
|
||||
consumed = zvfs_deserialize_req_open(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
req->blob_id = body.blob_id;
|
||||
req->open_flags = body.open_flags;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -889,6 +1110,7 @@ size_t zvfs_deserialize_req(uint8_t *buf, size_t buf_len, struct zvfs_req *req)
|
||||
req->handle_id = body.handle_id;
|
||||
req->offset = body.offset;
|
||||
req->length = body.length;
|
||||
req->write_flags = body.flags;
|
||||
req->data = malloc(req->length);
|
||||
}
|
||||
break;
|
||||
@@ -956,6 +1178,42 @@ size_t zvfs_deserialize_req(uint8_t *buf, size_t buf_len, struct zvfs_req *req)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_SEEK: {
|
||||
struct zvfs_req_seek_body body;
|
||||
consumed = zvfs_deserialize_req_seek(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
req->handle_id = body.handle_id;
|
||||
req->seek_offset = body.offset;
|
||||
req->seek_whence = body.whence;
|
||||
req->size_hint = body.logical_size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_GET_POS: {
|
||||
struct zvfs_req_get_pos_body body;
|
||||
consumed = zvfs_deserialize_req_get_pos(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
req->handle_id = body.handle_id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_GET_FLAGS: {
|
||||
struct zvfs_req_get_flags_body body;
|
||||
consumed = zvfs_deserialize_req_get_flags(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
req->handle_id = body.handle_id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_SET_FLAGS: {
|
||||
struct zvfs_req_set_flags_body body;
|
||||
consumed = zvfs_deserialize_req_set_flags(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
req->handle_id = body.handle_id;
|
||||
req->handle_flags = body.flags;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_RESET_BLOBSTORE:
|
||||
if (header.payload_len != 0) {
|
||||
return 0;
|
||||
@@ -1032,6 +1290,24 @@ size_t zvfs_serialize_resp(struct zvfs_resp *resp, uint8_t *buf, size_t buf_len)
|
||||
buf_len - ZVFS_RESP_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_SEEK: {
|
||||
struct zvfs_resp_seek_body body = { .offset = resp->offset };
|
||||
body_len = zvfs_serialize_resp_seek(&body, buf + ZVFS_RESP_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_RESP_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_GET_POS: {
|
||||
struct zvfs_resp_get_pos_body body = { .offset = resp->offset };
|
||||
body_len = zvfs_serialize_resp_get_pos(&body, buf + ZVFS_RESP_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_RESP_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_GET_FLAGS: {
|
||||
struct zvfs_resp_get_flags_body body = { .flags = resp->handle_flags };
|
||||
body_len = zvfs_serialize_resp_get_flags(&body, buf + ZVFS_RESP_HEADER_WIRE_SIZE,
|
||||
buf_len - ZVFS_RESP_HEADER_WIRE_SIZE);
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_RESIZE:
|
||||
body_len = 0;
|
||||
break;
|
||||
@@ -1048,6 +1324,7 @@ size_t zvfs_serialize_resp(struct zvfs_resp *resp, uint8_t *buf, size_t buf_len)
|
||||
case ZVFS_OP_DELETE:
|
||||
case ZVFS_OP_ADD_REF:
|
||||
case ZVFS_OP_ADD_REF_BATCH:
|
||||
case ZVFS_OP_SET_FLAGS:
|
||||
case ZVFS_OP_RESET_BLOBSTORE:
|
||||
body_len = 0;
|
||||
break;
|
||||
@@ -1055,7 +1332,10 @@ size_t zvfs_serialize_resp(struct zvfs_resp *resp, uint8_t *buf, size_t buf_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (resp->opcode <= ZVFS_OP_WRITE && body_len == 0) {
|
||||
if ((resp->opcode <= ZVFS_OP_WRITE ||
|
||||
resp->opcode == ZVFS_OP_SEEK ||
|
||||
resp->opcode == ZVFS_OP_GET_POS ||
|
||||
resp->opcode == ZVFS_OP_GET_FLAGS) && body_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1142,6 +1422,30 @@ size_t zvfs_deserialize_resp(uint8_t *buf, size_t buf_len, struct zvfs_resp *res
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_SEEK: {
|
||||
struct zvfs_resp_seek_body body;
|
||||
consumed = zvfs_deserialize_resp_seek(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
resp->offset = body.offset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_GET_POS: {
|
||||
struct zvfs_resp_get_pos_body body;
|
||||
consumed = zvfs_deserialize_resp_get_pos(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
resp->offset = body.offset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_GET_FLAGS: {
|
||||
struct zvfs_resp_get_flags_body body;
|
||||
consumed = zvfs_deserialize_resp_get_flags(payload, header.payload_len, &body);
|
||||
if (consumed == header.payload_len) {
|
||||
resp->handle_flags = body.flags;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZVFS_OP_RESIZE:
|
||||
if (header.payload_len != 0) {
|
||||
return 0;
|
||||
@@ -1160,6 +1464,7 @@ size_t zvfs_deserialize_resp(uint8_t *buf, size_t buf_len, struct zvfs_resp *res
|
||||
case ZVFS_OP_DELETE:
|
||||
case ZVFS_OP_ADD_REF:
|
||||
case ZVFS_OP_ADD_REF_BATCH:
|
||||
case ZVFS_OP_SET_FLAGS:
|
||||
case ZVFS_OP_RESET_BLOBSTORE:
|
||||
if (header.payload_len != 0) {
|
||||
return 0;
|
||||
|
||||
@@ -22,6 +22,10 @@ enum zvfs_opcode {
|
||||
ZVFS_OP_DELETE,
|
||||
ZVFS_OP_ADD_REF,
|
||||
ZVFS_OP_ADD_REF_BATCH,
|
||||
ZVFS_OP_SEEK,
|
||||
ZVFS_OP_GET_POS,
|
||||
ZVFS_OP_GET_FLAGS,
|
||||
ZVFS_OP_SET_FLAGS,
|
||||
ZVFS_OP_RESET_BLOBSTORE
|
||||
};
|
||||
|
||||
@@ -58,6 +62,18 @@ inline const char* cast_opcode2string(uint32_t op){
|
||||
case ZVFS_OP_ADD_REF_BATCH:
|
||||
return "ADD_REF_BATCH";
|
||||
break;
|
||||
case ZVFS_OP_SEEK:
|
||||
return "SEEK";
|
||||
break;
|
||||
case ZVFS_OP_GET_POS:
|
||||
return "GET_POS";
|
||||
break;
|
||||
case ZVFS_OP_GET_FLAGS:
|
||||
return "GET_FLAGS";
|
||||
break;
|
||||
case ZVFS_OP_SET_FLAGS:
|
||||
return "SET_FLAGS";
|
||||
break;
|
||||
case ZVFS_OP_RESET_BLOBSTORE:
|
||||
return "RESET_BLOBSTORE";
|
||||
break;
|
||||
@@ -68,6 +84,7 @@ inline const char* cast_opcode2string(uint32_t op){
|
||||
}
|
||||
|
||||
#define ZVFS_WRITE_F_AUTO_GROW (1u << 0)
|
||||
#define ZVFS_RW_F_USE_HANDLE_POS (1u << 1)
|
||||
|
||||
#define ZVFS_RESP_TRACE_F_VALID (1u << 0)
|
||||
#define ZVFS_RESP_TRACE_F_PHASE1_VALID (1u << 1)
|
||||
@@ -92,16 +109,19 @@ struct zvfs_resp_header {
|
||||
|
||||
struct zvfs_req_create_body {
|
||||
uint64_t size_hint;
|
||||
uint32_t open_flags;
|
||||
};
|
||||
|
||||
struct zvfs_req_open_body {
|
||||
uint64_t blob_id;
|
||||
uint32_t open_flags;
|
||||
};
|
||||
|
||||
struct zvfs_req_read_body {
|
||||
uint64_t handle_id;
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct zvfs_req_write_body {
|
||||
@@ -144,6 +164,26 @@ struct zvfs_req_add_ref_batch_body {
|
||||
const struct zvfs_add_ref_item *items;
|
||||
};
|
||||
|
||||
struct zvfs_req_seek_body {
|
||||
uint64_t handle_id;
|
||||
int64_t offset;
|
||||
uint32_t whence;
|
||||
uint64_t logical_size;
|
||||
};
|
||||
|
||||
struct zvfs_req_get_pos_body {
|
||||
uint64_t handle_id;
|
||||
};
|
||||
|
||||
struct zvfs_req_get_flags_body {
|
||||
uint64_t handle_id;
|
||||
};
|
||||
|
||||
struct zvfs_req_set_flags_body {
|
||||
uint64_t handle_id;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/* -------------------- per-op response body -------------------- */
|
||||
|
||||
struct zvfs_resp_create_body {
|
||||
@@ -183,6 +223,18 @@ struct zvfs_resp_sync_md_body {
|
||||
struct zvfs_resp_trace trace;
|
||||
};
|
||||
|
||||
struct zvfs_resp_seek_body {
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
struct zvfs_resp_get_pos_body {
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
struct zvfs_resp_get_flags_body {
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/* resize/sync_md/close/delete 成功时 body 为空 */
|
||||
size_t zvfs_serialize_resp_resize(uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_resp_resize(const uint8_t *buf, size_t buf_len);
|
||||
@@ -205,11 +257,15 @@ struct zvfs_req {
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
uint32_t write_flags;
|
||||
uint32_t open_flags;
|
||||
uint32_t handle_flags;
|
||||
void *data;
|
||||
|
||||
uint32_t ref_delta;
|
||||
uint32_t add_ref_count;
|
||||
struct zvfs_add_ref_item *add_ref_items;
|
||||
int64_t seek_offset;
|
||||
uint32_t seek_whence;
|
||||
|
||||
struct zvfs_conn *conn;
|
||||
struct zvfs_blob_handle *handle;
|
||||
@@ -225,12 +281,14 @@ struct zvfs_resp {
|
||||
uint64_t blob_id;
|
||||
uint64_t handle_id;
|
||||
uint64_t size;
|
||||
uint64_t offset;
|
||||
|
||||
uint64_t length;
|
||||
void *data;
|
||||
|
||||
uint64_t bytes_written;
|
||||
struct zvfs_resp_trace trace;
|
||||
uint32_t handle_flags;
|
||||
|
||||
struct zvfs_conn *conn;
|
||||
};
|
||||
@@ -277,6 +335,18 @@ size_t zvfs_deserialize_req_add_ref(const uint8_t *buf, size_t buf_len, struct z
|
||||
size_t zvfs_serialize_req_add_ref_batch(const struct zvfs_req_add_ref_batch_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_req_add_ref_batch(const uint8_t *buf, size_t buf_len, struct zvfs_req_add_ref_batch_body *body);
|
||||
|
||||
size_t zvfs_serialize_req_seek(const struct zvfs_req_seek_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_req_seek(const uint8_t *buf, size_t buf_len, struct zvfs_req_seek_body *body);
|
||||
|
||||
size_t zvfs_serialize_req_get_pos(const struct zvfs_req_get_pos_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_req_get_pos(const uint8_t *buf, size_t buf_len, struct zvfs_req_get_pos_body *body);
|
||||
|
||||
size_t zvfs_serialize_req_get_flags(const struct zvfs_req_get_flags_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_req_get_flags(const uint8_t *buf, size_t buf_len, struct zvfs_req_get_flags_body *body);
|
||||
|
||||
size_t zvfs_serialize_req_set_flags(const struct zvfs_req_set_flags_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_req_set_flags(const uint8_t *buf, size_t buf_len, struct zvfs_req_set_flags_body *body);
|
||||
|
||||
/* -------------------- response body 序列化/反序列化 -------------------- */
|
||||
|
||||
size_t zvfs_serialize_resp_create(const struct zvfs_resp_create_body *body, uint8_t *buf, size_t buf_len);
|
||||
@@ -291,6 +361,15 @@ size_t zvfs_deserialize_resp_read(const uint8_t *buf, size_t buf_len, struct zvf
|
||||
size_t zvfs_serialize_resp_write(const struct zvfs_resp_write_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_resp_write(const uint8_t *buf, size_t buf_len, struct zvfs_resp_write_body *body);
|
||||
|
||||
size_t zvfs_serialize_resp_seek(const struct zvfs_resp_seek_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_resp_seek(const uint8_t *buf, size_t buf_len, struct zvfs_resp_seek_body *body);
|
||||
|
||||
size_t zvfs_serialize_resp_get_pos(const struct zvfs_resp_get_pos_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_resp_get_pos(const uint8_t *buf, size_t buf_len, struct zvfs_resp_get_pos_body *body);
|
||||
|
||||
size_t zvfs_serialize_resp_get_flags(const struct zvfs_resp_get_flags_body *body, uint8_t *buf, size_t buf_len);
|
||||
size_t zvfs_deserialize_resp_get_flags(const uint8_t *buf, size_t buf_len, struct zvfs_resp_get_flags_body *body);
|
||||
|
||||
/* -------------------- 兼容封装 -------------------- */
|
||||
|
||||
size_t zvfs_serialize_req(struct zvfs_req *req, uint8_t *buf, size_t buf_len);
|
||||
|
||||
@@ -475,7 +475,7 @@ int io_engine_init(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_create(uint64_t size_hint, uint64_t *blob_id_out, uint64_t *handle_id_out) {
|
||||
int blob_create(uint64_t size_hint, int open_flags, uint64_t *blob_id_out, uint64_t *handle_id_out) {
|
||||
if (!blob_id_out || !handle_id_out) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
@@ -485,6 +485,7 @@ int blob_create(uint64_t size_hint, uint64_t *blob_id_out, uint64_t *handle_id_o
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.opcode = ZVFS_OP_CREATE;
|
||||
req.size_hint = size_hint;
|
||||
req.open_flags = (uint32_t)open_flags;
|
||||
|
||||
struct zvfs_resp resp;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
@@ -502,7 +503,7 @@ int blob_create(uint64_t size_hint, uint64_t *blob_id_out, uint64_t *handle_id_o
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_open(uint64_t blob_id, uint64_t *handle_id_out) {
|
||||
int blob_open(uint64_t blob_id, int open_flags, uint64_t *handle_id_out) {
|
||||
if (!handle_id_out) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
@@ -512,6 +513,7 @@ int blob_open(uint64_t blob_id, uint64_t *handle_id_out) {
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.opcode = ZVFS_OP_OPEN;
|
||||
req.blob_id = blob_id;
|
||||
req.open_flags = (uint32_t)open_flags;
|
||||
|
||||
struct zvfs_resp resp;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
@@ -571,7 +573,12 @@ int blob_write(uint64_t handle_id, uint64_t offset, const void *buf, size_t len)
|
||||
return blob_write_ex(handle_id, offset, buf, len, 0);
|
||||
}
|
||||
|
||||
int blob_read(uint64_t handle_id, uint64_t offset, void *buf, size_t len) {
|
||||
int blob_write_shared(uint64_t handle_id, uint64_t logical_size, const void *buf, size_t len, uint32_t write_flags) {
|
||||
return blob_write_ex(handle_id, logical_size, buf, len,
|
||||
write_flags | ZVFS_RW_F_USE_HANDLE_POS);
|
||||
}
|
||||
|
||||
ssize_t blob_read_ex(uint64_t handle_id, uint64_t offset, void *buf, size_t len, uint32_t read_flags) {
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -586,6 +593,7 @@ int blob_read(uint64_t handle_id, uint64_t offset, void *buf, size_t len) {
|
||||
req.handle_id = handle_id;
|
||||
req.offset = offset;
|
||||
req.length = (uint64_t)len;
|
||||
req.write_flags = read_flags;
|
||||
|
||||
struct zvfs_resp resp;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
@@ -594,7 +602,7 @@ int blob_read(uint64_t handle_id, uint64_t offset, void *buf, size_t len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!resp.data || resp.length != (uint64_t)len) {
|
||||
if (!resp.data && resp.length != 0) {
|
||||
if (resp.data) {
|
||||
free(resp.data);
|
||||
}
|
||||
@@ -602,11 +610,35 @@ int blob_read(uint64_t handle_id, uint64_t offset, void *buf, size_t len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(buf, resp.data, len);
|
||||
if (resp.length > len) {
|
||||
free(resp.data);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (resp.length > 0) {
|
||||
memcpy(buf, resp.data, (size_t)resp.length);
|
||||
}
|
||||
free(resp.data);
|
||||
return (ssize_t)resp.length;
|
||||
}
|
||||
|
||||
int blob_read(uint64_t handle_id, uint64_t offset, void *buf, size_t len) {
|
||||
ssize_t nr = blob_read_ex(handle_id, offset, buf, len, 0);
|
||||
if (nr < 0) {
|
||||
return -1;
|
||||
}
|
||||
if ((size_t)nr != len) {
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t blob_read_shared(uint64_t handle_id, uint64_t logical_size, void *buf, size_t len) {
|
||||
return blob_read_ex(handle_id, logical_size, buf, len, ZVFS_RW_F_USE_HANDLE_POS);
|
||||
}
|
||||
|
||||
int blob_resize(uint64_t handle_id, uint64_t new_size) {
|
||||
if (handle_id == 0) {
|
||||
errno = EINVAL;
|
||||
@@ -769,3 +801,106 @@ int blob_add_ref_batch(const uint64_t *handle_ids, const uint32_t *ref_deltas, u
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_seek(uint64_t handle_id, int64_t offset, int whence, uint64_t logical_size, uint64_t *new_offset_out) {
|
||||
if (handle_id == 0 || !new_offset_out) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct zvfs_req req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.opcode = ZVFS_OP_SEEK;
|
||||
req.handle_id = handle_id;
|
||||
req.seek_offset = offset;
|
||||
req.seek_whence = (uint32_t)whence;
|
||||
req.size_hint = logical_size;
|
||||
|
||||
struct zvfs_resp resp;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
if (ipc_do_req(&req, &resp) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*new_offset_out = resp.offset;
|
||||
if (resp.data) {
|
||||
free(resp.data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_get_pos(uint64_t handle_id, uint64_t *offset_out) {
|
||||
if (handle_id == 0 || !offset_out) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct zvfs_req req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.opcode = ZVFS_OP_GET_POS;
|
||||
req.handle_id = handle_id;
|
||||
|
||||
struct zvfs_resp resp;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
if (ipc_do_req(&req, &resp) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*offset_out = resp.offset;
|
||||
if (resp.data) {
|
||||
free(resp.data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_get_flags(uint64_t handle_id, uint32_t *flags_out) {
|
||||
if (handle_id == 0 || !flags_out) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct zvfs_req req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.opcode = ZVFS_OP_GET_FLAGS;
|
||||
req.handle_id = handle_id;
|
||||
|
||||
struct zvfs_resp resp;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
if (ipc_do_req(&req, &resp) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*flags_out = resp.handle_flags;
|
||||
if (resp.data) {
|
||||
free(resp.data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_set_flags(uint64_t handle_id, uint32_t flags) {
|
||||
if (handle_id == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct zvfs_req req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.opcode = ZVFS_OP_SET_FLAGS;
|
||||
req.handle_id = handle_id;
|
||||
req.handle_flags = flags;
|
||||
|
||||
struct zvfs_resp resp;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
if (ipc_do_req(&req, &resp) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (resp.data) {
|
||||
free(resp.data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,19 +3,27 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int io_engine_init(void);
|
||||
|
||||
int blob_create(uint64_t size_hint, uint64_t *blob_id_out, uint64_t *handle_id_out);
|
||||
int blob_open(uint64_t blob_id, uint64_t *handle_id_out);
|
||||
int blob_create(uint64_t size_hint, int open_flags, uint64_t *blob_id_out, uint64_t *handle_id_out);
|
||||
int blob_open(uint64_t blob_id, int open_flags, uint64_t *handle_id_out);
|
||||
int blob_write_ex(uint64_t handle_id, uint64_t offset, const void *buf, size_t len, uint32_t write_flags);
|
||||
int blob_write(uint64_t handle_id, uint64_t offset, const void *buf, size_t len);
|
||||
int blob_write_shared(uint64_t handle_id, uint64_t logical_size, const void *buf, size_t len, uint32_t write_flags);
|
||||
ssize_t blob_read_ex(uint64_t handle_id, uint64_t offset, void *buf, size_t len, uint32_t read_flags);
|
||||
int blob_read(uint64_t handle_id, uint64_t offset, void *buf, size_t len);
|
||||
ssize_t blob_read_shared(uint64_t handle_id, uint64_t logical_size, void *buf, size_t len);
|
||||
int blob_resize(uint64_t handle_id, uint64_t new_size);
|
||||
int blob_sync_md(uint64_t handle_id);
|
||||
int blob_close(uint64_t handle_id);
|
||||
int blob_delete(uint64_t blob_id);
|
||||
int blob_add_ref(uint64_t handle_id, uint32_t ref_delta);
|
||||
int blob_add_ref_batch(const uint64_t *handle_ids, const uint32_t *ref_deltas, uint32_t count);
|
||||
int blob_seek(uint64_t handle_id, int64_t offset, int whence, uint64_t logical_size, uint64_t *new_offset_out);
|
||||
int blob_get_pos(uint64_t handle_id, uint64_t *offset_out);
|
||||
int blob_get_flags(uint64_t handle_id, uint32_t *flags_out);
|
||||
int blob_set_flags(uint64_t handle_id, uint32_t flags);
|
||||
|
||||
#endif // __ZVFS_IO_ENGINE_H__
|
||||
|
||||
@@ -177,6 +177,12 @@ test_dup_fcntl_ioctl(const char *workdir)
|
||||
int file_flags_after = fcntl(fd, F_GETFL);
|
||||
ASSERT_SYS_OK(file_flags_after);
|
||||
ASSERT_TRUE((file_flags_after & O_APPEND) != 0, "O_APPEND should be set");
|
||||
if (dup_supported) {
|
||||
int file_flags_dup = fcntl(fd2, F_GETFL);
|
||||
ASSERT_SYS_OK(file_flags_dup);
|
||||
ASSERT_TRUE((file_flags_dup & O_APPEND) != 0,
|
||||
"dup should share status flags like O_APPEND");
|
||||
}
|
||||
|
||||
int avail = -1;
|
||||
ASSERT_SYS_OK(ioctl(dup_supported ? fd2 : fd, FIONREAD, &avail));
|
||||
|
||||
Reference in New Issue
Block a user