#include #include "storage/drivers/nvme.hh" #include "ntr.h" #include "spdk/bdev.h" #include "spdk/nvme.h" #include "spdk/nvme_spec.h" #include "spdk/thread.h" birb_nvme_thread_context::birb_nvme_thread_context(birb_nvme_driver * driver) : status(birb_driver::BIRB_FAIL), driver(driver), qpair(nullptr) { struct spdk_nvme_ctrlr * ctrlr = driver->get_ctrlr(); struct spdk_nvme_qpair * qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, driver->get_io_qpair_opts(), sizeof(struct spdk_nvme_io_qpair_opts)); if (qpair == nullptr) { ntr(NTR_DEP_USER1, NTR_LEVEL_ERROR, "birb_nvme_thread_context: could not allocate qpairs.\n"); } else { this->qpair = qpair; status = birb_driver::BIRB_SUCCESS; } } birb_driver::birb_driver_status birb_nvme_thread_context::get_status() { return this->status; } birb_nvme_thread_context::~birb_nvme_thread_context() { if (this->qpair != nullptr) { spdk_nvme_ctrlr_free_io_qpair(this->qpair); } } /* * Callback function for io completion. */ void birb_nvme_thread_context::io_callback(void *arg, const struct spdk_nvme_cpl *completion) { bool success = !spdk_nvme_cpl_is_error(completion); auto ctx = reinterpret_cast(arg); ctx->cb(success, ctx->ctx); delete ctx; } uint32_t birb_nvme_thread_context::size_to_lba(size_t size, int lba_size) { return (size - 1) / lba_size + 1; } uint64_t birb_nvme_thread_context::addr_to_lba(size_t addr, int lba_size) { return addr / lba_size; } int birb_nvme_thread_context::read(size_t offset, size_t size, char * buffer, callback callback, void * context) { auto ctx = new struct cb_context; ctx->cb = callback; ctx->ctx = context; struct spdk_nvme_ns * ns = this->driver->get_ns(); int lba_size = spdk_nvme_ns_get_sector_size(ns); return spdk_nvme_ns_cmd_read(ns, this->qpair, buffer, addr_to_lba(offset, lba_size), size_to_lba(size, lba_size), io_callback, reinterpret_cast(ctx), 0); } int birb_nvme_thread_context::write(size_t offset, size_t size, char * buffer, callback callback, void * context) { auto ctx = new struct cb_context; ctx->cb = callback; ctx->ctx = context; struct spdk_nvme_ns * ns = this->driver->get_ns(); int lba_size = spdk_nvme_ns_get_sector_size(ns); return spdk_nvme_ns_cmd_write(ns, this->qpair, buffer, addr_to_lba(offset, lba_size), size_to_lba(size, lba_size), io_callback, reinterpret_cast(ctx), 0); } void birb_nvme_thread_context::poll() { spdk_nvme_qpair_process_completions(this->qpair, 0); }