#include #include #include #include #include #include #include #include #define FILENAME_LENGTH 1024 typedef struct zfs_ctx_s { struct spdk_bs_dev *bsdev; struct spdk_blob_store *bs; spdk_blob_id blobid; struct spdk_blob *blob; struct spdk_io_channel *channel; uint8_t *write_buff; uint8_t *read_buff; uint64_t io_unit_size; bool finished; } zfs_ctx_t; typedef struct zvfs_file_s { char filename[FILENAME_LENGTH]; struct spdk_blob *blob; spdk_blob_id blobid; struct zvfs_s *fs; uint8_t *write_buff; // uint8_t *read_buff; // bool finished; } zvfs_file_t; typedef struct zvfs_file_operation_s { int (*open)(void); int (*write)(void); int (*read)(void); int (*close)(void); } zvfs_file_operation_t; typedef struct zvfs_s { struct spdk_bs_dev *bsdev; struct spdk_blob_store *bs; struct spdk_io_channel *channel; uint64_t io_unit_size; bool finished; } zvfs_t; typedef struct zvfs_operation_s { int (*load)(zvfs_t *fs); int (*unload)(zvfs_t *fs); } zvfs_operation_t; struct spdk_thread *global_thread; zvfs_t *fs; static void zvfs_spdk_bdev_complete(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) { printf("blobstore create success\n"); } static void zvfs_spdk_bs_unload_complete(void *arg, int bserrno) { zvfs_t *ctx = arg; #if 0 if (ctx->read_buff) { spdk_free(ctx->read_buff); ctx->read_buff = NULL; } if (ctx->write_buff) { spdk_free(ctx->write_buff); ctx->write_buff = NULL; } #endif ctx->finished = true; } static void zvfs_spdk_bs_destroy_complete(void *arg, int bserrno) { zvfs_t *ctx = arg; if (ctx->bs) { if (ctx->channel) { spdk_bs_free_io_channel(ctx->channel); } spdk_bs_unload(ctx->bs, zvfs_spdk_bs_unload_complete, ctx); } } static void zvfs_spdk_blob_close_complete(void *arg, int bserrno) { zvfs_file_t *file = arg; #if 1 if (file->read_buff) { spdk_free(file->read_buff); file->read_buff = NULL; } if (file->write_buff) { spdk_free(file->write_buff); file->write_buff = NULL; } #endif file->finished = true; } static void zvfs_spdk_blob_read_complete(void *arg, int bserrno) { zvfs_file_t *file = arg; //SPDK_NOTICELOG("read : %s\n", file->read_buff); #if 0 int match_res = memcmp(file->write_buff, file->read_buff, file->fs->io_unit_size); if (!match_res) { SPDK_NOTICELOG("read SUCCESS and data matches!\n"); } #endif file->finished = true; } static void zvfs_spdk_blob_write_complete(void *arg, int bserrno) { zvfs_file_t *file = arg; file->finished = true; //SPDK_NOTICELOG("ctx->finished = true\n"); } static void zvfs_spdk_blob_sync_complete(void *arg, int bserrno) { zvfs_file_t *file = arg; #if 1 file->write_buff = spdk_malloc(file->fs->io_unit_size, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); if (file->write_buff == NULL) { return ; } file->read_buff = spdk_malloc(file->fs->io_unit_size, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); if (file->read_buff == NULL) { return ; } #endif file->finished = true; //SPDK_NOTICELOG("ctx->finished = true\n"); } static void zvfs_spdk_bdev_resize_blob_complete(void *arg, int bserrno) { zvfs_file_t *file = arg; spdk_blob_sync_md(file->blob, zvfs_spdk_blob_sync_complete, file); } static void zvfs_spdk_bdev_open_blob_complete(void *arg, struct spdk_blob *blb, int bserrno) { zvfs_file_t *file = arg; file->blob = blb; uint64_t numfreed = spdk_bs_free_cluster_count(file->fs->bs); //SPDK_NOTICELOG("numfreed: %"PRIu64"\n", numfreed); spdk_blob_resize(blb, numfreed, zvfs_spdk_bdev_resize_blob_complete, file); } // create // open static void zvfs_spdk_bdev_create_blob_complete(void *arg, spdk_blob_id blobid, int bserrno) { //SPDK_NOTICELOG("spdk_blob_id: %"PRIu64"\n", blobid); zvfs_file_t *file = arg; file->blobid = blobid; #if 1 spdk_bs_open_blob(file->fs->bs, blobid, zvfs_spdk_bdev_open_blob_complete, file); #endif } static void zvfs_spdk_bdev_init_complete(void *arg, struct spdk_blob_store *bs, int bserrno) { zvfs_t *ctx = arg; ctx->bs = bs; ctx->io_unit_size = spdk_bs_get_io_unit_size(bs); #if 1 ctx->channel = spdk_bs_alloc_io_channel(ctx->bs); if (ctx->channel == NULL) { return ; } #endif //SPDK_NOTICELOG("io_unit_size --> %" PRIu64 "\n", ctx->io_unit_size); ctx->finished = true; } // zvfs static void zvfs_do_load(void *arg) { zvfs_t *ctx = arg; struct spdk_bs_dev *bsdev = NULL; const char * bdev_name = "Malloc0"; int res = spdk_bdev_create_bs_dev_ext(bdev_name, zvfs_spdk_bdev_complete, NULL, &bsdev); if (res != 0) { spdk_app_stop(-1); return ; } ctx->bsdev = bsdev; spdk_bs_init(bsdev, NULL, zvfs_spdk_bdev_init_complete, ctx); return ; } // unload static void zvfs_do_unload(void *arg) { zvfs_t *ctx = arg; //spdk_bs_delete_blob(ctx->bs, ctx->blobid, zvfs_spdk_bs_delete_complete, ctx); spdk_bs_destroy(ctx->bs, zvfs_spdk_bs_destroy_complete, ctx); return ; } /// zvfs file api // static const int POLLER_MAX_TIME = 100000; static bool poller(struct spdk_thread *thread, spdk_msg_fn start_fn, void *ctx, bool *finished) { spdk_thread_send_msg(thread, start_fn, ctx); int poller_count = 0; do { spdk_thread_poll(thread, 0, 0); poller_count ++; } while (!(*finished) && poller_count < POLLER_MAX_TIME); if (!(*finished) && poller_count >= POLLER_MAX_TIME) { //timeout return false; } return true; } /// static void zvfs_do_open(void *arg) { zvfs_file_t *ctx = arg; #if 0 spdk_bs_open_blob(ctx->fs->bs, ctx->blobid, zvfs_spdk_bdev_open_blob_complete, ctx); #else spdk_bs_create_blob(ctx->fs->bs, zvfs_spdk_bdev_create_blob_complete, ctx); #endif return ; } static void zvfs_do_write(void *arg) { zvfs_file_t *file = arg; #if 0 ctx->write_buff = spdk_malloc(ctx->io_unit_size, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); if (ctx->write_buff == NULL) { return ; } memset(ctx->write_buff, 'K', ctx->io_unit_size); ctx->write_buff[ctx->io_unit_size-1] = '\0'; #endif spdk_blob_io_write(file->blob, file->fs->channel, file->write_buff, 0, 1, zvfs_spdk_blob_write_complete, file); return ; } static void zvfs_do_read(void *arg) { zvfs_file_t *file = arg; #if 0 ctx->read_buff = spdk_malloc(ctx->io_unit_size, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); if (ctx->read_buff == NULL) { return ; } #endif spdk_blob_io_read(file->blob, file->fs->channel, file->read_buff, 0, 1, zvfs_spdk_blob_read_complete, file); return ; } static void zvfs_do_close(void *arg) { zvfs_file_t *file = arg; spdk_blob_close(file->blob, zvfs_spdk_blob_close_complete, file); return ; } // errno // 1. // strerr // //// zvfs_file_open static int zvfs_file_open(zvfs_file_t *file) { file->finished = false; if (!poller(global_thread, zvfs_do_open, file, &file->finished)) { return -1; } return 0; } static int zvfs_file_close(zvfs_file_t *file) { file->finished = false; if (!poller(global_thread, zvfs_do_close, file, &file->finished)) { return -1; } return 0; } static int zvfs_file_write(zvfs_file_t *file, const void *buf, size_t size) { file->finished = false; memcpy(file->write_buff, buf, size); // if (!poller(global_thread, zvfs_do_write, file, &file->finished)) { return -1; } return 0; } static int zvfs_file_read(zvfs_file_t *file, void *buf, size_t size) { file->finished = false; if (!poller(global_thread, zvfs_do_read, file, &file->finished)) { return -1; } memcpy(buf, file->read_buff, size); return 0; } //// zvfs static int zvfs_load(zvfs_t *fs) { fs->finished = false; if (!poller(global_thread, zvfs_do_load, fs, &fs->finished)) { return -1; } return 0; } static int zvfs_unload(zvfs_t *fs) { fs->finished = false; if (!poller(global_thread, zvfs_do_unload, fs, &fs->finished)) { return -1; } return 0; } // fd #define MAX_FD_COUNT 1024 #define DEFAULT_FD_NUM 3 static unsigned char fd_table[MAX_FD_COUNT / 8] = {0}; zvfs_file_t *files[MAX_FD_COUNT] = {0}; static int get_fd_frombitmap(void) { int fd = DEFAULT_FD_NUM; for ( ;fd < MAX_FD_COUNT;fd ++) { if ((fd_table[fd/8] & (0x1 << (fd % 8))) == 0) { fd_table[fd/8] |= (0x1 << (fd % 8)); return fd; } } return -1; } static int set_fd_frombitmap(int fd) { if (fd >= MAX_FD_COUNT) return -1; fd_table[fd/8] &= ~(0x1 << (fd % 8)); return 0; } static int zvfs_open(const char *filename, int flag) { zvfs_file_t *file = (zvfs_file_t*)malloc(sizeof(zvfs_file_t)); if (file == NULL) return -1; int fd = get_fd_frombitmap(); file->fs = fs; files[fd] = file; zvfs_file_open(file); return fd; } static int zvfs_write(int fd,const void *buf, size_t count) { zvfs_file_t *file = files[fd]; zvfs_file_write(file, buf, count); return 0; } static int zvfs_read(int fd, void *buf, size_t count) { zvfs_file_t *file = files[fd]; zvfs_file_read(file, buf, count); return strlen(buf); } static int zvfs_close(int fd) { zvfs_file_t *file = files[fd]; zvfs_file_close(file); set_fd_frombitmap(fd); free(file); return 0; } /// hook #if 0 typedef int (*open_t)(const char *pathname, int flags); open_t open_f = NULL; typedef ssize_t (*write_t)(int fd, const void *buf, size_t n); write_t write_f = NULL; typedef ssize_t (*read_t)(int fd, void *buf, size_t n); read_t read_f = NULL; typedef int (*close_t)(int fd); close_t close_f; int zvfs_initilize = false; static int zvfs_setup(void); int open(const char *pathname, int flags, ...) { int ret = 0; ret = syscall(__NR_open, pathname, flags); return ret; } ssize_t write(int fd, const void *buf, size_t n) { int ret = 0; ret = syscall(__NR_write, buf, n); return ret; } ssize_t read(int fd, void *buf, size_t n) { int ret = 0; ret = syscall(__NR_read, buf, n); return ret; } int close (int fd) { int ret = 0; ret = syscall(__NR_close, fd); return ret; } #else #include #define DEBUG_ENABLE 1 #if DEBUG_ENABLE #define dblog(fmt, ...) printf(fmt, ##__VA_ARGS__) #else #define dblog(fmt, ...) #endif typedef int (*open_t)(const char *pathname, int flags); open_t open_f = NULL; typedef ssize_t (*write_t)(int fd, const void *buf, size_t n); write_t write_f = NULL; typedef ssize_t (*read_t)(int fd, void *buf, size_t n); read_t read_f = NULL; typedef int (*close_t)(int fd); close_t close_f = NULL; int open(const char *pathname, int flags, ...) { if (!open_f) { open_f = dlsym(RTLD_NEXT, "open"); } dblog("open.. %s\n", pathname); return open_f(pathname, flags); } ssize_t read(int fd, void *buf, size_t count) { ssize_t ret; if (!read_f) { read_f = dlsym(RTLD_NEXT, "read"); } ret = read_f(fd, buf, count); dblog("read.. : %ld, %ld\n", ret, count); return ret; } ssize_t write(int fd, const void *buf, size_t count) { if (!write_f) { write_f = dlsym(RTLD_NEXT, "write"); } dblog("write.. : %ld\n", count); return write_f(fd, buf, count); } int close(int fd) { if (!close_f) { close_f = dlsym(RTLD_NEXT, "close"); } dblog("close..\n"); return close_f(fd); } #endif #if 1 static const char *json_file = "/home/king/share/spdk/examples/mysql/hello_blob.json"; static void json_app_load_done(int rc, void *ctx) { bool *done = ctx; *done = true; // SPDK_NOTICELOG("json_app_load_done\n"); } static 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); } static int zvfs_env_setup(void) { struct spdk_env_opts opts; spdk_env_opts_init(&opts); if (spdk_env_init(&opts) != 0) { 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; poller(global_thread, zvfs_json_load_fn, &done, &done); return 0; } // blob --> json static int zvfs_setup(void) { zvfs_env_setup(); zvfs_t *ctx = calloc(1, sizeof(zvfs_t)); zvfs_load(ctx); fs = ctx; return 0; } #if 0 int main(int argc, char *argv[]) { printf("zvfs_env_setup111\n"); #if 0 zvfs_env_setup(); // load --> bs_init, blob_create, blob_open, blob_resize zfs_ctx_t *ctx = calloc(1, sizeof(zfs_ctx_t)); ctx->finished = false; poller(global_thread, zvfs_do_load, ctx, &ctx->finished); // open ctx->finished = false; poller(global_thread, zvfs_do_open, ctx, &ctx->finished); // write ctx->finished = false; poller(global_thread, zvfs_do_write, ctx, &ctx->finished); // read ctx->finished = false; poller(global_thread, zvfs_do_read, ctx, &ctx->finished); // close ctx->finished = false; poller(global_thread, zvfs_do_close, ctx, &ctx->finished); // unload ctx->finished = false; poller(global_thread, zvfs_do_unload, ctx, &ctx->finished); #elif 0 zvfs_env_setup(); zvfs_t *ctx = calloc(1, sizeof(zvfs_t)); zvfs_load(ctx); fs = ctx; zvfs_file_t *file = calloc(1, sizeof(zvfs_file_t)); file->fs = ctx; zvfs_file_open(file); char *buffer = "zvoice.king"; zvfs_file_write(file, buffer, strlen(buffer)); char rbuffer[1024] = {0}; zvfs_file_read(file, rbuffer, 1024); printf("rbuffer: %s\n", rbuffer); zvfs_file_close(file); zvfs_unload(ctx); #elif 0 zvfs_t *ctx = calloc(1, sizeof(zvfs_t)); zvfs_load(ctx); fs = ctx; int fd = zvfs_open("king.txt", 0x666); char *buffer = "zvoice.king"; zvfs_write(fd, buffer, strlen(buffer)); char rbuffer[1024] = {0}; zvfs_read(fd, rbuffer, 1024); printf("rbuffer: %s\n", rbuffer); zvfs_close(fd); zvfs_unload(ctx); #else printf("zvfs_env_setup\n"); //zvfs_t *ctx = calloc(1, sizeof(zvfs_t)); //zvfs_load(ctx); //fs = ctx; printf("zvfs_load\n"); int fd = open("/home/king/share/spdk/examples/mysql/a.txt", O_RDWR | O_CREAT); printf("fd: %d, %s\n", fd, strerror(errno)); char *buffer = "zvoice.king"; int ret = write(fd, buffer, strlen(buffer)); lseek(fd, 0, SEEK_SET); char rbuffer[1024] = {0}; ret = read(fd, rbuffer, 1024); printf("ret : %d, rbuffer: %s\n", ret, rbuffer); close(fd); //zvfs_unload(fs); return 0; #endif } #endif #elif 0 int main() { int fd = open("./a.txt", RW); char *buffer = "zvoice.king"; write(fd, buffer, strlen(buffer)); char rbuffer[1024] = {0}; read(fd, rbuffer, 1024); close(fd); } #else int main(int argc, char *argv[]) { if (argc < 2) { return -1; } struct spdk_app_opts opts= {0}; spdk_app_opts_init(&opts, sizeof(opts)); opts.name = "zvfs"; opts.json_config_file = argv[1]; printf("spdk_set_thread --> \n"); zfs_ctx_t *ctx = calloc(1, sizeof(zfs_ctx_t)); spdk_app_start(&opts, zvfs_entry, ctx); spdk_app_fini(); free(ctx); return 0; } #endif