From f0710b6c37214457ab46bd1859f00ec413b01a7f Mon Sep 17 00:00:00 2001 From: sunshihao Date: Thu, 18 Feb 2021 10:52:24 +0800 Subject: [PATCH 17/27] add HSAK needed head file and API to spdk Signed-off-by: sunshihao --- CONFIG | 3 + Makefile | 6 + configure | 8 ++ etc/spdk/nvme.conf.in | 88 ++++++++++++ include/spdk/bdev.h | 85 +++++++++++ include/spdk/bdev_module.h | 89 ++++++++++++ include/spdk/log.h | 2 +- include/spdk/nvme.h | 230 ++++++++++++++++++++++++++++++ include/spdk/thread.h | 18 +++ include/spdk_internal/bdev_stat.h | 63 ++++++++ include/spdk_internal/debug.h | 43 ++++++ include/spdk_internal/thread.h | 2 + mk/spdk.app_vars.mk | 4 +- 13 files changed, 639 insertions(+), 2 deletions(-) create mode 100644 etc/spdk/nvme.conf.in create mode 100644 include/spdk_internal/bdev_stat.h create mode 100644 include/spdk_internal/debug.h diff --git a/CONFIG b/CONFIG index b5fffae..214e59e 100644 --- a/CONFIG +++ b/CONFIG @@ -43,6 +43,9 @@ CONFIG_CROSS_PREFIX= # Build with debug logging. Turn off for performance testing and normal usage CONFIG_DEBUG=n +# Enable read and write NVMe for application +CONFIG_APP_RW=n + # Treat warnings as errors (fail the build on any warning). CONFIG_WERROR=n diff --git a/Makefile b/Makefile index a50fa94..1c98268 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,12 @@ S := SPDK_ROOT_DIR := $(CURDIR) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk +ifeq ($(CONFIG_APP_RW),y) +# secure compile option +CFLAGS += -fPIE -pie -fPIC -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2 -Wall -Werror +CFLAGS += -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines +endif + DIRS-y += lib DIRS-y += module DIRS-$(CONFIG_SHARED) += shared_lib diff --git a/configure b/configure index 5b48696..964322e 100644 --- a/configure +++ b/configure @@ -25,6 +25,8 @@ function usage() echo " example: aarch64-linux-gnu" echo "" echo " --enable-debug Configure for debug builds" + echo " --enable-err-injc Enable error injection feature" + echo " --enable-raw Enable read and write NVMe disk feature." echo " --enable-werror Treat compiler warnings as errors" echo " --enable-asan Enable address sanitizer" echo " --enable-ubsan Enable undefined behavior sanitizer" @@ -204,6 +206,12 @@ for i in "$@"; do --disable-debug) CONFIG[DEBUG]=n ;; + --enable-raw) + CONFIG[APP_RW]=y + ;; + --enable-err-injc) + CONFIG[ERR_INJC]=y + ;; --enable-asan) CONFIG[ASAN]=y ;; diff --git a/etc/spdk/nvme.conf.in b/etc/spdk/nvme.conf.in new file mode 100644 index 0000000..a3df92b --- /dev/null +++ b/etc/spdk/nvme.conf.in @@ -0,0 +1,88 @@ +#NVME configuration file +# +# Please write all parameters using ASCII. +# The parameter must be quoted if it includes whitespace. +# +# Configuration syntax: +# Leading whitespace is ignored. +# Lines starting with '#' are comments. +# Lines ending with '\' are concatenated with the next line. +# Bracketed ([]) names define sections + +[Global] + # Users can restrict work items to only run on certain cores by specifying a ReactorMask. + # Can not specify the NO. 0 core. + ReactorMask 0x2 + + # The print level of log. + # 0: Print ERROR log only; 1: Print WARNING and ERROR log; and so on, 4: Print all level log + LogLevel 1 + + # The sizes of Memory for Libstorge(Unit: MB). The minimum value is 300MB. + # If parameter "SocketMem" was set corrected, MemSize was useless + MemSize 300 + + # The same block device supports multiple queues. + MultiQ No + + # End-to-end data protection. This item is only used if the namespace is formatted to use end-to-end protection information. + # if the value is set to '1', then the protection information are generated by controller, and the logical block data and protection information are written to NVM. + # if the value is set to '2', then the protection information are transferred from the host buffer to NVM. + E2eDif 2 + + # Open IOstat or not + IoStat No + + # Poll time threshold in millisecond, It will count exceptional polling thread call which duration exceed the value and display in stat report. + # This item is only used when UseReactor = No, Set to 0 means disable this measurement. + PollTime 0 + + # Preallocate specified amounts of memory(Unit: MB) per socket. + # The parameter is a comma-sprated list of values, For example: + # SocketMem 1024,2048 + # This will allocate 1 gigabyte of memory on socket 0, and 2048 megabytes of memory on socket 1. + # The sum of socket memory must be greater than 300MB. + # if SocketMem was set corrected, The parameter "MemSize" was useless + # SocketMem 300 + + # Place a per-socket upper limit on memory use (non-legacy memory mode only). + # 0 will disable the limit for a particular socket. + # SocketLimit 1024,1 + # This will set upper limit of 1 gigabyte on socket 0, and 1 megabytes of memory on socket 1. + # if the value is set to empty, means disable the limit per socket. + # if SocketMem was empty, the parameter was useless. + # SocketLimit 300 + + #Decide whether to start rpc server or not + RpcServer Yes + +# NVMe configuration options +[Nvme] + # NVMe Device Whitelist + # Users may specify which NVMe devices to claim by their transport id. + # See spdk_nvme_transport_id_parse() in spdk/nvme.h for the correct format. + # The second argument is the assigned name, which can be referenced from + # other sections in the configuration file. For NVMe devices, a namespace + # is automatically appended to each name in the format nY, where + # Y is the NSID (starts at 1). + #TransportID "trtype:PCIe traddr:0000:81:00.0" nvme0 + #TransportID "trtype:PCIe traddr:0000:01:00.0" nvme1 + + # The number of attempts per I/O when an I/O fails. Do not include + # this key to get the default behavior. + RetryCount 4 + # Timeout for each command, in microseconds. If 0, don't track timeouts. + TimeoutUsec 0 + # Action to take on command time out. Only valid when Timeout is greater + # than 0. This may be 'Reset' to reset the controller, 'Abort' to abort + # the command, or 'None' to just print a message but do nothing. + # Admin command timeouts will always result in a reset. + ActionOnTimeout None + # Set how often the admin queue is polled for asynchronous events. + # Units in microseconds. + AdminPollRate 100000 + +[Reactor] + # Batch size of IO for one-time release by reactor. + # The maximum value is 32. + BatchSize 8 diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index d894646..2951660 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -53,6 +53,8 @@ extern "C" { #define SPDK_BDEV_SMALL_BUF_MAX_SIZE 8192 #define SPDK_BDEV_LARGE_BUF_MAX_SIZE (64 * 1024) +#define SPDK_BDEV_SMALL_BUF_WITH_MAX_MD 512 +#define SPDK_BDEV_LARGE_BUF_WITH_MAX_MD 1024 /* Increase the buffer size to store interleaved metadata. Increment is the * amount necessary to store metadata per data block. 16 byte metadata per @@ -116,6 +118,42 @@ enum spdk_bdev_status { SPDK_BDEV_STATUS_REMOVING, }; +#ifdef SPDK_CONFIG_APP_RW +/** ns status */ +enum spdk_bdev_ns_status { + SPDK_BDEV_NS_STATUS_INVALID, + SPDK_BDEV_NS_STATUS_READY, + SPDK_BDEV_NS_STATUS_REMOVING, + SPDK_BDEV_NS_STATUS_UNREGISTER, +}; + +typedef void (*LIBSTORAGE_CALLBACK_FUNC)(int32_t cb_status, int32_t sct_code, void *cb_arg); + +typedef struct libstorage_io { + uint8_t *buf; + struct iovec *iovs; /* array of iovecs to transfer */ + int iovcnt; /* Number of iovecs in iovs array */ + int32_t fd; /* File Descriptor */ + uint16_t opcode; /* r/w */ + uint16_t streamId; /* Stream ID for IO */ + uint8_t pi_action; + uint8_t fua; + uint8_t location; + bool inSubmit; /* In the I/0 phase or not. Use in nopoll model */ + uint32_t count; + uint32_t nbytes; + uint64_t offset; + uint8_t *md_buf; + uint32_t md_len; + uint32_t magic; + /*Save the error code returned by the callback */ + int32_t err; + int32_t reserved; + LIBSTORAGE_CALLBACK_FUNC cb; + void *cb_arg; +} LIBSTORAGE_IO_T; +#endif + /** * \brief Handle to an opened SPDK block device. */ @@ -140,6 +178,13 @@ enum spdk_bdev_io_type { SPDK_BDEV_IO_TYPE_COMPARE, SPDK_BDEV_IO_TYPE_COMPARE_AND_WRITE, SPDK_BDEV_IO_TYPE_ABORT, +#ifdef SPDK_CONFIG_APP_RW + SPDK_BDEV_IO_TYPE_READ_NVME, + SPDK_BDEV_IO_TYPE_WRITE_NVME, + SPDK_BDEV_IO_TYPE_READV_NVME, + SPDK_BDEV_IO_TYPE_WRITEV_NVME, + SPDK_BDEV_IO_TYPE_UNMAP_BLOCKS, +#endif SPDK_BDEV_NUM_IO_TYPES /* Keep last */ }; @@ -181,6 +226,14 @@ struct spdk_bdev_io_stat { uint64_t write_latency_ticks; uint64_t unmap_latency_ticks; uint64_t ticks_rate; +#ifdef SPDK_CONFIG_APP_RW + int io_stat_id; + uint64_t io_ticks; + uint64_t pre_ticks; + uint64_t cur_ticks; + uint64_t start_tsc; + uint64_t interval_tsc; +#endif }; struct spdk_bdev_opts { @@ -1342,6 +1395,38 @@ int spdk_bdev_unmap(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, uint64_t offset, uint64_t nbytes, spdk_bdev_io_completion_cb cb, void *cb_arg); +#ifdef SPDK_CONFIG_APP_RW +/** + * Submit an unmap request to the block device. Unmap is sometimes also called trim or + * deallocate. This notifies the device that the data in the blocks described is no + * longer valid. Reading blocks that have been unmapped results in indeterminate data. + * + * \param bdev Block device description + * \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel(). + * \param unmap_d An array of unmap descriptors. + * \param bdesc_count The number of elements in unmap_d. + * \param cb Called when the request is complete. + * \param cb_arg Argument passed to cb. + * + * \return 0 on success. On success, the callback will always + * be called (even if the request ultimately failed). Return + * negated errno on failure, in which case the callback will not be called. + */ +int +spdk_bdev_unmap_multiblocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + void *unmap_d, uint16_t unmap_count, + spdk_bdev_io_completion_cb cb, void *cb_arg); + +void* +spdk_bdev_get_channel_group(struct spdk_io_channel *io_ch); + +void* +spdk_bdev_io_get_pool(size_t nbytes); + +bool +spdk_bdev_have_io_in_channel(struct spdk_io_channel *bdevIoCh); +#endif + /** * Submit an unmap request to the block device. Unmap is sometimes also called trim or * deallocate. This notifies the device that the data in the blocks described is no diff --git a/include/spdk/bdev_module.h b/include/spdk/bdev_module.h index bbb9f94..c2fd81d 100644 --- a/include/spdk/bdev_module.h +++ b/include/spdk/bdev_module.h @@ -222,8 +222,67 @@ struct spdk_bdev_fn_table { /** Get bdev module context. */ void *(*get_module_ctx)(void *ctx); + +#ifdef SPDK_CONFIG_APP_RW + uint16_t (*get_io_channel_id)(struct spdk_io_channel *ch); + + int (*bdev_poll_rsp)(void *pollCh); + + uint64_t (*get_timeout_count)(struct spdk_io_channel *ch); +#endif +}; + +#ifdef SPDK_CONFIG_APP_RW +static inline void spdk_bdev_set_io_location(void *bdev_ctx, uint8_t location) +{ + struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(bdev_ctx); + uint8_t *ioLoc = (uint8_t *)bdev_io->internal.caller_ctx; + *ioLoc = location; +} + +enum spdk_bdev_driver_ctx { + SPDK_BDEV_IO_ACTION_PI, + SPDK_BDEV_IO_ACTION_FUA, + SPDK_BDEV_IO_STREAM_ID_0, + SPDK_BDEV_IO_STREAM_ID_1, +}; + +enum spdk_bdev_io_e2e_pi_action{ + IO_NO_PROTECTION = 0, + IO_HALF_WAY_PROTECTION = 1, + IO_E2E_PROTECTION = 2 }; +#define FLAG_NO_REF 0x10//bit 4 : 1, disable ctrl ref tag check; 0, enable check +#define FLAG_CALCRC 0x08//bit 3 : 1, libstorage calculate crc; 0, app calculate crc +#define FLAG_PRCHK 0x04//bit 2 : 1, enable ctrl guard crc check; 0, disable check + +enum spdk_bdev_io_fua{ + IO_FUA_NO = 0, + IO_FUA_YES = 1 +}; + +void spdk_bdev_nvme_remove_cb(void *cb_ctx, void *ctrlr); + +void spdk_bdev_fail_ctrlr(const char* traddr); + +void *nvme_channel_get_group(void *io_ch); + +enum reqLocation_E +{ + LOCAL_RECEIVE_APP = 1, + LOCAL_LIBSTORAGE_SUBMIT = 2, + LOCAL_LIBSTORAGE_ASYNC_REQ = 3, + LOCAL_LIBSTORAGE_BDEV_NVME = 4, + LOCAL_LIBSTORAGE_HUNG_REQ = 5, + LOCAL_LIBSTORAGE_TO_DISK = 6, + LOCAL_LIBSTORAGE_FROM_DISK = 7, + LOCAL_LIBSTORAGE_CALLBACK = 8, + LOCAL_LIBSTORAGE_SUBMIT_RETRY = 9, + LOCAL_LIBSTORAGE_BDEV_NOMEM = 10, +}; +#endif + /** bdev I/O completion status */ enum spdk_bdev_io_status { SPDK_BDEV_IO_STATUS_AIO_ERROR = -8, @@ -407,6 +466,10 @@ struct spdk_bdev { /** The bdev status */ enum spdk_bdev_status status; +#ifdef SPDK_CONFIG_APP_RW + enum spdk_bdev_ns_status ns_status; +#endif + /** * Pointer to the module that has claimed this bdev for purposes of creating virtual * bdevs on top of it. Set to NULL if the bdev has not been claimed. @@ -528,6 +591,11 @@ struct spdk_bdev_io { /** Starting offset (in blocks) of the bdev for this I/O. */ uint64_t offset_blocks; +#ifdef SPDK_CONFIG_APP_RW + /* The number of bytes to transfer */ + size_t nbytes; +#endif + /** stored user callback in case we split the I/O and use a temporary callback */ spdk_bdev_io_completion_cb stored_user_cb; @@ -595,6 +663,27 @@ struct spdk_bdev_io { /* The data buffer */ void *buf; } zone_mgmt; +#ifdef SPDK_CONFIG_APP_RW + struct { + /* The data buffer to transfer */ + void *buf; + + /* The meta data buffer to transfer */ + void *md_buf; + + /** Total size of data(in blocks) to be transferred. */ + uint64_t num_blocks; + + /* The number of bytes to transfer */ + size_t nbytes; + + /** Starting offset (in blocks) of the bdev for this I/O. */ + size_t offset_blocks; + + /* meta data buffer size to transfer */ + size_t md_len; + } contig; +#endif } u; /** It may be used by modules to put the bdev_io into its own list. */ diff --git a/include/spdk/log.h b/include/spdk/log.h index ad850ab..e16035c 100644 --- a/include/spdk/log.h +++ b/include/spdk/log.h @@ -173,7 +173,7 @@ enum spdk_log_level spdk_log_get_print_level(void); * \param format Format string to the message. */ void spdk_log(enum spdk_log_level level, const char *file, const int line, const char *func, - const char *format, ...) __attribute__((__format__(__printf__, 5, 6))); + const char *format, ...) __attribute__((weak)) __attribute__((__format__(__printf__, 5, 6))); /** * Same as spdk_log except that instead of being called with variable number of diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index 45b9f94..8e05139 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -2465,6 +2465,7 @@ enum spdk_nvme_ns_flags { part of the logical block that it is associated with */ SPDK_NVME_NS_WRITE_UNCORRECTABLE_SUPPORTED = 0x40, /**< The write uncorrectable command is supported */ SPDK_NVME_NS_COMPARE_SUPPORTED = 0x80, /**< The compare command is supported */ + SPDK_NVME_NS_DPS_PI_MDSTART = 0x100 /**< protection info transferred at start of metadata */ }; /** @@ -3434,6 +3435,235 @@ struct spdk_nvme_transport_ops { */ void spdk_nvme_transport_register(const struct spdk_nvme_transport_ops *ops); +#ifdef SPDK_CONFIG_APP_RW +struct nvme_ctrlr_info { + char ctrlName[16]; + char pciAddr[24]; + uint64_t tnvmcap; /* Total NVM Capacity in bytes */ + uint64_t unvmcap; /* Unallocated NVM Capacity in bytes */ + int8_t sn[20]; /* Serial number */ + int8_t mn[40]; /* Model number */ + uint8_t fr[8]; /* Firmware revision */ + uint32_t max_num_ns; /* Number of namespaces */ + uint32_t version; /* Version of the NVM Express specification that the controller implementation supports */ + uint16_t num_io_queues; /* num of io queues */ + uint16_t io_queue_size; /* io queue size */ + uint16_t device_id; /* Device id */ + uint16_t subdevice_id; /* Subsystem device id */ + uint16_t vid; /* Vendor id */ + uint16_t ssvid; /* Subsystem vendor id */ + uint16_t ctrlid; /* Controller id */ + uint16_t trtype; /* Transport type */ + uint16_t support_ns :1; /* Supports the Namespace Management and Namespace Attachment commands */ + uint16_t directives :1; /* Supports Directives */ + uint16_t streams :1; /* Supports Streams Directives */ + uint16_t dsm :1; /* Supports the controller supports the Dataset Management command */ + uint16_t reserved :12; + uint16_t reserved2[3]; +}; + +struct nvme_ctrlr; +struct nvme_bdev_ctrlr; +struct spdk_bdev; +struct nvme_bdev; +struct spdk_nvme_ns; +struct spdk_nvme_qpair; +int32_t nvme_ctrlr_get_info(const char* ctrlName, struct nvme_ctrlr_info** ppCtrlr); +struct spdk_nvme_ctrlr* spdk_nvme_ctrlr_get_by_name(const char* ctrlname); +struct spdk_nvme_ctrlr* spdk_nvme_ctrlr_get_by_ctrlr(const struct nvme_bdev_ctrlr *nvme_bdev_ctrlr); +struct nvme_bdev_ctrlr* nvme_ctrlr_get_by_name(const char* ctrlname); +void nvme_ctrlr_clear_iostat_by_name(const char* ctrlname); +void nvme_ctrlr_clear_iostat_all(void); +struct nvme_bdev_ctrlr* bdev_nvme_get_ctrlr_by_bdev_desc(void *bdev); +struct spdk_nvme_ns* bdev_nvme_get_ns(struct nvme_bdev *nbdev); +void bdev_nvme_update_block_by_nvme_ctrlr(struct spdk_nvme_ctrlr *ctrlr); +int bdev_nvme_update_ns(struct nvme_bdev_ctrlr *nvme_ctrlr, uint32_t nsid); +bool spdk_bdev_can_remove(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr, uint32_t nsid); +void spdk_bdev_set_ns_normal(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr, uint32_t nsid); +void spdk_nvme_ctrlr_set_shutdown(struct spdk_nvme_ctrlr *ctrlr, bool is_shutdown); +bool spdk_nvme_ctrlr_is_smart_per_namespace_supported(struct spdk_nvme_ctrlr *ctrlr); +int spdk_nvme_ctrlr_get_smart_info(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, struct spdk_nvme_health_information_page *health_payload); +int spdk_nvme_ctrlr_get_error_info(struct spdk_nvme_ctrlr *ctrlr, uint32_t err_entries, struct spdk_nvme_error_information_entry *error_info); +struct spdk_nvme_ctrlr_opts* spdk_nvme_ctrlr_get_opts(struct spdk_nvme_ctrlr *ctrlr); +int nvme_ns_get_common_data(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns_data *nsdata); +bool spdk_nvme_ns_is_allocated(struct spdk_nvme_ctrlr *ctrlr, uint16_t nsid); +bool spdk_nvme_ctrlr_is_ns_manage_supported(struct spdk_nvme_ctrlr *ctrlr); +bool spdk_nvme_ctrlr_is_format_supported(struct spdk_nvme_ctrlr *ctrlr); +bool spdk_nvme_ctrlr_is_format_all_ns(struct spdk_nvme_ctrlr *ctrlr); +bool spdk_nvme_ctrlr_is_directive_supported(struct spdk_nvme_ctrlr *ctrlr); +bool spdk_nvme_ctrlr_is_streams_supported(struct spdk_nvme_ctrlr *ctrlr); +int32_t spdk_nvme_ctrlr_identify_directives(struct spdk_nvme_ctrlr *ctrlr, uint16_t nsid, void *payload); +int32_t spdk_nvme_ctrlr_enable_streams(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid); +int32_t spdk_nvme_ctrlr_ret_streams_param(struct spdk_nvme_ctrlr *ctrlr, void *payload); +int32_t spdk_nvme_ns_ret_streams_param(struct spdk_nvme_ns *ns, void *payload); +int32_t spdk_nvme_ns_get_streams_status(struct spdk_nvme_ns *ns, void *payload); +int32_t spdk_nvme_ns_alloc_streams_res(struct spdk_nvme_ns *ns, uint16_t nsr); +int32_t spdk_nvme_ns_release_streams_id(struct spdk_nvme_ns *ns, uint16_t streamsId); +int32_t spdk_nvme_ns_release_streams_res(struct spdk_nvme_ns *ns); +void spdk_nvme_use_streams(bool use); + +/** + * \brief Get the ctrlr is_failed state, for an I/O sent to the given namespace. + * + * This function is thread safe and can be called at any point while the controller is attached to + * the SPDK NVMe driver. + */ +bool spdk_nvme_ns_ctrl_is_failed(struct spdk_nvme_ns *ns); +#define NVME_MAX_CONTROLLERS 1024 + +/* check nvme whether exist by access cc register */ +bool nvme_ctrlr_is_exist(struct spdk_nvme_ctrlr *ctrlr); + +/* create ctrlr for new added device */ +int spdk_bdev_nvme_create_self(struct spdk_nvme_transport_id *trid, const char *base_name, + const char **names, size_t *count, const char *hostnqn); + +int spdk_nvme_detach_ublock(struct spdk_nvme_ctrlr *ctrlr); +void spdk_nvme_ctrlr_update_unvmcap(struct spdk_nvme_ctrlr *ctrlr); + +#define SPDK_NVME_UEVENT_SUBSYSTEM_UIO 1 +#define SPDK_NVME_UEVENT_SUBSYSTEM_NVME 2 + +enum spdk_nvme_uevent_action { + SPDK_NVME_UEVENT_ADD = 0, + SPDK_NVME_UEVENT_REMOVE = 1, +}; + +struct spdk_uevent { + /* remove or add */ + enum spdk_nvme_uevent_action action; + int subsystem; + /* pci address of device */ + char traddr[SPDK_NVMF_TRADDR_MAX_LEN + 1]; +}; + +/* make a socket to get uevent */ +int nvme_uevent_connect(void); + +/* get uevent from socket fd */ +int nvme_get_uevent(int fd, struct spdk_uevent *uevent); + +/* blocked to get uevent from socket fd */ +int nvme_get_uevent_block(int fd, struct spdk_uevent *uevent); + +/** + * @Description: bind device with pci_addr to driver + * @param pci_addr: device's pci_addr,like "0000:08:00.0" + * @param driver: driver name which device bind to + */ +int32_t spdk_rebind_driver(char *pci_addr, char *driver_name); + +/** + * \brief True if the protection information transferred at the start of metadata + * when end-to-end data protection enabled. + * + * This function is thread safe and can be called at any point while the controller is attached to + * the SPDK NVMe driver. + */ +bool spdk_nvme_ns_pi_md_start(struct spdk_nvme_ns *ns); + +/** + * \brief True if the namespace supports Dataset Management command. + * + * This function is thread safe and can be called at any point while the controller is attached to + * the SPDK NVMe driver. + */ +bool spdk_nvme_ns_is_dataset_mng_supported(struct spdk_nvme_ns *ns); + +/** + * Submit a data set management request to the specified NVMe namespace. Data set + * management operations are designed to optimize interaction with the block + * translation layer inside the device. The most common type of operation is + * deallocate, which is often referred to as TRIM or UNMAP. + * + * The command is submitted to a qpair allocated by spdk_nvme_ctrlr_alloc_io_qpair(). + * The user must ensure that only one thread submits I/O on a given qpair at any + * given time. + * + * This is a convenience wrapper that will automatically allocate and construct + * the correct data buffers. Therefore, ranges does not need to be allocated from + * pinned memory and can be placed on the stack. If a higher performance, zero-copy + * version of DSM is required, simply build and submit a raw command using + * spdk_nvme_ctrlr_cmd_io_raw(). + * + * \param ns NVMe namespace to submit the DSM request + * \param type A bit field constructed from \ref spdk_nvme_dsm_attribute. + * \param qpair I/O queue pair to submit the request + * \param ranges An array of \ref spdk_nvme_dsm_range elements describing the LBAs + * to operate on. + * \param num_ranges The number of elements in the ranges array. + * \param cb_fn Callback function to invoke when the I/O is completed + * \param cb_arg Argument to pass to the callback function + * + * \return 0 if successfully submitted, negated POSIX errno values otherwise. + */ +int spdk_nvme_ns_cmd_unmap_blocks(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint32_t type, + const struct spdk_nvme_dsm_range *ranges, + uint16_t num_ranges, + spdk_nvme_cmd_cb cb_fn, + void *cb_arg); +/** + * \brief Submits a write I/O to the specified NVMe namespace. + * + * \param ns NVMe namespace to submit the write I/O + * \param qpair I/O queue pair to submit the request + * \param lba starting LBA to write the data + * \param lba_count length (in sectors) for the write operation + * \param streamId The stream id for write I/O + * \param cb_fn callback function to invoke when the I/O is completed + * \param cb_arg argument to pass to the callback function + * \param io_flags set flags, defined in nvme_spec.h, for this I/O + * \param reset_sgl_fn callback function to reset scattered payload + * \param next_sge_fn callback function to iterate each scattered + * payload memory segment + * + * \return 0 if successfully submitted, ENOMEM if an nvme_request + * structure cannot be allocated for the I/O request + * + * The command is submitted to a qpair allocated by spdk_nvme_ctrlr_alloc_io_qpair(). + * The user must ensure that only one thread submits I/O on a given qpair at any given time. + */ +int spdk_nvme_ns_cmd_writev_stream(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t lba, uint32_t lba_count, uint16_t streamId, + spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags, + spdk_nvme_req_reset_sgl_cb reset_sgl_fn, + spdk_nvme_req_next_sge_cb next_sge_fn); + +/** + * \brief Send comman to NVMe controller to start or abort a self-test operation. + * + * \param ctrlr NVMe controller to operate self-test command. + * \param nsid Depending on the log page, this may be 0, a namespace identifier, or SPDK_NVME_GLOBAL_NS_TAG. + * \param stc self-test code, which specifies the action taken by the Device Self-test command. + * \param payload The pointer to the payload buffer. it doesn't work actually. + * \param payload_size The size of payload buffer. it doesn't work actually. + * \param cb_fn Callback function to invoke when the feature has been retrieved. + * \param cb_arg Argument to pass to the callback function. + * + * \return 0 if successfully submitted, ENOMEM if resources could not be allocated for this request + * + * This function is thread safe and can be called at any point while the controller is attached to + * the SPDK NVMe driver. + * + * Call \ref spdk_nvme_ctrlr_process_admin_completions() to poll for completion + * of commands submitted through this function. + * + * \sa spdk_nvme_ctrlr_cmd_self_test_operation() + */ +int spdk_nvme_ctrlr_cmd_self_test_operation(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, uint32_t stc, + void *payload, uint32_t payload_size, + spdk_nvme_cmd_cb cb_fn, void *cb_arg); + +/** + *\get I/O queue pair id + *\param qpair I/O queue pair to submit the request + *\ + *\return I/O queue pair id + */ +uint16_t spdk_nvme_get_qpair_id(struct spdk_nvme_qpair *qpair); +#endif + /* * Macro used to register new transports. */ diff --git a/include/spdk/thread.h b/include/spdk/thread.h index 4b7e650..7c52433 100644 --- a/include/spdk/thread.h +++ b/include/spdk/thread.h @@ -42,6 +42,9 @@ #include "spdk/cpuset.h" #include "spdk/queue.h" +#ifdef SPDK_CONFIG_APP_RW +#include "rte_config.h" +#endif #ifdef __cplusplus extern "C" { @@ -57,6 +60,21 @@ enum spdk_thread_poller_rc { */ struct spdk_thread; +#ifdef SPDK_CONFIG_APP_RW +struct spdk_iodev_thread_info { + struct spdk_thread *thread; + volatile int32_t state; + uint32_t bdevnum; +}; +extern struct spdk_iodev_thread_info lcore_thread_info[RTE_MAX_LCORE]; + +void spdk_reactors_use(bool useOrNot); + +bool spdk_get_reactor_type(void); + +void spdk_set_thread_exited(struct spdk_thread *thread); +#endif + /** * A function repeatedly called on the same spdk_thread. */ diff --git a/include/spdk_internal/bdev_stat.h b/include/spdk_internal/bdev_stat.h new file mode 100644 index 0000000..f1ba1df --- /dev/null +++ b/include/spdk_internal/bdev_stat.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. +*/ + +#ifndef LIBSTORAGE_STAT_H +#define LIBSTORAGE_STAT_H + +#include +#include +#include +#include + +//share memory file name +#define LIBSTORAGE_STAT_SHM_FILE_NAME "libstorage_stat.shm.\ +49ce4ec241e017c65812b71b9832a50865f0b7d9b4d5f18d3d03283b" + +//max number of channel+bdev +#define STAT_MAX_NUM 8192 + +extern int32_t g_libstorage_iostat; +extern int32_t g_polltime_threshold; + +extern pthread_mutex_t *g_io_stat_map_mutex; + +/* libstorage iostat status */ +enum libstorage_iostat_status { + LIBSTORAGE_IOSTAT_DISABLE = 0, + LIBSTORAGE_IOSTAT_ENABLE = 1, + LIBSTORAGE_IOSTAT_QUERY = 2, +}; + +struct libstorage_bdev_io_stat +{ + bool used; + uint16_t channel_id; + char bdev_name[24]; + uint64_t num_read_ops; + uint64_t num_write_ops; + uint64_t bytes_read; + uint64_t bytes_written; + uint64_t io_outstanding; + uint64_t read_latency_ticks; + uint64_t write_latency_ticks; + uint64_t io_ticks; + bool poll_time_used; + uint64_t num_poll_timeout; +}; + +extern struct libstorage_bdev_io_stat *g_io_stat_map; + +int libstorage_stat_init(void); + +int libstorage_stat_exit(void); +#endif diff --git a/include/spdk_internal/debug.h b/include/spdk_internal/debug.h new file mode 100644 index 0000000..5d6e623 --- /dev/null +++ b/include/spdk_internal/debug.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. +*/ + +#ifndef LIBSTORAGE_INTERNAL_DEBUG_H +#define LIBSTORAGE_INTERNAL_DEBUG_H +#include "spdk/stdinc.h" + +struct spdk_debug_subsystem +{ + const char *name; + void (*output)(FILE *file); + TAILQ_ENTRY(spdk_debug_subsystem) tailq; +}; + +void spdk_add_debug_subsystem(struct spdk_debug_subsystem *subsystem); + +/** + * \brief Register a new subsystem + */ +#define SPDK_DEBUG_REGISTER(_name, _output) \ + struct spdk_debug_subsystem __spdk_debug_subsystem_ ## _name = \ + { \ + .name = #_name, \ + .output = _output, \ + }; \ + __attribute__((constructor)) static void _name ## _debug_register(void) \ + { \ + spdk_add_debug_subsystem(&__spdk_debug_subsystem_ ## _name); \ + } + +void spdk_output_debug_info(void); + +#endif diff --git a/include/spdk_internal/thread.h b/include/spdk_internal/thread.h index 5bab452..7d1811b 100644 --- a/include/spdk_internal/thread.h +++ b/include/spdk_internal/thread.h @@ -80,6 +80,8 @@ struct spdk_poller { }; enum spdk_thread_state { + SPDK_THREAD_STATE_INITIALIZED, + /* The thread is pocessing poller and message by spdk_thread_poll(). */ SPDK_THREAD_STATE_RUNNING, diff --git a/mk/spdk.app_vars.mk b/mk/spdk.app_vars.mk index 059a56e..ff8fad5 100644 --- a/mk/spdk.app_vars.mk +++ b/mk/spdk.app_vars.mk @@ -57,8 +57,10 @@ SPDK_LIB_LINKER_ARGS = \ -L$(SPDK_ROOT_DIR)/build/lib \ -Wl,--whole-archive \ -Wl,--no-as-needed \ + -Wl,-Bstatic \ $(SPDK_DEPLIB_LIST:%=-lspdk_%) \ - -Wl,--no-whole-archive + -Wl,--no-whole-archive \ + -Wl,-Bdynamic # This is primarily used for unit tests to ensure they link when shared library # build is enabled. Shared libraries can't get their mock implementation from -- 2.33.0