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:
Edward Yang 2017-05-13 13:12:13 -07:00 committed by Ben Walker
parent aec9d3dcb5
commit 54e16f96b3
4 changed files with 108 additions and 0 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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)
{

View File

@ -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)
{