zvfs: 重构核心读写逻辑并新增 POSIX hook;引入目录元数据与伪 fd;分离创建、打开、关闭、删除的逻辑;
This commit is contained in:
442
zvfs.old/zvfs.c
Executable file
442
zvfs.old/zvfs.c
Executable file
@@ -0,0 +1,442 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <spdk/event.h>
|
||||
#include <spdk/blob.h>
|
||||
#include <spdk/bdev.h>
|
||||
#include <spdk/blob_bdev.h>
|
||||
#include <spdk/env.h>
|
||||
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user