numam/storage/drivers/nvme_thread.cc
2022-03-29 00:47:46 +08:00

90 lines
2.6 KiB
C++

#include <sys/endian.h>
#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<struct cb_context *>(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<void*>(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<void*>(ctx), 0);
}
void
birb_nvme_thread_context::poll()
{
spdk_nvme_qpair_process_completions(this->qpair, 0);
}