14ed98d54SEvgeniy Kochetov /* SPDX-License-Identifier: BSD-3-Clause 24ed98d54SEvgeniy Kochetov * Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 34ed98d54SEvgeniy Kochetov */ 44ed98d54SEvgeniy Kochetov 54ed98d54SEvgeniy Kochetov #include "spdk/stdinc.h" 64ed98d54SEvgeniy Kochetov #include "spdk/thread.h" 74ed98d54SEvgeniy Kochetov #include "spdk/fsdev.h" 84ed98d54SEvgeniy Kochetov #include "spdk/env.h" 94ed98d54SEvgeniy Kochetov #include "spdk/event.h" 104ed98d54SEvgeniy Kochetov #include "spdk/log.h" 114ed98d54SEvgeniy Kochetov #include "spdk/string.h" 124ed98d54SEvgeniy Kochetov 134ed98d54SEvgeniy Kochetov #define TEST_FILENAME "hello_file" 144ed98d54SEvgeniy Kochetov #define DATA_SIZE 512 154ed98d54SEvgeniy Kochetov #define ROOT_NODEID 1 164ed98d54SEvgeniy Kochetov 174ed98d54SEvgeniy Kochetov static char *g_fsdev_name = "Fs0"; 184ed98d54SEvgeniy Kochetov int g_result = 0; 194ed98d54SEvgeniy Kochetov 204ed98d54SEvgeniy Kochetov /* 214ed98d54SEvgeniy Kochetov * We'll use this struct to gather housekeeping hello_context to pass between 224ed98d54SEvgeniy Kochetov * our events and callbacks. 234ed98d54SEvgeniy Kochetov */ 244ed98d54SEvgeniy Kochetov struct hello_context_t { 254ed98d54SEvgeniy Kochetov struct spdk_thread *app_thread; 264ed98d54SEvgeniy Kochetov struct spdk_fsdev_desc *fsdev_desc; 274ed98d54SEvgeniy Kochetov struct spdk_io_channel *fsdev_io_channel; 284ed98d54SEvgeniy Kochetov struct spdk_fsdev_file_object *root_fobject; 294ed98d54SEvgeniy Kochetov char *fsdev_name; 304ed98d54SEvgeniy Kochetov int thread_count; 314ed98d54SEvgeniy Kochetov }; 324ed98d54SEvgeniy Kochetov 334ed98d54SEvgeniy Kochetov struct hello_thread_t { 344ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context; 354ed98d54SEvgeniy Kochetov struct spdk_thread *thread; 364ed98d54SEvgeniy Kochetov struct spdk_io_channel *fsdev_io_channel; 374ed98d54SEvgeniy Kochetov uint64_t unique; 384ed98d54SEvgeniy Kochetov uint8_t *buf; 394ed98d54SEvgeniy Kochetov char *file_name; 404ed98d54SEvgeniy Kochetov struct spdk_fsdev_file_object *fobject; 414ed98d54SEvgeniy Kochetov struct spdk_fsdev_file_handle *fhandle; 424ed98d54SEvgeniy Kochetov struct iovec iov[2]; 434ed98d54SEvgeniy Kochetov }; 444ed98d54SEvgeniy Kochetov 454ed98d54SEvgeniy Kochetov /* 464ed98d54SEvgeniy Kochetov * Usage function for printing parameters that are specific to this application 474ed98d54SEvgeniy Kochetov */ 484ed98d54SEvgeniy Kochetov static void 494ed98d54SEvgeniy Kochetov hello_fsdev_usage(void) 504ed98d54SEvgeniy Kochetov { 514ed98d54SEvgeniy Kochetov printf(" -f <fs> name of the fsdev to use\n"); 524ed98d54SEvgeniy Kochetov } 534ed98d54SEvgeniy Kochetov 544ed98d54SEvgeniy Kochetov /* 554ed98d54SEvgeniy Kochetov * This function is called to parse the parameters that are specific to this application 564ed98d54SEvgeniy Kochetov */ 574ed98d54SEvgeniy Kochetov static int 584ed98d54SEvgeniy Kochetov hello_fsdev_parse_arg(int ch, char *arg) 594ed98d54SEvgeniy Kochetov { 604ed98d54SEvgeniy Kochetov switch (ch) { 614ed98d54SEvgeniy Kochetov case 'f': 624ed98d54SEvgeniy Kochetov g_fsdev_name = arg; 634ed98d54SEvgeniy Kochetov break; 644ed98d54SEvgeniy Kochetov default: 654ed98d54SEvgeniy Kochetov return -EINVAL; 664ed98d54SEvgeniy Kochetov } 674ed98d54SEvgeniy Kochetov return 0; 684ed98d54SEvgeniy Kochetov } 694ed98d54SEvgeniy Kochetov 704ed98d54SEvgeniy Kochetov static void 714ed98d54SEvgeniy Kochetov hello_app_done(struct hello_context_t *hello_context, int rc) 724ed98d54SEvgeniy Kochetov { 734ed98d54SEvgeniy Kochetov spdk_put_io_channel(hello_context->fsdev_io_channel); 744ed98d54SEvgeniy Kochetov spdk_fsdev_close(hello_context->fsdev_desc); 754ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Stopping app: rc %d\n", rc); 764ed98d54SEvgeniy Kochetov spdk_app_stop(rc); 774ed98d54SEvgeniy Kochetov } 784ed98d54SEvgeniy Kochetov 794ed98d54SEvgeniy Kochetov static void 804ed98d54SEvgeniy Kochetov root_forget_complete(void *cb_arg, struct spdk_io_channel *ch, int status) 814ed98d54SEvgeniy Kochetov { 824ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = cb_arg; 834ed98d54SEvgeniy Kochetov 844ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Root forget complete (status=%d)\n", status); 854ed98d54SEvgeniy Kochetov if (status) { 864ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Root forget failed: error %d\n", status); 874ed98d54SEvgeniy Kochetov g_result = EINVAL; 884ed98d54SEvgeniy Kochetov } 894ed98d54SEvgeniy Kochetov 904ed98d54SEvgeniy Kochetov hello_app_done(hello_context, g_result); 914ed98d54SEvgeniy Kochetov } 924ed98d54SEvgeniy Kochetov 934ed98d54SEvgeniy Kochetov static void 944ed98d54SEvgeniy Kochetov hello_root_release(struct hello_context_t *hello_context) 954ed98d54SEvgeniy Kochetov { 964ed98d54SEvgeniy Kochetov int res; 974ed98d54SEvgeniy Kochetov 984ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Forget root\n"); 994ed98d54SEvgeniy Kochetov res = spdk_fsdev_forget(hello_context->fsdev_desc, hello_context->fsdev_io_channel, 0, 1004ed98d54SEvgeniy Kochetov hello_context->root_fobject, 1, 1014ed98d54SEvgeniy Kochetov root_forget_complete, hello_context); 1024ed98d54SEvgeniy Kochetov if (res) { 1034ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Failed to forget root (err=%d)\n", res); 1044ed98d54SEvgeniy Kochetov hello_app_done(hello_context, EINVAL); 1054ed98d54SEvgeniy Kochetov } 1064ed98d54SEvgeniy Kochetov } 1074ed98d54SEvgeniy Kochetov 1084ed98d54SEvgeniy Kochetov static void 1094ed98d54SEvgeniy Kochetov hello_app_notify_thread_done(void *ctx) 1104ed98d54SEvgeniy Kochetov { 1114ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = (struct hello_context_t *)ctx; 1124ed98d54SEvgeniy Kochetov 1134ed98d54SEvgeniy Kochetov assert(hello_context->thread_count > 0); 1144ed98d54SEvgeniy Kochetov hello_context->thread_count--; 1154ed98d54SEvgeniy Kochetov if (hello_context->thread_count == 0) { 1164ed98d54SEvgeniy Kochetov hello_root_release(hello_context); 1174ed98d54SEvgeniy Kochetov } 1184ed98d54SEvgeniy Kochetov } 1194ed98d54SEvgeniy Kochetov 1204ed98d54SEvgeniy Kochetov static void 1214ed98d54SEvgeniy Kochetov hello_thread_done(struct hello_thread_t *hello_thread, int rc) 1224ed98d54SEvgeniy Kochetov { 1234ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = hello_thread->hello_context; 1244ed98d54SEvgeniy Kochetov 1254ed98d54SEvgeniy Kochetov spdk_put_io_channel(hello_thread->fsdev_io_channel); 1264ed98d54SEvgeniy Kochetov free(hello_thread->buf); 1274ed98d54SEvgeniy Kochetov free(hello_thread->file_name); 1284ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Thread %s done: rc %d\n", 1294ed98d54SEvgeniy Kochetov spdk_thread_get_name(hello_thread->thread), rc); 1304ed98d54SEvgeniy Kochetov spdk_thread_exit(hello_thread->thread); 1314ed98d54SEvgeniy Kochetov free(hello_thread); 1324ed98d54SEvgeniy Kochetov if (rc) { 1334ed98d54SEvgeniy Kochetov g_result = rc; 1344ed98d54SEvgeniy Kochetov } 1354ed98d54SEvgeniy Kochetov 1364ed98d54SEvgeniy Kochetov spdk_thread_send_msg(hello_context->app_thread, hello_app_notify_thread_done, hello_context); 1374ed98d54SEvgeniy Kochetov } 1384ed98d54SEvgeniy Kochetov 1394ed98d54SEvgeniy Kochetov static bool 1404ed98d54SEvgeniy Kochetov hello_check_complete(struct hello_thread_t *hello_thread, int status, const char *op) 1414ed98d54SEvgeniy Kochetov { 1424ed98d54SEvgeniy Kochetov hello_thread->unique++; 1434ed98d54SEvgeniy Kochetov if (status) { 1444ed98d54SEvgeniy Kochetov SPDK_ERRLOG("%s failed with %d\n", op, status); 1454ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, EIO); 1464ed98d54SEvgeniy Kochetov return false; 1474ed98d54SEvgeniy Kochetov } 1484ed98d54SEvgeniy Kochetov 1494ed98d54SEvgeniy Kochetov return true; 1504ed98d54SEvgeniy Kochetov } 1514ed98d54SEvgeniy Kochetov 1524ed98d54SEvgeniy Kochetov static void 1534ed98d54SEvgeniy Kochetov unlink_complete(void *cb_arg, struct spdk_io_channel *ch, int status) 1544ed98d54SEvgeniy Kochetov { 1554ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread = cb_arg; 1564ed98d54SEvgeniy Kochetov 1574ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Unlink complete (status=%d)\n", status); 1584ed98d54SEvgeniy Kochetov if (!hello_check_complete(hello_thread, status, "unlink")) { 1594ed98d54SEvgeniy Kochetov return; 1604ed98d54SEvgeniy Kochetov } 1614ed98d54SEvgeniy Kochetov 1624ed98d54SEvgeniy Kochetov hello_thread->fobject = NULL; 1634ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, 0); 1644ed98d54SEvgeniy Kochetov } 1654ed98d54SEvgeniy Kochetov 1664ed98d54SEvgeniy Kochetov static void 1674ed98d54SEvgeniy Kochetov hello_unlink(struct hello_thread_t *hello_thread) 1684ed98d54SEvgeniy Kochetov { 1694ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = hello_thread->hello_context; 1704ed98d54SEvgeniy Kochetov int res; 1714ed98d54SEvgeniy Kochetov 1724ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Unlink file %s\n", hello_thread->file_name); 1734ed98d54SEvgeniy Kochetov 1744ed98d54SEvgeniy Kochetov res = spdk_fsdev_unlink(hello_context->fsdev_desc, hello_thread->fsdev_io_channel, 1754ed98d54SEvgeniy Kochetov hello_thread->unique, hello_context->root_fobject, hello_thread->file_name, 1764ed98d54SEvgeniy Kochetov unlink_complete, hello_thread); 1774ed98d54SEvgeniy Kochetov if (res) { 1784ed98d54SEvgeniy Kochetov SPDK_ERRLOG("unlink failed with %d\n", res); 1794ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, EIO); 1804ed98d54SEvgeniy Kochetov } 1814ed98d54SEvgeniy Kochetov } 1824ed98d54SEvgeniy Kochetov 1834ed98d54SEvgeniy Kochetov static void 1844ed98d54SEvgeniy Kochetov release_complete(void *cb_arg, struct spdk_io_channel *ch, int status) 1854ed98d54SEvgeniy Kochetov { 1864ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread = cb_arg; 1874ed98d54SEvgeniy Kochetov 1884ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Release complete (status=%d)\n", status); 1894ed98d54SEvgeniy Kochetov if (!hello_check_complete(hello_thread, status, "release")) { 1904ed98d54SEvgeniy Kochetov return; 1914ed98d54SEvgeniy Kochetov } 1924ed98d54SEvgeniy Kochetov 1934ed98d54SEvgeniy Kochetov hello_thread->fhandle = NULL; 1944ed98d54SEvgeniy Kochetov hello_unlink(hello_thread); 1954ed98d54SEvgeniy Kochetov } 1964ed98d54SEvgeniy Kochetov 1974ed98d54SEvgeniy Kochetov static void 1984ed98d54SEvgeniy Kochetov hello_release(struct hello_thread_t *hello_thread) 1994ed98d54SEvgeniy Kochetov { 2004ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = hello_thread->hello_context; 2014ed98d54SEvgeniy Kochetov int res; 2024ed98d54SEvgeniy Kochetov 2034ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Release file handle %p\n", hello_thread->fhandle); 2044ed98d54SEvgeniy Kochetov 2054ed98d54SEvgeniy Kochetov res = spdk_fsdev_release(hello_context->fsdev_desc, hello_thread->fsdev_io_channel, 2064ed98d54SEvgeniy Kochetov hello_thread->unique, hello_thread->fobject, hello_thread->fhandle, 2074ed98d54SEvgeniy Kochetov release_complete, hello_thread); 2084ed98d54SEvgeniy Kochetov if (res) { 2094ed98d54SEvgeniy Kochetov SPDK_ERRLOG("release failed with %d\n", res); 2104ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, EIO); 2114ed98d54SEvgeniy Kochetov } 2124ed98d54SEvgeniy Kochetov } 2134ed98d54SEvgeniy Kochetov 2144ed98d54SEvgeniy Kochetov static void 2154ed98d54SEvgeniy Kochetov read_complete(void *cb_arg, struct spdk_io_channel *ch, int status, uint32_t data_size) 2164ed98d54SEvgeniy Kochetov { 2174ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread = cb_arg; 2184ed98d54SEvgeniy Kochetov uint8_t data = spdk_env_get_current_core(); 2194ed98d54SEvgeniy Kochetov uint32_t i; 2204ed98d54SEvgeniy Kochetov 2214ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Read complete (status=%d, %" PRIu32 "bytes read)\n", status, data_size); 2224ed98d54SEvgeniy Kochetov if (!hello_check_complete(hello_thread, status, "read")) { 2234ed98d54SEvgeniy Kochetov return; 2244ed98d54SEvgeniy Kochetov } 2254ed98d54SEvgeniy Kochetov 2264ed98d54SEvgeniy Kochetov assert(data_size == DATA_SIZE); 2274ed98d54SEvgeniy Kochetov 2284ed98d54SEvgeniy Kochetov for (i = 0; i < DATA_SIZE; ++i) { 2294ed98d54SEvgeniy Kochetov if (hello_thread->buf[i] != data) { 2304ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Bad read data at offset %d, 0x%02X != 0x%02X\n", 2314ed98d54SEvgeniy Kochetov i, hello_thread->buf[i], data); 2324ed98d54SEvgeniy Kochetov break; 2334ed98d54SEvgeniy Kochetov } 2344ed98d54SEvgeniy Kochetov } 2354ed98d54SEvgeniy Kochetov 2364ed98d54SEvgeniy Kochetov hello_release(hello_thread); 2374ed98d54SEvgeniy Kochetov } 2384ed98d54SEvgeniy Kochetov 2394ed98d54SEvgeniy Kochetov static void 2404ed98d54SEvgeniy Kochetov hello_read(struct hello_thread_t *hello_thread) 2414ed98d54SEvgeniy Kochetov { 2424ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = hello_thread->hello_context; 2434ed98d54SEvgeniy Kochetov int res; 2444ed98d54SEvgeniy Kochetov 2454ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Read from file handle %p\n", hello_thread->fhandle); 2464ed98d54SEvgeniy Kochetov 2474ed98d54SEvgeniy Kochetov memset(hello_thread->buf, 0xFF, DATA_SIZE); 2484ed98d54SEvgeniy Kochetov 2494ed98d54SEvgeniy Kochetov hello_thread->iov[0].iov_base = hello_thread->buf; 2504ed98d54SEvgeniy Kochetov hello_thread->iov[0].iov_len = DATA_SIZE / 4; 2514ed98d54SEvgeniy Kochetov hello_thread->iov[1].iov_base = hello_thread->buf + hello_thread->iov[0].iov_len; 2524ed98d54SEvgeniy Kochetov hello_thread->iov[1].iov_len = DATA_SIZE - hello_thread->iov[0].iov_len; 2534ed98d54SEvgeniy Kochetov 2544ed98d54SEvgeniy Kochetov res = spdk_fsdev_read(hello_context->fsdev_desc, hello_thread->fsdev_io_channel, 2554ed98d54SEvgeniy Kochetov hello_thread->unique, hello_thread->fobject, hello_thread->fhandle, 2564ed98d54SEvgeniy Kochetov DATA_SIZE, 0, 0, hello_thread->iov, 2, NULL, 2574ed98d54SEvgeniy Kochetov read_complete, hello_thread); 2584ed98d54SEvgeniy Kochetov if (res) { 2594ed98d54SEvgeniy Kochetov SPDK_ERRLOG("write failed with %d\n", res); 2604ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, EIO); 2614ed98d54SEvgeniy Kochetov } 2624ed98d54SEvgeniy Kochetov } 2634ed98d54SEvgeniy Kochetov 2644ed98d54SEvgeniy Kochetov static void 2654ed98d54SEvgeniy Kochetov write_complete(void *cb_arg, struct spdk_io_channel *ch, int status, uint32_t data_size) 2664ed98d54SEvgeniy Kochetov { 2674ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread = cb_arg; 2684ed98d54SEvgeniy Kochetov 2694ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Write complete (status=%d, %" PRIu32 "bytes written)\n", status, data_size); 2704ed98d54SEvgeniy Kochetov if (!hello_check_complete(hello_thread, status, "write")) { 2714ed98d54SEvgeniy Kochetov return; 2724ed98d54SEvgeniy Kochetov } 2734ed98d54SEvgeniy Kochetov 2744ed98d54SEvgeniy Kochetov assert(data_size == DATA_SIZE); 2754ed98d54SEvgeniy Kochetov hello_read(hello_thread); 2764ed98d54SEvgeniy Kochetov } 2774ed98d54SEvgeniy Kochetov 2784ed98d54SEvgeniy Kochetov static void 2794ed98d54SEvgeniy Kochetov hello_write(struct hello_thread_t *hello_thread) 2804ed98d54SEvgeniy Kochetov { 2814ed98d54SEvgeniy Kochetov uint8_t data = spdk_env_get_current_core(); 2824ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = hello_thread->hello_context; 2834ed98d54SEvgeniy Kochetov int res; 2844ed98d54SEvgeniy Kochetov 2854ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Write to file handle %p\n", hello_thread->fhandle); 2864ed98d54SEvgeniy Kochetov 2874ed98d54SEvgeniy Kochetov memset(hello_thread->buf, data, DATA_SIZE); 2884ed98d54SEvgeniy Kochetov 2894ed98d54SEvgeniy Kochetov hello_thread->iov[0].iov_base = hello_thread->buf; 2904ed98d54SEvgeniy Kochetov hello_thread->iov[0].iov_len = DATA_SIZE / 2; 2914ed98d54SEvgeniy Kochetov hello_thread->iov[1].iov_base = hello_thread->buf + hello_thread->iov[0].iov_len; 2924ed98d54SEvgeniy Kochetov hello_thread->iov[1].iov_len = DATA_SIZE - hello_thread->iov[0].iov_len; 2934ed98d54SEvgeniy Kochetov 2944ed98d54SEvgeniy Kochetov res = spdk_fsdev_write(hello_context->fsdev_desc, hello_thread->fsdev_io_channel, 2954ed98d54SEvgeniy Kochetov hello_thread->unique, hello_thread->fobject, hello_thread->fhandle, 2964ed98d54SEvgeniy Kochetov DATA_SIZE, 0, 0, hello_thread->iov, 2, NULL, 2974ed98d54SEvgeniy Kochetov write_complete, hello_thread); 2984ed98d54SEvgeniy Kochetov if (res) { 2994ed98d54SEvgeniy Kochetov SPDK_ERRLOG("write failed with %d\n", res); 3004ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, EIO); 3014ed98d54SEvgeniy Kochetov } 3024ed98d54SEvgeniy Kochetov } 3034ed98d54SEvgeniy Kochetov 3044ed98d54SEvgeniy Kochetov static void 3054ed98d54SEvgeniy Kochetov fopen_complete(void *cb_arg, struct spdk_io_channel *ch, int status, 3064ed98d54SEvgeniy Kochetov struct spdk_fsdev_file_handle *fhandle) 3074ed98d54SEvgeniy Kochetov { 3084ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread = cb_arg; 3094ed98d54SEvgeniy Kochetov 3104ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Open complete (status=%d)\n", status); 3114ed98d54SEvgeniy Kochetov if (!hello_check_complete(hello_thread, status, "open")) { 3124ed98d54SEvgeniy Kochetov return; 3134ed98d54SEvgeniy Kochetov } 3144ed98d54SEvgeniy Kochetov 3154ed98d54SEvgeniy Kochetov hello_thread->fhandle = fhandle; 3164ed98d54SEvgeniy Kochetov hello_write(hello_thread); 3174ed98d54SEvgeniy Kochetov } 3184ed98d54SEvgeniy Kochetov 3194ed98d54SEvgeniy Kochetov static void 3204ed98d54SEvgeniy Kochetov hello_open(struct hello_thread_t *hello_thread) 3214ed98d54SEvgeniy Kochetov { 3224ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = hello_thread->hello_context; 3234ed98d54SEvgeniy Kochetov int res; 3244ed98d54SEvgeniy Kochetov 3254ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Open fobject %p\n", hello_thread->fobject); 3264ed98d54SEvgeniy Kochetov 3274ed98d54SEvgeniy Kochetov res = spdk_fsdev_fopen(hello_context->fsdev_desc, hello_thread->fsdev_io_channel, 3284ed98d54SEvgeniy Kochetov hello_thread->unique, hello_thread->fobject, O_RDWR, 3294ed98d54SEvgeniy Kochetov fopen_complete, hello_thread); 3304ed98d54SEvgeniy Kochetov if (res) { 3314ed98d54SEvgeniy Kochetov SPDK_ERRLOG("open failed with %d\n", res); 3324ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, EIO); 3334ed98d54SEvgeniy Kochetov } 3344ed98d54SEvgeniy Kochetov } 3354ed98d54SEvgeniy Kochetov 3364ed98d54SEvgeniy Kochetov static void 3374ed98d54SEvgeniy Kochetov lookup_complete(void *cb_arg, struct spdk_io_channel *ch, int status, 3384ed98d54SEvgeniy Kochetov struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 3394ed98d54SEvgeniy Kochetov { 3404ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread = cb_arg; 3414ed98d54SEvgeniy Kochetov 3424ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Lookup complete (status=%d)\n", status); 3434ed98d54SEvgeniy Kochetov if (!hello_check_complete(hello_thread, status, "lookup")) { 3444ed98d54SEvgeniy Kochetov return; 3454ed98d54SEvgeniy Kochetov } 3464ed98d54SEvgeniy Kochetov 3474ed98d54SEvgeniy Kochetov assert(hello_thread->fobject == fobject); 3484ed98d54SEvgeniy Kochetov hello_open(hello_thread); 3494ed98d54SEvgeniy Kochetov } 3504ed98d54SEvgeniy Kochetov 3514ed98d54SEvgeniy Kochetov static void 3524ed98d54SEvgeniy Kochetov hello_lookup(struct hello_thread_t *hello_thread) 3534ed98d54SEvgeniy Kochetov { 3544ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = hello_thread->hello_context; 3554ed98d54SEvgeniy Kochetov int res; 3564ed98d54SEvgeniy Kochetov 3574ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Lookup file %s\n", hello_thread->file_name); 3584ed98d54SEvgeniy Kochetov 3594ed98d54SEvgeniy Kochetov res = spdk_fsdev_lookup(hello_context->fsdev_desc, hello_thread->fsdev_io_channel, 3604ed98d54SEvgeniy Kochetov hello_thread->unique, hello_context->root_fobject, hello_thread->file_name, 3614ed98d54SEvgeniy Kochetov lookup_complete, hello_thread); 3624ed98d54SEvgeniy Kochetov if (res) { 3634ed98d54SEvgeniy Kochetov SPDK_ERRLOG("lookup failed with %d\n", res); 3644ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, EIO); 3654ed98d54SEvgeniy Kochetov } 3664ed98d54SEvgeniy Kochetov } 3674ed98d54SEvgeniy Kochetov 3684ed98d54SEvgeniy Kochetov static void 3694ed98d54SEvgeniy Kochetov mknod_complete(void *cb_arg, struct spdk_io_channel *ch, int status, 3704ed98d54SEvgeniy Kochetov struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 3714ed98d54SEvgeniy Kochetov { 3724ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread = cb_arg; 3734ed98d54SEvgeniy Kochetov 3744ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Mknod complete (status=%d)\n", status); 3754ed98d54SEvgeniy Kochetov if (!hello_check_complete(hello_thread, status, "mknod")) { 3764ed98d54SEvgeniy Kochetov return; 3774ed98d54SEvgeniy Kochetov } 3784ed98d54SEvgeniy Kochetov 3794ed98d54SEvgeniy Kochetov hello_thread->fobject = fobject; 3804ed98d54SEvgeniy Kochetov hello_lookup(hello_thread); 3814ed98d54SEvgeniy Kochetov } 3824ed98d54SEvgeniy Kochetov 3834ed98d54SEvgeniy Kochetov static void 3844ed98d54SEvgeniy Kochetov hello_mknod(void *ctx) 3854ed98d54SEvgeniy Kochetov { 3864ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread = (struct hello_thread_t *)ctx; 3874ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = hello_thread->hello_context; 3884ed98d54SEvgeniy Kochetov int res; 3894ed98d54SEvgeniy Kochetov 3904ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Mknod file %s\n", hello_thread->file_name); 3914ed98d54SEvgeniy Kochetov 3924ed98d54SEvgeniy Kochetov res = spdk_fsdev_mknod(hello_context->fsdev_desc, hello_thread->fsdev_io_channel, 3934ed98d54SEvgeniy Kochetov hello_thread->unique, hello_context->root_fobject, hello_thread->file_name, 3944ed98d54SEvgeniy Kochetov S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO, 0, 0, 0, mknod_complete, hello_thread); 3954ed98d54SEvgeniy Kochetov if (res) { 3964ed98d54SEvgeniy Kochetov SPDK_ERRLOG("mknod failed with %d\n", res); 3974ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, EIO); 3984ed98d54SEvgeniy Kochetov } 3994ed98d54SEvgeniy Kochetov } 4004ed98d54SEvgeniy Kochetov 4014ed98d54SEvgeniy Kochetov static void 4024ed98d54SEvgeniy Kochetov hello_start_thread(void *ctx) 4034ed98d54SEvgeniy Kochetov { 4044ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = (struct hello_context_t *)ctx; 4054ed98d54SEvgeniy Kochetov struct hello_thread_t *hello_thread; 4064ed98d54SEvgeniy Kochetov /* File name size assumes that core number will fit into 3 characters */ 4074ed98d54SEvgeniy Kochetov const int filename_size = strlen(TEST_FILENAME) + 5; 4084ed98d54SEvgeniy Kochetov 4094ed98d54SEvgeniy Kochetov hello_thread = calloc(1, sizeof(struct hello_thread_t)); 4104ed98d54SEvgeniy Kochetov if (!hello_thread) { 4114ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Failed to allocate thread context\n"); 4124ed98d54SEvgeniy Kochetov spdk_thread_send_msg(hello_context->app_thread, hello_app_notify_thread_done, hello_context); 4134ed98d54SEvgeniy Kochetov return; 4144ed98d54SEvgeniy Kochetov } 4154ed98d54SEvgeniy Kochetov 4164ed98d54SEvgeniy Kochetov hello_thread->hello_context = hello_context; 4174ed98d54SEvgeniy Kochetov hello_thread->thread = spdk_get_thread(); 4184ed98d54SEvgeniy Kochetov hello_thread->unique = 1; 4194ed98d54SEvgeniy Kochetov hello_thread->buf = (char *)malloc(DATA_SIZE); 4204ed98d54SEvgeniy Kochetov if (!hello_thread->buf) { 4214ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Could not allocate data buffer\n"); 4224ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, ENOMEM); 4234ed98d54SEvgeniy Kochetov return; 4244ed98d54SEvgeniy Kochetov } 4254ed98d54SEvgeniy Kochetov 4264ed98d54SEvgeniy Kochetov hello_thread->file_name = (char *)malloc(filename_size); 4274ed98d54SEvgeniy Kochetov if (!hello_thread->file_name) { 4284ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Could not allocate file name buffer\n"); 4294ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, ENOMEM); 4304ed98d54SEvgeniy Kochetov return; 4314ed98d54SEvgeniy Kochetov } 4324ed98d54SEvgeniy Kochetov 4334ed98d54SEvgeniy Kochetov if (snprintf(hello_thread->file_name, filename_size, "%s_%u", 4344ed98d54SEvgeniy Kochetov TEST_FILENAME, spdk_env_get_current_core()) >= filename_size) { 4354ed98d54SEvgeniy Kochetov SPDK_ERRLOG("File name size doesn't fit into buffer\n"); 4364ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, ENOMEM); 4374ed98d54SEvgeniy Kochetov return; 4384ed98d54SEvgeniy Kochetov } 4394ed98d54SEvgeniy Kochetov 4404ed98d54SEvgeniy Kochetov hello_thread->fsdev_io_channel = spdk_fsdev_get_io_channel(hello_thread->hello_context->fsdev_desc); 4414ed98d54SEvgeniy Kochetov if (!hello_thread->fsdev_io_channel) { 4424ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Could not create fsdev I/O channel!\n"); 4434ed98d54SEvgeniy Kochetov hello_thread_done(hello_thread, ENOMEM); 4444ed98d54SEvgeniy Kochetov return; 4454ed98d54SEvgeniy Kochetov } 4464ed98d54SEvgeniy Kochetov 4474ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Started thread %s on core %u\n", 4484ed98d54SEvgeniy Kochetov spdk_thread_get_name(hello_thread->thread), 4494ed98d54SEvgeniy Kochetov spdk_env_get_current_core()); 4504ed98d54SEvgeniy Kochetov spdk_thread_send_msg(hello_thread->thread, hello_mknod, hello_thread); 4514ed98d54SEvgeniy Kochetov } 4524ed98d54SEvgeniy Kochetov 4534ed98d54SEvgeniy Kochetov static void 4544ed98d54SEvgeniy Kochetov hello_create_threads(struct hello_context_t *hello_context) 4554ed98d54SEvgeniy Kochetov { 4564ed98d54SEvgeniy Kochetov uint32_t cpu; 4574ed98d54SEvgeniy Kochetov char thread_name[32]; 4584ed98d54SEvgeniy Kochetov struct spdk_cpuset mask = {}; 4594ed98d54SEvgeniy Kochetov struct spdk_thread *thread; 4604ed98d54SEvgeniy Kochetov 4614ed98d54SEvgeniy Kochetov SPDK_ENV_FOREACH_CORE(cpu) { 4624ed98d54SEvgeniy Kochetov snprintf(thread_name, sizeof(thread_name), "hello_fsdev_%u", cpu); 4634ed98d54SEvgeniy Kochetov spdk_cpuset_zero(&mask); 4644ed98d54SEvgeniy Kochetov spdk_cpuset_set_cpu(&mask, cpu, true); 4654ed98d54SEvgeniy Kochetov thread = spdk_thread_create(thread_name, &mask); 4664ed98d54SEvgeniy Kochetov assert(thread != NULL); 4674ed98d54SEvgeniy Kochetov hello_context->thread_count++; 4684ed98d54SEvgeniy Kochetov spdk_thread_send_msg(thread, hello_start_thread, hello_context); 4694ed98d54SEvgeniy Kochetov } 4704ed98d54SEvgeniy Kochetov } 4714ed98d54SEvgeniy Kochetov 4724ed98d54SEvgeniy Kochetov 4734ed98d54SEvgeniy Kochetov static void 4744ed98d54SEvgeniy Kochetov root_lookup_complete(void *cb_arg, struct spdk_io_channel *ch, int status, 4754ed98d54SEvgeniy Kochetov struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 4764ed98d54SEvgeniy Kochetov { 4774ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = cb_arg; 4784ed98d54SEvgeniy Kochetov 4794ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Root lookup complete (status=%d)\n", status); 4804ed98d54SEvgeniy Kochetov if (status) { 4814ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Fuse init failed: error %d\n", status); 4824ed98d54SEvgeniy Kochetov hello_app_done(hello_context, status); 4834ed98d54SEvgeniy Kochetov return; 4844ed98d54SEvgeniy Kochetov } 4854ed98d54SEvgeniy Kochetov 4864ed98d54SEvgeniy Kochetov hello_context->root_fobject = fobject; 4874ed98d54SEvgeniy Kochetov 4884ed98d54SEvgeniy Kochetov hello_create_threads(hello_context); 4894ed98d54SEvgeniy Kochetov } 4904ed98d54SEvgeniy Kochetov 4914ed98d54SEvgeniy Kochetov static void 4924ed98d54SEvgeniy Kochetov root_lookup(struct hello_context_t *hello_context) 4934ed98d54SEvgeniy Kochetov { 4944ed98d54SEvgeniy Kochetov int res; 4954ed98d54SEvgeniy Kochetov 4964ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Lookup for the root\n"); 4974ed98d54SEvgeniy Kochetov 4984ed98d54SEvgeniy Kochetov res = spdk_fsdev_lookup(hello_context->fsdev_desc, hello_context->fsdev_io_channel, 0, 4994ed98d54SEvgeniy Kochetov NULL /* root */, "" /* will be ignored */, root_lookup_complete, hello_context); 5004ed98d54SEvgeniy Kochetov if (res) { 5014ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Failed to initiate lookup for the root (err=%d)\n", res); 5024ed98d54SEvgeniy Kochetov hello_app_done(hello_context, res); 5034ed98d54SEvgeniy Kochetov return; 5044ed98d54SEvgeniy Kochetov } 5054ed98d54SEvgeniy Kochetov } 5064ed98d54SEvgeniy Kochetov 5074ed98d54SEvgeniy Kochetov static void 5084ed98d54SEvgeniy Kochetov hello_fsdev_event_cb(enum spdk_fsdev_event_type type, struct spdk_fsdev *fsdev, void *event_ctx) 5094ed98d54SEvgeniy Kochetov { 5104ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Unsupported fsdev event: type %d\n", type); 5114ed98d54SEvgeniy Kochetov } 5124ed98d54SEvgeniy Kochetov 5134ed98d54SEvgeniy Kochetov /* 5144ed98d54SEvgeniy Kochetov * Our initial event that kicks off everything from main(). 5154ed98d54SEvgeniy Kochetov */ 5164ed98d54SEvgeniy Kochetov static void 5174ed98d54SEvgeniy Kochetov hello_start(void *arg1) 5184ed98d54SEvgeniy Kochetov { 5194ed98d54SEvgeniy Kochetov struct hello_context_t *hello_context = arg1; 5204ed98d54SEvgeniy Kochetov int rc = 0; 5214ed98d54SEvgeniy Kochetov hello_context->fsdev_desc = NULL; 5224ed98d54SEvgeniy Kochetov 5234ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Successfully started the application\n"); 5244ed98d54SEvgeniy Kochetov 5254ed98d54SEvgeniy Kochetov hello_context->app_thread = spdk_get_thread(); 5264ed98d54SEvgeniy Kochetov 5274ed98d54SEvgeniy Kochetov /* 5284ed98d54SEvgeniy Kochetov * There can be many fsdevs configured, but this application will only use 5294ed98d54SEvgeniy Kochetov * the one input by the user at runtime. 5304ed98d54SEvgeniy Kochetov * 5314ed98d54SEvgeniy Kochetov * Open the fs by calling spdk_fsdev_open() with its name. 5324ed98d54SEvgeniy Kochetov * The function will return a descriptor 5334ed98d54SEvgeniy Kochetov */ 5344ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Opening the fsdev %s\n", hello_context->fsdev_name); 5354ed98d54SEvgeniy Kochetov rc = spdk_fsdev_open(hello_context->fsdev_name, 536*6cb9c75cSAnton Nayshtut hello_fsdev_event_cb, NULL, 5374ed98d54SEvgeniy Kochetov &hello_context->fsdev_desc); 5384ed98d54SEvgeniy Kochetov if (rc) { 5394ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Could not open fsdev: %s\n", hello_context->fsdev_name); 5404ed98d54SEvgeniy Kochetov spdk_app_stop(-1); 5414ed98d54SEvgeniy Kochetov return; 5424ed98d54SEvgeniy Kochetov } 5434ed98d54SEvgeniy Kochetov 5444ed98d54SEvgeniy Kochetov SPDK_NOTICELOG("Opening io channel\n"); 5454ed98d54SEvgeniy Kochetov /* Open I/O channel */ 5464ed98d54SEvgeniy Kochetov hello_context->fsdev_io_channel = spdk_fsdev_get_io_channel(hello_context->fsdev_desc); 5474ed98d54SEvgeniy Kochetov if (!hello_context->fsdev_io_channel) { 5484ed98d54SEvgeniy Kochetov SPDK_ERRLOG("Could not create fsdev I/O channel!\n"); 5494ed98d54SEvgeniy Kochetov spdk_fsdev_close(hello_context->fsdev_desc); 5504ed98d54SEvgeniy Kochetov spdk_app_stop(-1); 5514ed98d54SEvgeniy Kochetov return; 5524ed98d54SEvgeniy Kochetov } 5534ed98d54SEvgeniy Kochetov 5544ed98d54SEvgeniy Kochetov root_lookup(hello_context); 5554ed98d54SEvgeniy Kochetov } 5564ed98d54SEvgeniy Kochetov 5574ed98d54SEvgeniy Kochetov int 5584ed98d54SEvgeniy Kochetov main(int argc, char **argv) 5594ed98d54SEvgeniy Kochetov { 5604ed98d54SEvgeniy Kochetov struct spdk_app_opts opts = {}; 5614ed98d54SEvgeniy Kochetov int rc = 0; 5624ed98d54SEvgeniy Kochetov struct hello_context_t hello_context = {}; 5634ed98d54SEvgeniy Kochetov 5644ed98d54SEvgeniy Kochetov /* Set default values in opts structure. */ 5654ed98d54SEvgeniy Kochetov spdk_app_opts_init(&opts, sizeof(opts)); 5664ed98d54SEvgeniy Kochetov opts.name = "hello_fsdev"; 5674ed98d54SEvgeniy Kochetov 5684ed98d54SEvgeniy Kochetov /* 5694ed98d54SEvgeniy Kochetov * Parse built-in SPDK command line parameters as well 5704ed98d54SEvgeniy Kochetov * as our custom one(s). 5714ed98d54SEvgeniy Kochetov */ 5724ed98d54SEvgeniy Kochetov if ((rc = spdk_app_parse_args(argc, argv, &opts, "f:", NULL, hello_fsdev_parse_arg, 5734ed98d54SEvgeniy Kochetov hello_fsdev_usage)) != SPDK_APP_PARSE_ARGS_SUCCESS) { 5744ed98d54SEvgeniy Kochetov exit(rc); 5754ed98d54SEvgeniy Kochetov } 5764ed98d54SEvgeniy Kochetov hello_context.fsdev_name = g_fsdev_name; 5774ed98d54SEvgeniy Kochetov 5784ed98d54SEvgeniy Kochetov /* 5794ed98d54SEvgeniy Kochetov * spdk_app_start() will initialize the SPDK framework, call hello_start(), 5804ed98d54SEvgeniy Kochetov * and then block until spdk_app_stop() is called (or if an initialization 5814ed98d54SEvgeniy Kochetov * error occurs, spdk_app_start() will return with rc even without calling 5824ed98d54SEvgeniy Kochetov * hello_start(). 5834ed98d54SEvgeniy Kochetov */ 5844ed98d54SEvgeniy Kochetov rc = spdk_app_start(&opts, hello_start, &hello_context); 5854ed98d54SEvgeniy Kochetov if (rc) { 5864ed98d54SEvgeniy Kochetov SPDK_ERRLOG("ERROR starting application\n"); 5874ed98d54SEvgeniy Kochetov } 5884ed98d54SEvgeniy Kochetov 5894ed98d54SEvgeniy Kochetov /* At this point either spdk_app_stop() was called, or spdk_app_start() 5904ed98d54SEvgeniy Kochetov * failed because of internal error. 5914ed98d54SEvgeniy Kochetov */ 5924ed98d54SEvgeniy Kochetov 5934ed98d54SEvgeniy Kochetov /* Gracefully close out all of the SPDK subsystems. */ 5944ed98d54SEvgeniy Kochetov spdk_app_fini(); 5954ed98d54SEvgeniy Kochetov return rc; 5964ed98d54SEvgeniy Kochetov } 597