nvme: Add metadata support to io commands
Adding metadata support for io commands. Currently metadata is ignored even if present in the cmd struct. Making metadata adress readable/writable depending on data transfer bits. Adding extra unit test to make sure metadata fields are populated. Signed-off-by: Ahriben Gonzalez <ahribeng@gmail.com> Change-Id: I1d01974a6b2831c82b43e94073065d235eea429a Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10854 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
parent
9e14341bd9
commit
0345729e00
@ -70,9 +70,14 @@ struct cuse_io_ctx {
|
||||
|
||||
uint64_t lba;
|
||||
uint32_t lba_count;
|
||||
uint16_t apptag;
|
||||
uint16_t appmask;
|
||||
|
||||
void *data;
|
||||
void *metadata;
|
||||
|
||||
int data_len;
|
||||
int metadata_len;
|
||||
|
||||
fuse_req_t req;
|
||||
};
|
||||
@ -81,6 +86,7 @@ static void
|
||||
cuse_io_ctx_free(struct cuse_io_ctx *ctx)
|
||||
{
|
||||
spdk_free(ctx->data);
|
||||
spdk_free(ctx->metadata);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
@ -97,7 +103,7 @@ static void
|
||||
cuse_nvme_passthru_cmd_cb(void *arg, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct cuse_io_ctx *ctx = arg;
|
||||
struct iovec out_iov[2];
|
||||
struct iovec out_iov[3];
|
||||
struct spdk_nvme_cpl _cpl;
|
||||
int out_iovcnt = 0;
|
||||
uint16_t status_field = cpl->status_raw >> 1; /* Drop out phase bit */
|
||||
@ -107,10 +113,17 @@ cuse_nvme_passthru_cmd_cb(void *arg, const struct spdk_nvme_cpl *cpl)
|
||||
out_iov[out_iovcnt].iov_len = sizeof(_cpl.cdw0);
|
||||
out_iovcnt += 1;
|
||||
|
||||
if (ctx->data_transfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST && ctx->data_len > 0) {
|
||||
out_iov[out_iovcnt].iov_base = ctx->data;
|
||||
out_iov[out_iovcnt].iov_len = ctx->data_len;
|
||||
out_iovcnt += 1;
|
||||
if (ctx->data_transfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST) {
|
||||
if (ctx->data_len > 0) {
|
||||
out_iov[out_iovcnt].iov_base = ctx->data;
|
||||
out_iov[out_iovcnt].iov_len = ctx->data_len;
|
||||
out_iovcnt += 1;
|
||||
}
|
||||
if (ctx->metadata_len > 0) {
|
||||
out_iov[out_iovcnt].iov_base = ctx->metadata;
|
||||
out_iov[out_iovcnt].iov_len = ctx->metadata_len;
|
||||
out_iovcnt += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fuse_reply_ioctl_iov(ctx->req, status_field, out_iov, out_iovcnt);
|
||||
@ -124,8 +137,9 @@ cuse_nvme_passthru_cmd_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, voi
|
||||
struct cuse_io_ctx *ctx = arg;
|
||||
|
||||
if (nsid != 0) {
|
||||
rc = spdk_nvme_ctrlr_cmd_io_raw(ctrlr, ctrlr->external_io_msgs_qpair, &ctx->nvme_cmd, ctx->data,
|
||||
ctx->data_len, cuse_nvme_passthru_cmd_cb, (void *)ctx);
|
||||
rc = spdk_nvme_ctrlr_cmd_io_raw_with_md(ctrlr, ctrlr->external_io_msgs_qpair, &ctx->nvme_cmd,
|
||||
ctx->data,
|
||||
ctx->data_len, ctx->metadata, cuse_nvme_passthru_cmd_cb, (void *)ctx);
|
||||
} else {
|
||||
rc = spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, &ctx->nvme_cmd, ctx->data, ctx->data_len,
|
||||
cuse_nvme_passthru_cmd_cb, (void *)ctx);
|
||||
@ -138,7 +152,7 @@ cuse_nvme_passthru_cmd_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, voi
|
||||
|
||||
static void
|
||||
cuse_nvme_passthru_cmd_send(fuse_req_t req, struct nvme_passthru_cmd *passthru_cmd,
|
||||
const void *data, int cmd)
|
||||
const void *data, const void *metadata, int cmd)
|
||||
{
|
||||
struct cuse_io_ctx *ctx;
|
||||
struct cuse_device *cuse_device = fuse_req_userdata(req);
|
||||
@ -165,6 +179,7 @@ cuse_nvme_passthru_cmd_send(fuse_req_t req, struct nvme_passthru_cmd *passthru_c
|
||||
ctx->nvme_cmd.cdw15 = passthru_cmd->cdw15;
|
||||
|
||||
ctx->data_len = passthru_cmd->data_len;
|
||||
ctx->metadata_len = passthru_cmd->metadata_len;
|
||||
|
||||
if (ctx->data_len > 0) {
|
||||
ctx->data = spdk_malloc(ctx->data_len, 4096, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
|
||||
@ -179,6 +194,19 @@ cuse_nvme_passthru_cmd_send(fuse_req_t req, struct nvme_passthru_cmd *passthru_c
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->metadata_len > 0) {
|
||||
ctx->metadata = spdk_malloc(ctx->metadata_len, 4096, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
|
||||
if (!ctx->metadata) {
|
||||
SPDK_ERRLOG("Cannot allocate memory for metadata\n");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
cuse_io_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
if (metadata != NULL) {
|
||||
memcpy(ctx->metadata, metadata, ctx->metadata_len);
|
||||
}
|
||||
}
|
||||
|
||||
if ((unsigned int)cmd != NVME_IOCTL_ADMIN_CMD) {
|
||||
/* Send NS for IO IOCTLs */
|
||||
rv = nvme_io_msg_send(cuse_device->ctrlr, passthru_cmd->nsid, cuse_nvme_passthru_cmd_execute, ctx);
|
||||
@ -200,9 +228,9 @@ cuse_nvme_passthru_cmd(fuse_req_t req, int cmd, void *arg,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
||||
{
|
||||
struct nvme_passthru_cmd *passthru_cmd;
|
||||
struct iovec in_iov[2], out_iov[2];
|
||||
struct iovec in_iov[3], out_iov[3];
|
||||
int in_iovcnt = 0, out_iovcnt = 0;
|
||||
const void *dptr = NULL;
|
||||
const void *dptr = NULL, *mdptr = NULL;
|
||||
enum spdk_nvme_data_transfer data_transfer;
|
||||
|
||||
in_iov[in_iovcnt].iov_base = (void *)arg;
|
||||
@ -223,19 +251,32 @@ cuse_nvme_passthru_cmd(fuse_req_t req, int cmd, void *arg,
|
||||
in_iov[in_iovcnt].iov_len = passthru_cmd->data_len;
|
||||
in_iovcnt += 1;
|
||||
}
|
||||
/* Make metadata pointer accessible (RO) */
|
||||
if (passthru_cmd->metadata != 0) {
|
||||
in_iov[in_iovcnt].iov_base = (void *)passthru_cmd->metadata;
|
||||
in_iov[in_iovcnt].iov_len = passthru_cmd->metadata_len;
|
||||
in_iovcnt += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Always make result field writable regardless of data transfer bits */
|
||||
/* Always make result field writeable regardless of data transfer bits */
|
||||
out_iov[out_iovcnt].iov_base = &((struct nvme_passthru_cmd *)arg)->result;
|
||||
out_iov[out_iovcnt].iov_len = sizeof(uint32_t);
|
||||
out_iovcnt += 1;
|
||||
|
||||
if (data_transfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST) {
|
||||
/* Make data pointer accessible (WO) */
|
||||
if (passthru_cmd->data_len > 0) {
|
||||
out_iov[out_iovcnt].iov_base = (void *)passthru_cmd->addr;
|
||||
out_iov[out_iovcnt].iov_len = passthru_cmd->data_len;
|
||||
out_iovcnt += 1;
|
||||
}
|
||||
/* Make metadata pointer accessible (WO) */
|
||||
if (passthru_cmd->metadata_len > 0) {
|
||||
out_iov[out_iovcnt].iov_base = (void *)passthru_cmd->metadata;
|
||||
out_iov[out_iovcnt].iov_len = passthru_cmd->metadata_len;
|
||||
out_iovcnt += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_bufsz == 0) {
|
||||
@ -250,9 +291,11 @@ cuse_nvme_passthru_cmd(fuse_req_t req, int cmd, void *arg,
|
||||
|
||||
if (data_transfer == SPDK_NVME_DATA_HOST_TO_CONTROLLER) {
|
||||
dptr = (passthru_cmd->addr == 0) ? NULL : in_buf + sizeof(*passthru_cmd);
|
||||
mdptr = (passthru_cmd->metadata == 0) ? NULL : in_buf + sizeof(*passthru_cmd) +
|
||||
passthru_cmd->data_len;
|
||||
}
|
||||
|
||||
cuse_nvme_passthru_cmd_send(req, passthru_cmd, dptr, cmd);
|
||||
cuse_nvme_passthru_cmd_send(req, passthru_cmd, dptr, mdptr, cmd);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -365,10 +408,11 @@ cuse_nvme_submit_io_write_cb(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void
|
||||
struct cuse_io_ctx *ctx = arg;
|
||||
struct spdk_nvme_ns *ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);
|
||||
|
||||
rc = spdk_nvme_ns_cmd_write(ns, ctrlr->external_io_msgs_qpair, ctx->data,
|
||||
ctx->lba, /* LBA start */
|
||||
ctx->lba_count, /* number of LBAs */
|
||||
cuse_nvme_submit_io_write_done, ctx, 0);
|
||||
rc = spdk_nvme_ns_cmd_write_with_md(ns, ctrlr->external_io_msgs_qpair, ctx->data, ctx->metadata,
|
||||
ctx->lba, /* LBA start */
|
||||
ctx->lba_count, /* number of LBAs */
|
||||
cuse_nvme_submit_io_write_done, ctx, 0,
|
||||
ctx->appmask, ctx->apptag);
|
||||
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("write failed: rc = %d\n", rc);
|
||||
@ -380,7 +424,7 @@ cuse_nvme_submit_io_write_cb(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void
|
||||
|
||||
static void
|
||||
cuse_nvme_submit_io_write(struct cuse_device *cuse_device, fuse_req_t req, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned flags, uint32_t block_size,
|
||||
struct fuse_file_info *fi, unsigned flags, uint32_t block_size, uint32_t md_size,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
||||
{
|
||||
const struct nvme_user_io *user_io = in_buf;
|
||||
@ -410,6 +454,25 @@ cuse_nvme_submit_io_write(struct cuse_device *cuse_device, fuse_req_t req, int c
|
||||
|
||||
memcpy(ctx->data, in_buf + sizeof(*user_io), ctx->data_len);
|
||||
|
||||
if (user_io->metadata) {
|
||||
ctx->apptag = user_io->apptag;
|
||||
ctx->appmask = user_io->appmask;
|
||||
ctx->metadata_len = md_size * ctx->lba_count;
|
||||
ctx->metadata = spdk_zmalloc(ctx->metadata_len, 4096, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
|
||||
|
||||
if (ctx->metadata == NULL) {
|
||||
SPDK_ERRLOG("Cannot allocate memory for metadata\n");
|
||||
if (ctx->metadata_len == 0) {
|
||||
SPDK_ERRLOG("Device format does not support metadata\n");
|
||||
}
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
cuse_io_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(ctx->metadata, in_buf + sizeof(*user_io) + ctx->data_len, ctx->metadata_len);
|
||||
}
|
||||
|
||||
rc = nvme_io_msg_send(cuse_device->ctrlr, cuse_device->nsid, cuse_nvme_submit_io_write_cb,
|
||||
ctx);
|
||||
if (rc < 0) {
|
||||
@ -423,13 +486,21 @@ static void
|
||||
cuse_nvme_submit_io_read_done(void *ref, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct cuse_io_ctx *ctx = (struct cuse_io_ctx *)ref;
|
||||
struct iovec iov;
|
||||
struct iovec iov[2];
|
||||
int iovcnt = 0;
|
||||
uint16_t status_field = cpl->status_raw >> 1; /* Drop out phase bit */
|
||||
|
||||
iov.iov_base = ctx->data;
|
||||
iov.iov_len = ctx->data_len;
|
||||
iov[iovcnt].iov_base = ctx->data;
|
||||
iov[iovcnt].iov_len = ctx->data_len;
|
||||
iovcnt += 1;
|
||||
|
||||
fuse_reply_ioctl_iov(ctx->req, status_field, &iov, 1);
|
||||
if (ctx->metadata) {
|
||||
iov[iovcnt].iov_base = ctx->metadata;
|
||||
iov[iovcnt].iov_len = ctx->metadata_len;
|
||||
iovcnt += 1;
|
||||
}
|
||||
|
||||
fuse_reply_ioctl_iov(ctx->req, status_field, iov, iovcnt);
|
||||
|
||||
cuse_io_ctx_free(ctx);
|
||||
}
|
||||
@ -441,10 +512,11 @@ cuse_nvme_submit_io_read_cb(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *
|
||||
struct cuse_io_ctx *ctx = arg;
|
||||
struct spdk_nvme_ns *ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);
|
||||
|
||||
rc = spdk_nvme_ns_cmd_read(ns, ctrlr->external_io_msgs_qpair, ctx->data,
|
||||
ctx->lba, /* LBA start */
|
||||
ctx->lba_count, /* number of LBAs */
|
||||
cuse_nvme_submit_io_read_done, ctx, 0);
|
||||
rc = spdk_nvme_ns_cmd_read_with_md(ns, ctrlr->external_io_msgs_qpair, ctx->data, ctx->metadata,
|
||||
ctx->lba, /* LBA start */
|
||||
ctx->lba_count, /* number of LBAs */
|
||||
cuse_nvme_submit_io_read_done, ctx, 0,
|
||||
ctx->appmask, ctx->apptag);
|
||||
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("read failed: rc = %d\n", rc);
|
||||
@ -456,7 +528,7 @@ cuse_nvme_submit_io_read_cb(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *
|
||||
|
||||
static void
|
||||
cuse_nvme_submit_io_read(struct cuse_device *cuse_device, fuse_req_t req, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned flags, uint32_t block_size,
|
||||
struct fuse_file_info *fi, unsigned flags, uint32_t block_size, uint32_t md_size,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
||||
{
|
||||
int rc;
|
||||
@ -484,6 +556,23 @@ cuse_nvme_submit_io_read(struct cuse_device *cuse_device, fuse_req_t req, int cm
|
||||
return;
|
||||
}
|
||||
|
||||
if (user_io->metadata) {
|
||||
ctx->apptag = user_io->apptag;
|
||||
ctx->appmask = user_io->appmask;
|
||||
ctx->metadata_len = md_size * ctx->lba_count;
|
||||
ctx->metadata = spdk_zmalloc(ctx->metadata_len, 4096, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
|
||||
|
||||
if (ctx->metadata == NULL) {
|
||||
SPDK_ERRLOG("Cannot allocate memory for metadata\n");
|
||||
if (ctx->metadata_len == 0) {
|
||||
SPDK_ERRLOG("Device format does not support metadata\n");
|
||||
}
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
cuse_io_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rc = nvme_io_msg_send(cuse_device->ctrlr, cuse_device->nsid, cuse_nvme_submit_io_read_cb, ctx);
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("Cannot send read io\n");
|
||||
@ -499,15 +588,18 @@ cuse_nvme_submit_io(fuse_req_t req, int cmd, void *arg,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
||||
{
|
||||
const struct nvme_user_io *user_io;
|
||||
struct iovec in_iov[2], out_iov;
|
||||
struct iovec in_iov[3], out_iov[2];
|
||||
int in_iovcnt = 0, out_iovcnt = 0;
|
||||
struct cuse_device *cuse_device = fuse_req_userdata(req);
|
||||
struct spdk_nvme_ns *ns;
|
||||
uint32_t block_size;
|
||||
uint32_t md_size;
|
||||
|
||||
in_iov[0].iov_base = (void *)arg;
|
||||
in_iov[0].iov_len = sizeof(*user_io);
|
||||
in_iov[in_iovcnt].iov_base = (void *)arg;
|
||||
in_iov[in_iovcnt].iov_len = sizeof(*user_io);
|
||||
in_iovcnt += 1;
|
||||
if (in_bufsz == 0) {
|
||||
fuse_reply_ioctl_retry(req, in_iov, 1, NULL, 0);
|
||||
fuse_reply_ioctl_retry(req, in_iov, in_iovcnt, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -515,29 +607,42 @@ cuse_nvme_submit_io(fuse_req_t req, int cmd, void *arg,
|
||||
|
||||
ns = spdk_nvme_ctrlr_get_ns(cuse_device->ctrlr, cuse_device->nsid);
|
||||
block_size = spdk_nvme_ns_get_sector_size(ns);
|
||||
md_size = spdk_nvme_ns_get_md_size(ns);
|
||||
|
||||
switch (user_io->opcode) {
|
||||
case SPDK_NVME_OPC_READ:
|
||||
out_iov.iov_base = (void *)user_io->addr;
|
||||
out_iov.iov_len = (user_io->nblocks + 1) * block_size;
|
||||
out_iov[out_iovcnt].iov_base = (void *)user_io->addr;
|
||||
out_iov[out_iovcnt].iov_len = (user_io->nblocks + 1) * block_size;
|
||||
out_iovcnt += 1;
|
||||
if (user_io->metadata != 0) {
|
||||
out_iov[out_iovcnt].iov_base = (void *)user_io->metadata;
|
||||
out_iov[out_iovcnt].iov_len = (user_io->nblocks + 1) * md_size;
|
||||
out_iovcnt += 1;
|
||||
}
|
||||
if (out_bufsz == 0) {
|
||||
fuse_reply_ioctl_retry(req, in_iov, 1, &out_iov, 1);
|
||||
fuse_reply_ioctl_retry(req, in_iov, in_iovcnt, out_iov, out_iovcnt);
|
||||
return;
|
||||
}
|
||||
|
||||
cuse_nvme_submit_io_read(cuse_device, req, cmd, arg, fi, flags,
|
||||
block_size, in_buf, in_bufsz, out_bufsz);
|
||||
block_size, md_size, in_buf, in_bufsz, out_bufsz);
|
||||
break;
|
||||
case SPDK_NVME_OPC_WRITE:
|
||||
in_iov[1].iov_base = (void *)user_io->addr;
|
||||
in_iov[1].iov_len = (user_io->nblocks + 1) * block_size;
|
||||
in_iov[in_iovcnt].iov_base = (void *)user_io->addr;
|
||||
in_iov[in_iovcnt].iov_len = (user_io->nblocks + 1) * block_size;
|
||||
in_iovcnt += 1;
|
||||
if (user_io->metadata != 0) {
|
||||
in_iov[in_iovcnt].iov_base = (void *)user_io->metadata;
|
||||
in_iov[in_iovcnt].iov_len = (user_io->nblocks + 1) * md_size;
|
||||
in_iovcnt += 1;
|
||||
}
|
||||
if (in_bufsz == sizeof(*user_io)) {
|
||||
fuse_reply_ioctl_retry(req, in_iov, 2, NULL, 0);
|
||||
fuse_reply_ioctl_retry(req, in_iov, in_iovcnt, NULL, out_iovcnt);
|
||||
return;
|
||||
}
|
||||
|
||||
cuse_nvme_submit_io_write(cuse_device, req, cmd, arg, fi, flags,
|
||||
block_size, in_buf, in_bufsz, out_bufsz);
|
||||
block_size, md_size, in_buf, in_bufsz, out_bufsz);
|
||||
break;
|
||||
default:
|
||||
SPDK_ERRLOG("SUBMIT_IO: opc:%d not valid\n", user_io->opcode);
|
||||
|
@ -47,8 +47,8 @@ DEFINE_STUB(spdk_nvme_ctrlr_cmd_admin_raw, int, (struct spdk_nvme_ctrlr *ctrlr,
|
||||
struct spdk_nvme_cmd *cmd, void *buf, uint32_t len,
|
||||
spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_cmd_io_raw, int, (struct spdk_nvme_ctrlr *ctrlr,
|
||||
struct spdk_nvme_qpair *qpair, struct spdk_nvme_cmd *cmd, void *buf, uint32_t len,
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_cmd_io_raw_with_md, int, (struct spdk_nvme_ctrlr *ctrlr,
|
||||
struct spdk_nvme_qpair *qpair, struct spdk_nvme_cmd *cmd, void *buf, uint32_t len, void *md_buf,
|
||||
spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_get_num_ns, uint32_t, (struct spdk_nvme_ctrlr *ctrlr), 128);
|
||||
@ -84,20 +84,24 @@ DEFINE_STUB(spdk_nvme_ctrlr_reset, int, (struct spdk_nvme_ctrlr *ctrlr), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_reset_subsystem, int, (struct spdk_nvme_ctrlr *ctrlr), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_cmd_read, int, (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
|
||||
void *payload,
|
||||
DEFINE_STUB(spdk_nvme_ns_cmd_read_with_md, int, (struct spdk_nvme_ns *ns,
|
||||
struct spdk_nvme_qpair *qpair,
|
||||
void *payload, void *metadata,
|
||||
uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
|
||||
uint32_t io_flags), 0);
|
||||
uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_cmd_write, int, (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
|
||||
void *payload,
|
||||
DEFINE_STUB(spdk_nvme_ns_cmd_write_with_md, int, (struct spdk_nvme_ns *ns,
|
||||
struct spdk_nvme_qpair *qpair,
|
||||
void *payload, void *metadata,
|
||||
uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
|
||||
uint32_t io_flags), 0);
|
||||
uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_get_num_sectors, uint64_t, (struct spdk_nvme_ns *ns), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_get_sector_size, uint32_t, (struct spdk_nvme_ns *ns), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_get_md_size, uint32_t, (struct spdk_nvme_ns *ns), 0);
|
||||
|
||||
DEFINE_STUB_V(spdk_unaffinitize_thread, (void));
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_get_ns, struct spdk_nvme_ns *, (struct spdk_nvme_ctrlr *ctrlr,
|
||||
|
@ -45,27 +45,31 @@ DEFINE_STUB(spdk_nvme_ctrlr_cmd_admin_raw, int, (struct spdk_nvme_ctrlr *ctrlr,
|
||||
struct spdk_nvme_cmd *cmd, void *buf, uint32_t len,
|
||||
spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_cmd_io_raw, int, (struct spdk_nvme_ctrlr *ctrlr,
|
||||
struct spdk_nvme_qpair *qpair, struct spdk_nvme_cmd *cmd, void *buf, uint32_t len,
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_cmd_io_raw_with_md, int, (struct spdk_nvme_ctrlr *ctrlr,
|
||||
struct spdk_nvme_qpair *qpair, struct spdk_nvme_cmd *cmd, void *buf, uint32_t len, void *md_buf,
|
||||
spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_reset, int, (struct spdk_nvme_ctrlr *ctrlr), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ctrlr_reset_subsystem, int, (struct spdk_nvme_ctrlr *ctrlr), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_cmd_read, int,
|
||||
(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
|
||||
void *payload, uint64_t lba, uint32_t lba_count,
|
||||
spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags), 0);
|
||||
DEFINE_STUB(spdk_nvme_ns_cmd_read_with_md, int, (struct spdk_nvme_ns *ns,
|
||||
struct spdk_nvme_qpair *qpair,
|
||||
void *payload, void *metadata,
|
||||
uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
|
||||
uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_cmd_write, int,
|
||||
(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
|
||||
void *payload, uint64_t lba, uint32_t lba_count,
|
||||
spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags), 0);
|
||||
DEFINE_STUB(spdk_nvme_ns_cmd_write_with_md, int, (struct spdk_nvme_ns *ns,
|
||||
struct spdk_nvme_qpair *qpair,
|
||||
void *payload, void *metadata,
|
||||
uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
|
||||
uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_get_num_sectors, uint64_t,
|
||||
(struct spdk_nvme_ns *ns), 0);
|
||||
|
||||
DEFINE_STUB(spdk_nvme_ns_get_md_size, uint32_t, (struct spdk_nvme_ns *ns), 0);
|
||||
|
||||
DEFINE_STUB_V(spdk_unaffinitize_thread, (void));
|
||||
|
||||
DEFINE_STUB(nvme_io_msg_ctrlr_register, int,
|
||||
@ -178,6 +182,7 @@ test_cuse_nvme_submit_io_read_write(void)
|
||||
fuse_req_t req = (void *)0xDEEACDFF;
|
||||
unsigned flags = FUSE_IOCTL_DIR;
|
||||
uint32_t block_size = 4096;
|
||||
uint32_t md_size = 0;
|
||||
size_t in_bufsz = 4096;
|
||||
size_t out_bufsz = 4096;
|
||||
|
||||
@ -192,7 +197,7 @@ test_cuse_nvme_submit_io_read_write(void)
|
||||
|
||||
/* Submit IO read */
|
||||
cuse_nvme_submit_io_read(&cuse_device, req, 0, arg, &fi, flags,
|
||||
block_size, user_io, in_bufsz, out_bufsz);
|
||||
block_size, md_size, user_io, in_bufsz, out_bufsz);
|
||||
CU_ASSERT(g_ut_ctx != NULL);
|
||||
CU_ASSERT(g_ut_ctx->req == req);
|
||||
CU_ASSERT(g_ut_ctx->lba = user_io->slba);
|
||||
@ -200,13 +205,17 @@ test_cuse_nvme_submit_io_read_write(void)
|
||||
CU_ASSERT(g_ut_ctx->data_len ==
|
||||
(int)((user_io->nblocks + 1) * block_size));
|
||||
CU_ASSERT(g_ut_ctx->data != NULL);
|
||||
CU_ASSERT(g_ut_ctx->metadata_len == 0);
|
||||
CU_ASSERT(g_ut_ctx->metadata == NULL);
|
||||
CU_ASSERT(g_ut_ctx->appmask == 0);
|
||||
CU_ASSERT(g_ut_ctx->apptag == 0);
|
||||
cuse_io_ctx_free(g_ut_ctx);
|
||||
|
||||
/* Submit IO write */
|
||||
g_ut_ctx = NULL;
|
||||
|
||||
cuse_nvme_submit_io_write(&cuse_device, req, 0, arg, &fi, flags,
|
||||
block_size, user_io, in_bufsz, out_bufsz);
|
||||
block_size, md_size, user_io, in_bufsz, out_bufsz);
|
||||
CU_ASSERT(g_ut_ctx != NULL);
|
||||
CU_ASSERT(g_ut_ctx->req == req);
|
||||
CU_ASSERT(g_ut_ctx->lba = user_io->slba);
|
||||
@ -214,6 +223,74 @@ test_cuse_nvme_submit_io_read_write(void)
|
||||
CU_ASSERT(g_ut_ctx->data_len ==
|
||||
(int)((user_io->nblocks + 1) * block_size));
|
||||
CU_ASSERT(g_ut_ctx->data != NULL);
|
||||
CU_ASSERT(g_ut_ctx->metadata_len == 0);
|
||||
CU_ASSERT(g_ut_ctx->metadata == NULL);
|
||||
CU_ASSERT(g_ut_ctx->appmask == 0);
|
||||
CU_ASSERT(g_ut_ctx->apptag == 0);
|
||||
cuse_io_ctx_free(g_ut_ctx);
|
||||
free(user_io);
|
||||
}
|
||||
|
||||
static void
|
||||
test_cuse_nvme_submit_io_read_write_with_md(void)
|
||||
{
|
||||
struct cuse_device cuse_device = {};
|
||||
struct fuse_file_info fi = {};
|
||||
struct nvme_user_io *user_io = NULL;
|
||||
char arg[1024] = {};
|
||||
fuse_req_t req = (void *)0xDEEACDFF;
|
||||
unsigned flags = FUSE_IOCTL_DIR;
|
||||
uint32_t block_size = 4096;
|
||||
uint32_t md_size = 8;
|
||||
size_t in_bufsz = 4096;
|
||||
size_t out_bufsz = 4096;
|
||||
|
||||
/* Allocate memory to avoid stack buffer overflow */
|
||||
user_io = calloc(4, 4096);
|
||||
SPDK_CU_ASSERT_FATAL(user_io != NULL);
|
||||
cuse_device.ctrlr = (void *)0xDEADBEEF;
|
||||
cuse_device.nsid = 1;
|
||||
user_io->slba = 1024;
|
||||
user_io->nblocks = 1;
|
||||
user_io->appmask = 0xF00D;
|
||||
user_io->apptag = 0xC0DE;
|
||||
user_io->metadata = 0xDEADDEAD;
|
||||
g_ut_ctx = NULL;
|
||||
|
||||
/* Submit IO read */
|
||||
cuse_nvme_submit_io_read(&cuse_device, req, 0, arg, &fi, flags,
|
||||
block_size, md_size, user_io, in_bufsz, out_bufsz);
|
||||
CU_ASSERT(g_ut_ctx != NULL);
|
||||
CU_ASSERT(g_ut_ctx->req == req);
|
||||
CU_ASSERT(g_ut_ctx->lba = user_io->slba);
|
||||
CU_ASSERT(g_ut_ctx->lba_count == (uint32_t)(user_io->nblocks + 1));
|
||||
CU_ASSERT(g_ut_ctx->data_len ==
|
||||
(int)((user_io->nblocks + 1) * block_size));
|
||||
CU_ASSERT(g_ut_ctx->data != NULL);
|
||||
CU_ASSERT(g_ut_ctx->metadata_len ==
|
||||
(int)((user_io->nblocks + 1) * md_size));
|
||||
CU_ASSERT(g_ut_ctx->metadata != NULL);
|
||||
CU_ASSERT(g_ut_ctx->appmask == 0xF00D);
|
||||
CU_ASSERT(g_ut_ctx->apptag == 0xC0DE);
|
||||
cuse_io_ctx_free(g_ut_ctx);
|
||||
|
||||
/* Submit IO write */
|
||||
g_ut_ctx = NULL;
|
||||
|
||||
cuse_nvme_submit_io_write(&cuse_device, req, 0, arg, &fi, flags,
|
||||
block_size, md_size, user_io, in_bufsz, out_bufsz);
|
||||
CU_ASSERT(g_ut_ctx != NULL);
|
||||
CU_ASSERT(g_ut_ctx->req == req);
|
||||
CU_ASSERT(g_ut_ctx->lba = user_io->slba);
|
||||
CU_ASSERT(g_ut_ctx->lba_count == (uint32_t)(user_io->nblocks + 1));
|
||||
CU_ASSERT(g_ut_ctx->data_len ==
|
||||
(int)((user_io->nblocks + 1) * block_size));
|
||||
CU_ASSERT(g_ut_ctx->data != NULL);
|
||||
CU_ASSERT(g_ut_ctx->metadata_len ==
|
||||
(int)((user_io->nblocks + 1) * md_size));
|
||||
CU_ASSERT(g_ut_ctx->metadata != NULL);
|
||||
CU_ASSERT(g_ut_ctx->appmask == 0xF00D);
|
||||
CU_ASSERT(g_ut_ctx->apptag == 0xC0DE);
|
||||
cuse_io_ctx_free(g_ut_ctx);
|
||||
free(user_io);
|
||||
}
|
||||
@ -234,22 +311,74 @@ test_cuse_nvme_submit_passthru_cmd(void)
|
||||
|
||||
g_ut_ctx = NULL;
|
||||
/* Passthrough command */
|
||||
passthru_cmd->opcode = SPDK_NVME_DATA_CONTROLLER_TO_HOST;
|
||||
passthru_cmd->nsid = 1;
|
||||
passthru_cmd->data_len = 512;
|
||||
passthru_cmd->cdw10 = 0xc0de1010;
|
||||
passthru_cmd->cdw11 = 0xc0de1111;
|
||||
passthru_cmd->cdw12 = 0xc0de1212;
|
||||
passthru_cmd->cdw13 = 0xc0de1313;
|
||||
passthru_cmd->cdw14 = 0xc0de1414;
|
||||
passthru_cmd->cdw15 = 0xc0de1515;
|
||||
passthru_cmd->opcode = SPDK_NVME_DATA_CONTROLLER_TO_HOST;
|
||||
passthru_cmd->nsid = 1;
|
||||
passthru_cmd->data_len = 512;
|
||||
passthru_cmd->metadata_len = 0;
|
||||
passthru_cmd->cdw10 = 0xc0de1010;
|
||||
passthru_cmd->cdw11 = 0xc0de1111;
|
||||
passthru_cmd->cdw12 = 0xc0de1212;
|
||||
passthru_cmd->cdw13 = 0xc0de1313;
|
||||
passthru_cmd->cdw14 = 0xc0de1414;
|
||||
passthru_cmd->cdw15 = 0xc0de1515;
|
||||
|
||||
/* Send IO Command IOCTL */
|
||||
cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL, NVME_IOCTL_IO_CMD);
|
||||
cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL, NULL, NVME_IOCTL_IO_CMD);
|
||||
SPDK_CU_ASSERT_FATAL(g_ut_ctx != NULL);
|
||||
CU_ASSERT(g_ut_ctx->data != NULL);
|
||||
CU_ASSERT(g_ut_ctx->metadata == NULL);
|
||||
CU_ASSERT(g_ut_ctx->req == req);
|
||||
CU_ASSERT(g_ut_ctx->data_len == 512);
|
||||
CU_ASSERT(g_ut_ctx->metadata_len == 0);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.opc == SPDK_NVME_DATA_CONTROLLER_TO_HOST);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.nsid == 1);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.cdw10 == 0xc0de1010);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.cdw11 == 0xc0de1111);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.cdw12 == 0xc0de1212);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.cdw13 == 0xc0de1313);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.cdw14 == 0xc0de1414);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.cdw15 == 0xc0de1515);
|
||||
|
||||
cuse_io_ctx_free(g_ut_ctx);
|
||||
free(passthru_cmd);
|
||||
free(g_cuse_device);
|
||||
}
|
||||
|
||||
static void
|
||||
test_cuse_nvme_submit_passthru_cmd_with_md(void)
|
||||
{
|
||||
struct nvme_passthru_cmd *passthru_cmd = NULL;
|
||||
fuse_req_t req = (void *)0xDEEACDFF;
|
||||
|
||||
passthru_cmd = calloc(1, sizeof(struct nvme_passthru_cmd));
|
||||
g_cuse_device = calloc(1, sizeof(struct cuse_device));
|
||||
|
||||
/* Use fatal or we'll segfault if we didn't get memory */
|
||||
SPDK_CU_ASSERT_FATAL(passthru_cmd != NULL);
|
||||
SPDK_CU_ASSERT_FATAL(g_cuse_device != NULL);
|
||||
g_cuse_device->ctrlr = (void *)0xDEADBEEF;
|
||||
|
||||
g_ut_ctx = NULL;
|
||||
/* Passthrough command */
|
||||
passthru_cmd->opcode = SPDK_NVME_DATA_CONTROLLER_TO_HOST;
|
||||
passthru_cmd->nsid = 1;
|
||||
passthru_cmd->data_len = 512;
|
||||
passthru_cmd->metadata_len = 8;
|
||||
passthru_cmd->cdw10 = 0xc0de1010;
|
||||
passthru_cmd->cdw11 = 0xc0de1111;
|
||||
passthru_cmd->cdw12 = 0xc0de1212;
|
||||
passthru_cmd->cdw13 = 0xc0de1313;
|
||||
passthru_cmd->cdw14 = 0xc0de1414;
|
||||
passthru_cmd->cdw15 = 0xc0de1515;
|
||||
|
||||
/* Send IO Command IOCTL */
|
||||
cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL, NULL, NVME_IOCTL_IO_CMD);
|
||||
SPDK_CU_ASSERT_FATAL(g_ut_ctx != NULL);
|
||||
CU_ASSERT(g_ut_ctx->data != NULL);
|
||||
CU_ASSERT(g_ut_ctx->metadata != NULL);
|
||||
CU_ASSERT(g_ut_ctx->req == req);
|
||||
CU_ASSERT(g_ut_ctx->data_len == 512);
|
||||
CU_ASSERT(g_ut_ctx->metadata_len == 8);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.opc == SPDK_NVME_DATA_CONTROLLER_TO_HOST);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.nsid == 1);
|
||||
CU_ASSERT(g_ut_ctx->nvme_cmd.cdw10 == 0xc0de1010);
|
||||
@ -334,6 +463,11 @@ test_cuse_nvme_submit_io(void)
|
||||
CU_ASSERT(g_ut_ctx->lba_count == 2);
|
||||
CU_ASSERT(g_ut_ctx->data_len == 2 * 4096);
|
||||
CU_ASSERT(g_ut_ctx->data != NULL);
|
||||
CU_ASSERT(g_ut_ctx->metadata_len == 0);
|
||||
CU_ASSERT(g_ut_ctx->metadata == NULL);
|
||||
CU_ASSERT(g_ut_ctx->appmask == 0);
|
||||
CU_ASSERT(g_ut_ctx->apptag == 0);
|
||||
|
||||
cuse_io_ctx_free(g_ut_ctx);
|
||||
|
||||
/* Write */
|
||||
@ -348,6 +482,10 @@ test_cuse_nvme_submit_io(void)
|
||||
CU_ASSERT(g_ut_ctx->lba_count == 2);
|
||||
CU_ASSERT(g_ut_ctx->data_len == 2 * 4096);
|
||||
CU_ASSERT(g_ut_ctx->data != NULL);
|
||||
CU_ASSERT(g_ut_ctx->metadata_len == 0);
|
||||
CU_ASSERT(g_ut_ctx->metadata == NULL);
|
||||
CU_ASSERT(g_ut_ctx->appmask == 0);
|
||||
CU_ASSERT(g_ut_ctx->apptag == 0);
|
||||
cuse_io_ctx_free(g_ut_ctx);
|
||||
|
||||
/* Invalid */
|
||||
@ -428,7 +566,9 @@ int main(int argc, char **argv)
|
||||
|
||||
suite = CU_add_suite("nvme_cuse", NULL, NULL);
|
||||
CU_ADD_TEST(suite, test_cuse_nvme_submit_io_read_write);
|
||||
CU_ADD_TEST(suite, test_cuse_nvme_submit_io_read_write_with_md);
|
||||
CU_ADD_TEST(suite, test_cuse_nvme_submit_passthru_cmd);
|
||||
CU_ADD_TEST(suite, test_cuse_nvme_submit_passthru_cmd_with_md);
|
||||
CU_ADD_TEST(suite, test_nvme_cuse_get_cuse_ns_device);
|
||||
CU_ADD_TEST(suite, test_cuse_nvme_submit_io);
|
||||
CU_ADD_TEST(suite, test_cuse_nvme_reset);
|
||||
|
Loading…
Reference in New Issue
Block a user