lib/nvme: CUSE add admin requests
Admin requests handling for CUSE io producer: - NVME_IOCTL_ADMIN_CMD, - NVME_IOCTL_RESET Change-Id: I24169f7d08b90fd0a695b5bf3341fd56e0382b9f Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com> Signed-off-by: Maciej Szwed <maciej.szwed@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/469690 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
805d994281
commit
39283f0074
@ -61,6 +61,194 @@ struct cuse_device {
|
||||
static TAILQ_HEAD(, cuse_device) g_ctrlr_ctx_head = TAILQ_HEAD_INITIALIZER(g_ctrlr_ctx_head);
|
||||
static int g_controllers_found = 0;
|
||||
|
||||
struct cuse_io_ctx {
|
||||
struct spdk_nvme_cmd nvme_cmd;
|
||||
|
||||
uint64_t lba;
|
||||
uint32_t lba_count;
|
||||
|
||||
void *data;
|
||||
int data_len;
|
||||
|
||||
fuse_req_t req;
|
||||
};
|
||||
|
||||
static void
|
||||
cuse_io_ctx_free(struct cuse_io_ctx *ctx)
|
||||
{
|
||||
spdk_free(ctx->data);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
#define FUSE_REPLY_CHECK_BUFFER(req, arg, out_bufsz, val) \
|
||||
if (out_bufsz == 0) { \
|
||||
struct iovec out_iov; \
|
||||
out_iov.iov_base = (void *)arg; \
|
||||
out_iov.iov_len = sizeof(val); \
|
||||
fuse_reply_ioctl_retry(req, NULL, 0, &out_iov, 1); \
|
||||
return; \
|
||||
}
|
||||
|
||||
static void
|
||||
cuse_nvme_admin_cmd_cb(void *arg, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct cuse_io_ctx *ctx = arg;
|
||||
struct iovec out_iov[2];
|
||||
struct spdk_nvme_cpl _cpl;
|
||||
|
||||
memcpy(&_cpl, cpl, sizeof(struct spdk_nvme_cpl));
|
||||
|
||||
out_iov[0].iov_base = &_cpl.cdw0;
|
||||
out_iov[0].iov_len = sizeof(_cpl.cdw0);
|
||||
if (ctx->data_len > 0) {
|
||||
out_iov[1].iov_base = ctx->data;
|
||||
out_iov[1].iov_len = ctx->data_len;
|
||||
fuse_reply_ioctl_iov(ctx->req, 0, out_iov, 2);
|
||||
} else {
|
||||
fuse_reply_ioctl_iov(ctx->req, 0, out_iov, 1);
|
||||
}
|
||||
|
||||
cuse_io_ctx_free(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
cuse_nvme_admin_cmd_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg)
|
||||
{
|
||||
int rc;
|
||||
struct cuse_io_ctx *ctx = arg;
|
||||
|
||||
rc = spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, &ctx->nvme_cmd, ctx->data, ctx->data_len,
|
||||
cuse_nvme_admin_cmd_cb, (void *)ctx);
|
||||
if (rc < 0) {
|
||||
fuse_reply_err(ctx->req, EINVAL);
|
||||
cuse_io_ctx_free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cuse_nvme_admin_cmd(fuse_req_t req, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned flags,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
||||
{
|
||||
struct nvme_admin_cmd *admin_cmd;
|
||||
struct iovec in_iov, out_iov[2];
|
||||
struct cuse_io_ctx *ctx;
|
||||
int rv;
|
||||
struct cuse_device *cuse_device = fuse_req_userdata(req);
|
||||
|
||||
in_iov.iov_base = (void *)arg;
|
||||
in_iov.iov_len = sizeof(*admin_cmd);
|
||||
if (in_bufsz == 0) {
|
||||
fuse_reply_ioctl_retry(req, &in_iov, 1, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
admin_cmd = (struct nvme_admin_cmd *)in_buf;
|
||||
|
||||
switch (spdk_nvme_opc_get_data_transfer(admin_cmd->opcode)) {
|
||||
case SPDK_NVME_DATA_NONE:
|
||||
SPDK_ERRLOG("SPDK_NVME_DATA_NONE not implemented\n");
|
||||
fuse_reply_err(req, EINVAL);
|
||||
return;
|
||||
case SPDK_NVME_DATA_HOST_TO_CONTROLLER:
|
||||
SPDK_ERRLOG("SPDK_NVME_DATA_HOST_TO_CONTROLLER not implemented\n");
|
||||
fuse_reply_err(req, EINVAL);
|
||||
return;
|
||||
case SPDK_NVME_DATA_CONTROLLER_TO_HOST:
|
||||
if (out_bufsz == 0) {
|
||||
out_iov[0].iov_base = &((struct nvme_admin_cmd *)arg)->result;
|
||||
out_iov[0].iov_len = sizeof(uint32_t);
|
||||
if (admin_cmd->data_len > 0) {
|
||||
out_iov[1].iov_base = (void *)admin_cmd->addr;
|
||||
out_iov[1].iov_len = admin_cmd->data_len;
|
||||
fuse_reply_ioctl_retry(req, &in_iov, 1, out_iov, 2);
|
||||
} else {
|
||||
fuse_reply_ioctl_retry(req, &in_iov, 1, out_iov, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = (struct cuse_io_ctx *)calloc(1, sizeof(struct cuse_io_ctx));
|
||||
if (!ctx) {
|
||||
SPDK_ERRLOG("Cannot allocate memory for cuse_io_ctx\n");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->req = req;
|
||||
|
||||
memset(&ctx->nvme_cmd, 0, sizeof(ctx->nvme_cmd));
|
||||
ctx->nvme_cmd.opc = admin_cmd->opcode;
|
||||
ctx->nvme_cmd.nsid = admin_cmd->nsid;
|
||||
ctx->nvme_cmd.cdw10 = admin_cmd->cdw10;
|
||||
ctx->nvme_cmd.cdw11 = admin_cmd->cdw11;
|
||||
ctx->nvme_cmd.cdw12 = admin_cmd->cdw12;
|
||||
ctx->nvme_cmd.cdw13 = admin_cmd->cdw13;
|
||||
ctx->nvme_cmd.cdw14 = admin_cmd->cdw14;
|
||||
ctx->nvme_cmd.cdw15 = admin_cmd->cdw15;
|
||||
|
||||
ctx->data_len = admin_cmd->data_len;
|
||||
if (ctx->data_len > 0) {
|
||||
ctx->data = spdk_malloc(ctx->data_len, 0, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
|
||||
if (!ctx->data) {
|
||||
SPDK_ERRLOG("Cannot allocate memory for data\n");
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
free(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SPDK_NVME_DATA_BIDIRECTIONAL:
|
||||
fuse_reply_err(req, EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = nvme_io_msg_send(cuse_device->ctrlr, 0, cuse_nvme_admin_cmd_execute, ctx);
|
||||
if (rv) {
|
||||
SPDK_ERRLOG("Cannot send io msg to the controller\n");
|
||||
fuse_reply_err(req, -rv);
|
||||
cuse_io_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cuse_nvme_reset_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg)
|
||||
{
|
||||
int rc;
|
||||
fuse_req_t req = arg;
|
||||
|
||||
rc = spdk_nvme_ctrlr_reset(ctrlr);
|
||||
if (rc) {
|
||||
fuse_reply_err(req, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
fuse_reply_ioctl_iov(req, 0, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
cuse_nvme_reset(fuse_req_t req, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned flags,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
||||
{
|
||||
int rv;
|
||||
struct cuse_device *cuse_device = fuse_req_userdata(req);
|
||||
|
||||
if (cuse_device->nsid) {
|
||||
SPDK_ERRLOG("Namespace reset not supported\n");
|
||||
fuse_reply_err(req, EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = nvme_io_msg_send(cuse_device->ctrlr, cuse_device->nsid, cuse_nvme_reset_execute, (void *)req);
|
||||
if (rv) {
|
||||
SPDK_ERRLOG("Cannot send reset\n");
|
||||
fuse_reply_err(req, EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cuse_ctrlr_ioctl(fuse_req_t req, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned flags,
|
||||
@ -71,8 +259,19 @@ cuse_ctrlr_ioctl(fuse_req_t req, int cmd, void *arg,
|
||||
return;
|
||||
}
|
||||
|
||||
SPDK_ERRLOG("Unsupported IOCTL 0x%X.\n", cmd);
|
||||
fuse_reply_err(req, EINVAL);
|
||||
switch (cmd) {
|
||||
case NVME_IOCTL_ADMIN_CMD:
|
||||
cuse_nvme_admin_cmd(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz);
|
||||
break;
|
||||
|
||||
case NVME_IOCTL_RESET:
|
||||
cuse_nvme_reset(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz);
|
||||
break;
|
||||
|
||||
default:
|
||||
SPDK_ERRLOG("Unsupported IOCTL 0x%X.\n", cmd);
|
||||
fuse_reply_err(req, EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user