Commit 54e16f96 authored by Edward Yang's avatar Edward Yang Committed by Ben Walker
Browse files

bdev: Add spdk_bdev_nvme_admin_passthru



Support passthru for NVMe admin commands.

Change-Id: If926f2ecabb078a553158f544c10a92452dbdb39
Signed-off-by: default avatarEdward Yang <eyang@us.fujitsu.com>
Reviewed-on: https://review.gerrithub.io/363294


Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent aec9d3dc
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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);
+10 −0
Original line number Diff line number Diff line
@@ -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 */
+32 −0
Original line number Diff line number Diff line
@@ -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)
{
+59 −0
Original line number Diff line number Diff line
@@ -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)
{