From f0710b6c37214457ab46bd1859f00ec413b01a7f Mon Sep 17 00:00:00 2001
From: sunshihao <sunshihao@huawei.com>
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 <sunshihao@huawei.com>
---
 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 <YourName>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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+//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

