bdev: Add spdk_bdev_nvme_admin_passthru
Support passthru for NVMe admin commands. Change-Id: If926f2ecabb078a553158f544c10a92452dbdb39 Signed-off-by: Edward Yang <eyang@us.fujitsu.com> Reviewed-on: https://review.gerrithub.io/363294 Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
aec9d3dcb5
commit
54e16f96b3
@ -43,6 +43,7 @@
|
||||
|
||||
#include "spdk/event.h"
|
||||
#include "spdk/scsi_spec.h"
|
||||
#include "spdk/nvme_spec.h"
|
||||
|
||||
#define SPDK_BDEV_SMALL_BUF_MAX_SIZE 8192
|
||||
#define SPDK_BDEV_LARGE_BUF_MAX_SIZE (64 * 1024)
|
||||
@ -82,6 +83,7 @@ enum spdk_bdev_io_type {
|
||||
SPDK_BDEV_IO_TYPE_UNMAP,
|
||||
SPDK_BDEV_IO_TYPE_FLUSH,
|
||||
SPDK_BDEV_IO_TYPE_RESET,
|
||||
SPDK_BDEV_IO_TYPE_NVME_ADMIN,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -223,6 +225,11 @@ struct spdk_bdev_io *spdk_bdev_flush(struct spdk_bdev *bdev, struct spdk_io_chan
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||
void spdk_bdev_get_io_stat(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
||||
struct spdk_bdev_io_stat *stat);
|
||||
struct spdk_bdev_io *spdk_bdev_nvme_admin_passthru(struct spdk_bdev *bdev,
|
||||
struct spdk_io_channel *ch,
|
||||
const struct spdk_nvme_cmd *cmd,
|
||||
void *buf, size_t nbytes,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||
int spdk_bdev_free_io(struct spdk_bdev_io *bdev_io);
|
||||
int spdk_bdev_reset(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||
|
@ -285,6 +285,16 @@ struct spdk_bdev_io {
|
||||
/** Represents the number of bytes to be flushed, starting at offset. */
|
||||
uint64_t length;
|
||||
} flush;
|
||||
struct {
|
||||
/* The NVMe command to execute */
|
||||
struct spdk_nvme_cmd cmd;
|
||||
|
||||
/* The data buffer to transfer */
|
||||
void *buf;
|
||||
|
||||
/* The number of bytes to transfer */
|
||||
size_t nbytes;
|
||||
} nvme_passthru;
|
||||
} u;
|
||||
|
||||
/** Status for the IO */
|
||||
|
@ -964,6 +964,38 @@ spdk_bdev_get_io_stat(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
||||
memset(&channel->stat, 0, sizeof(channel->stat));
|
||||
}
|
||||
|
||||
struct spdk_bdev_io *
|
||||
spdk_bdev_nvme_admin_passthru(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
||||
const struct spdk_nvme_cmd *cmd, void *buf, size_t nbytes,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
struct spdk_bdev_io *bdev_io;
|
||||
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
||||
int rc;
|
||||
|
||||
bdev_io = spdk_bdev_get_io();
|
||||
if (!bdev_io) {
|
||||
SPDK_ERRLOG("bdev_io memory allocation failed during nvme_admin_passthru\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdev_io->ch = channel;
|
||||
bdev_io->type = SPDK_BDEV_IO_TYPE_NVME_ADMIN;
|
||||
bdev_io->u.nvme_passthru.cmd = *cmd;
|
||||
bdev_io->u.nvme_passthru.buf = buf;
|
||||
bdev_io->u.nvme_passthru.nbytes = nbytes;
|
||||
|
||||
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
||||
|
||||
rc = spdk_bdev_io_submit(bdev_io);
|
||||
if (rc < 0) {
|
||||
spdk_bdev_put_io(bdev_io);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bdev_io;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
|
@ -92,6 +92,12 @@ struct nvme_bdev_io {
|
||||
|
||||
/** Offset in current iovec. */
|
||||
uint32_t iov_offset;
|
||||
|
||||
/** Saved status for admin passthru completion event. */
|
||||
struct spdk_nvme_cpl cpl;
|
||||
|
||||
/** Event pointer for admin passthru completion. */
|
||||
struct spdk_event *admin_passthru_completion_event;
|
||||
};
|
||||
|
||||
enum data_direction {
|
||||
@ -131,6 +137,8 @@ static int bdev_nvme_queue_cmd(struct nvme_bdev *bdev, struct spdk_nvme_qpair *q
|
||||
struct nvme_bdev_io *bio,
|
||||
int direction, struct iovec *iov, int iovcnt, uint64_t nbytes,
|
||||
uint64_t offset);
|
||||
static int bdev_nvme_admin_passthru(struct nvme_bdev *nbdev, struct nvme_bdev_io *bio,
|
||||
struct spdk_nvme_cmd *cmd, void *buf, size_t nbytes);
|
||||
|
||||
static int
|
||||
bdev_nvme_get_ctx_size(void)
|
||||
@ -296,6 +304,13 @@ _bdev_nvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_
|
||||
bdev_io->u.flush.offset,
|
||||
bdev_io->u.flush.length);
|
||||
|
||||
case SPDK_BDEV_IO_TYPE_NVME_ADMIN:
|
||||
return bdev_nvme_admin_passthru((struct nvme_bdev *)bdev_io->bdev->ctxt,
|
||||
(struct nvme_bdev_io *)bdev_io->driver_ctx,
|
||||
&bdev_io->u.nvme_passthru.cmd,
|
||||
bdev_io->u.nvme_passthru.buf,
|
||||
bdev_io->u.nvme_passthru.nbytes);
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -321,6 +336,7 @@ bdev_nvme_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
|
||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||
case SPDK_BDEV_IO_TYPE_RESET:
|
||||
case SPDK_BDEV_IO_TYPE_FLUSH:
|
||||
case SPDK_BDEV_IO_TYPE_NVME_ADMIN:
|
||||
return true;
|
||||
|
||||
case SPDK_BDEV_IO_TYPE_UNMAP:
|
||||
@ -962,6 +978,25 @@ bdev_nvme_queued_done(void *ref, const struct spdk_nvme_cpl *cpl)
|
||||
spdk_bdev_io_complete_nvme_status(bdev_io, cpl->status.sct, cpl->status.sc);
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_nvme_admin_passthru_completion(void *arg1, void *arg2)
|
||||
{
|
||||
struct spdk_bdev_io *bdev_io = arg1;
|
||||
struct nvme_bdev_io *bio = arg2;
|
||||
|
||||
spdk_bdev_io_complete_nvme_status(bdev_io,
|
||||
bio->cpl.status.sct, bio->cpl.status.sc);
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_nvme_admin_passthru_done(void *ref, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct nvme_bdev_io *bio = ref;
|
||||
|
||||
bio->cpl = *cpl;
|
||||
spdk_event_call(bio->admin_passthru_completion_event);
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_nvme_queued_reset_sgl(void *ref, uint32_t sgl_offset)
|
||||
{
|
||||
@ -1075,6 +1110,30 @@ bdev_nvme_unmap(struct nvme_bdev *nbdev, struct spdk_io_channel *ch,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
bdev_nvme_admin_passthru(struct nvme_bdev *nbdev, struct nvme_bdev_io *bio,
|
||||
struct spdk_nvme_cmd *cmd, void *buf, size_t nbytes)
|
||||
{
|
||||
struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(bio);
|
||||
|
||||
if (nbytes > UINT32_MAX) {
|
||||
SPDK_ERRLOG("nbytes is greater than UINT32_MAX.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bio->admin_passthru_completion_event =
|
||||
spdk_event_allocate(spdk_env_get_current_core(), bdev_nvme_admin_passthru_completion,
|
||||
bdev_io, bio);
|
||||
|
||||
if (bio->admin_passthru_completion_event == NULL) {
|
||||
SPDK_ERRLOG("memory allocation for bio->admin_passthru_completion_event failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return spdk_nvme_ctrlr_cmd_admin_raw(nbdev->nvme_ctrlr->ctrlr, cmd, buf,
|
||||
(uint32_t)nbytes, bdev_nvme_admin_passthru_done, bio);
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_nvme_get_spdk_running_config(FILE *fp)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user