#define SPDK_NVMF_MAX_SGL_ENTRIES 16
+/* AIO backend requires block size aligned data buffers,
+ * extra 4KiB aligned data buffer should work for most devices.
+ */
+#define SHIFT_4KB 12u
+#define NVMF_DATA_BUFFER_ALIGNMENT (1u << SHIFT_4KB)
+#define NVMF_DATA_BUFFER_MASK (NVMF_DATA_BUFFER_ALIGNMENT - 1LL)
+
enum spdk_nvmf_subsystem_state {
SPDK_NVMF_SUBSYSTEM_INACTIVE = 0,
SPDK_NVMF_SUBSYSTEM_ACTIVATING,
enum spdk_nvmf_qpair_state {
SPDK_NVMF_QPAIR_UNINITIALIZED = 0,
- SPDK_NVMF_QPAIR_INACTIVE,
- SPDK_NVMF_QPAIR_ACTIVATING,
SPDK_NVMF_QPAIR_ACTIVE,
SPDK_NVMF_QPAIR_DEACTIVATING,
SPDK_NVMF_QPAIR_ERROR,
typedef void (*spdk_nvmf_state_change_done)(void *cb_arg, int status);
struct spdk_nvmf_tgt {
- struct spdk_nvmf_tgt_opts opts;
-
uint64_t discovery_genctr;
+ uint32_t max_subsystems;
+
/* Array of subsystem pointers of size max_subsystems indexed by sid */
struct spdk_nvmf_subsystem **subsystems;
TAILQ_ENTRY(spdk_nvmf_listener) link;
};
+struct spdk_nvmf_transport_pg_cache_buf {
+ STAILQ_ENTRY(spdk_nvmf_transport_pg_cache_buf) link;
+};
+
struct spdk_nvmf_transport_poll_group {
- struct spdk_nvmf_transport *transport;
- TAILQ_ENTRY(spdk_nvmf_transport_poll_group) link;
+ struct spdk_nvmf_transport *transport;
+ STAILQ_HEAD(, spdk_nvmf_transport_pg_cache_buf) buf_cache;
+ uint32_t buf_cache_count;
+ uint32_t buf_cache_size;
+ TAILQ_ENTRY(spdk_nvmf_transport_poll_group) link;
+};
+
+/* Maximum number of registrants supported per namespace */
+#define SPDK_NVMF_MAX_NUM_REGISTRANTS 16
+
+struct spdk_nvmf_subsystem_pg_ns_info {
+ struct spdk_io_channel *channel;
+ /* current reservation key, no reservation if the value is 0 */
+ uint64_t crkey;
+ /* reservation type */
+ enum spdk_nvme_reservation_type rtype;
+ /* Host ID which holds the reservation */
+ struct spdk_uuid holder_id;
+ /* Host ID for the registrants with the namespace */
+ struct spdk_uuid reg_hostid[SPDK_NVMF_MAX_NUM_REGISTRANTS];
};
+typedef void(*spdk_nvmf_poll_group_mod_done)(void *cb_arg, int status);
+
struct spdk_nvmf_subsystem_poll_group {
- /* Array of channels for each namespace indexed by nsid - 1 */
- struct spdk_io_channel **channels;
- uint32_t num_channels;
+ /* Array of namespace information for each namespace indexed by nsid - 1 */
+ struct spdk_nvmf_subsystem_pg_ns_info *ns_info;
+ uint32_t num_ns;
- enum spdk_nvmf_subsystem_state state;
+ uint64_t io_outstanding;
+ spdk_nvmf_poll_group_mod_done cb_fn;
+ void *cb_arg;
- TAILQ_HEAD(, spdk_nvmf_request) queued;
+ enum spdk_nvmf_subsystem_state state;
+
+ TAILQ_HEAD(, spdk_nvmf_request) queued;
};
struct spdk_nvmf_poll_group {
void *data;
union nvmf_h2c_msg *cmd;
union nvmf_c2h_msg *rsp;
- struct iovec iov[SPDK_NVMF_MAX_SGL_ENTRIES];
+ struct iovec iov[SPDK_NVMF_MAX_SGL_ENTRIES * 2];
uint32_t iovcnt;
struct spdk_bdev_io_wait_entry bdev_io_wait;
TAILQ_ENTRY(spdk_nvmf_request) link;
};
+struct spdk_nvmf_registrant {
+ TAILQ_ENTRY(spdk_nvmf_registrant) link;
+ struct spdk_uuid hostid;
+ /* Registration key */
+ uint64_t rkey;
+};
+
struct spdk_nvmf_ns {
+ uint32_t nsid;
struct spdk_nvmf_subsystem *subsystem;
struct spdk_bdev *bdev;
struct spdk_bdev_desc *desc;
struct spdk_nvmf_ns_opts opts;
+ /* reservation notificaton mask */
+ uint32_t mask;
+ /* generation code */
+ uint32_t gen;
+ /* registrants head */
+ TAILQ_HEAD(, spdk_nvmf_registrant) registrants;
+ /* current reservation key */
+ uint64_t crkey;
+ /* reservation type */
+ enum spdk_nvme_reservation_type rtype;
+ /* current reservation holder, only valid if reservation type can only have one holder */
+ struct spdk_nvmf_registrant *holder;
+ /* Persist Through Power Loss file which contains the persistent reservation */
+ char *ptpl_file;
};
struct spdk_nvmf_qpair {
union spdk_nvme_feat_keep_alive_timer keep_alive_timer;
};
+/*
+ * NVMf reservation notificaton log page.
+ */
+struct spdk_nvmf_reservation_log {
+ struct spdk_nvme_reservation_notification_log log;
+ TAILQ_ENTRY(spdk_nvmf_reservation_log) link;
+ struct spdk_nvmf_ctrlr *ctrlr;
+};
+
/*
* This structure represents an NVMe-oF controller,
* which is like a "session" in networking terms.
struct spdk_nvmf_request *aer_req;
union spdk_nvme_async_event_completion notice_event;
- uint8_t hostid[16];
+ union spdk_nvme_async_event_completion reservation_event;
+ struct spdk_uuid hostid;
uint16_t changed_ns_list_count;
struct spdk_nvme_ns_list changed_ns_list;
+ uint64_t log_page_count;
+ uint8_t num_avail_log_pages;
+ TAILQ_HEAD(log_page_head, spdk_nvmf_reservation_log) log_head;
+
+ /* Time to trigger keep-alive--poller_time = now_tick + period */
+ uint64_t last_keep_alive_tick;
+ struct spdk_poller *keep_alive_poller;
TAILQ_ENTRY(spdk_nvmf_ctrlr) link;
};
struct spdk_nvmf_tgt *tgt;
char sn[SPDK_NVME_CTRLR_SN_LEN + 1];
+ char mn[SPDK_NVME_CTRLR_MN_LEN + 1];
/* Array of pointers to namespaces of size max_nsid indexed by nsid - 1 */
struct spdk_nvmf_ns **ns;
TAILQ_ENTRY(spdk_nvmf_subsystem) entries;
};
-typedef void(*spdk_nvmf_poll_group_mod_done)(void *cb_arg, int status);
struct spdk_nvmf_transport *spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt,
enum spdk_nvme_transport_type);
int spdk_nvmf_request_free(struct spdk_nvmf_request *req);
int spdk_nvmf_request_complete(struct spdk_nvmf_request *req);
-void spdk_nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt,
- void *buffer, uint64_t offset,
- uint32_t length);
+void spdk_nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt, struct iovec *iov,
+ uint32_t iovcnt, uint64_t offset, uint32_t length);
void spdk_nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr);
int spdk_nvmf_ctrlr_process_fabrics_cmd(struct spdk_nvmf_request *req);
void spdk_nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid);
void spdk_nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata);
+int spdk_nvmf_bdev_ctrlr_read_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
+ struct spdk_io_channel *ch, struct spdk_nvmf_request *req);
+int spdk_nvmf_bdev_ctrlr_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
+ struct spdk_io_channel *ch, struct spdk_nvmf_request *req);
+int spdk_nvmf_bdev_ctrlr_write_zeroes_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
+ struct spdk_io_channel *ch, struct spdk_nvmf_request *req);
+int spdk_nvmf_bdev_ctrlr_flush_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
+ struct spdk_io_channel *ch, struct spdk_nvmf_request *req);
+int spdk_nvmf_bdev_ctrlr_dsm_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
+ struct spdk_io_channel *ch, struct spdk_nvmf_request *req);
+int spdk_nvmf_bdev_ctrlr_nvme_passthru_io(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
+ struct spdk_io_channel *ch, struct spdk_nvmf_request *req);
int spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem,
struct spdk_nvmf_ctrlr *ctrlr);
struct spdk_nvmf_ctrlr *spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem,
uint16_t cntlid);
int spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr);
+void spdk_nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr);
+void spdk_nvmf_ns_reservation_request(void *ctx);
+void spdk_nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
+ struct spdk_nvmf_ns *ns,
+ enum spdk_nvme_reservation_notification_log_page_type type);
/*
* Abort aer is sent on a per controller basis and sends a completion for the aer to the host.