From 3a58b2fb2f99ff469507dcb207688598bb678395 Mon Sep 17 00:00:00 2001 From: Konrad Sztyber Date: Mon, 23 Sep 2019 11:32:49 +0200 Subject: [PATCH] bdev/ocssd: append command This patch adds support for the append operation. The user doesn't need to specify the exact location of where the data should be placed, but only need to pass starting LBA of a zone to append to. The user can retrieve the address the data was written at during completion callback. Change-Id: Ic03abcf2e7a953a7a229a6b6b6122fffa01cb714 Signed-off-by: Konrad Sztyber Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/469120 Reviewed-by: Jim Harris Reviewed-by: Ben Walker Reviewed-by: Mateusz Kozlowski Tested-by: SPDK CI Jenkins Community-CI: Broadcom SPDK FC-NVMe CI Community-CI: SPDK CI Jenkins --- module/bdev/nvme/bdev_ocssd.c | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/module/bdev/nvme/bdev_ocssd.c b/module/bdev/nvme/bdev_ocssd.c index a3900150a..2e6df7b97 100644 --- a/module/bdev/nvme/bdev_ocssd.c +++ b/module/bdev/nvme/bdev_ocssd.c @@ -354,6 +354,10 @@ bdev_ocssd_write_cb(void *ctx, const struct spdk_nvme_cpl *cpl) struct spdk_bdev_io *bdev_io = ctx; struct bdev_ocssd_io *ocdev_io = (struct bdev_ocssd_io *)bdev_io->driver_ctx; + if (bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND) { + bdev_io->u.bdev.offset_blocks = ocdev_io->io.zone->write_pointer; + } + ocdev_io->io.zone->write_pointer = bdev_io->u.bdev.offset_blocks + bdev_io->u.bdev.num_blocks; assert(ocdev_io->io.zone->write_pointer <= ocdev_io->io.zone->slba + @@ -399,6 +403,50 @@ bdev_ocssd_write(struct spdk_io_channel *ioch, struct spdk_bdev_io *bdev_io) return rc; } +static int +bdev_ocssd_zone_append(struct spdk_io_channel *ioch, struct spdk_bdev_io *bdev_io) +{ + struct ocssd_bdev *ocssd_bdev = bdev_io->bdev->ctxt; + struct nvme_bdev *nvme_bdev = &ocssd_bdev->nvme_bdev; + struct nvme_io_channel *nvme_ioch = spdk_io_channel_get_ctx(ioch); + struct bdev_ocssd_io *ocdev_io = (struct bdev_ocssd_io *)bdev_io->driver_ctx; + struct bdev_ocssd_zone *zone; + uint64_t lba; + int rc = 0; + + zone = bdev_ocssd_get_zone_by_slba(ocssd_bdev, bdev_io->u.bdev.offset_blocks); + if (!zone) { + SPDK_ERRLOG("Invalid zone SLBA: %"PRIu64"\n", bdev_io->u.bdev.offset_blocks); + return -EINVAL; + } + + if (__atomic_exchange_n(&zone->busy, true, __ATOMIC_SEQ_CST)) { + return -EAGAIN; + } + + if (zone->slba + zone->capacity - zone->write_pointer < bdev_io->u.bdev.num_blocks) { + SPDK_ERRLOG("Insufficient number of blocks remaining\n"); + rc = -ENOSPC; + goto out; + } + + ocdev_io->io.zone = zone; + ocdev_io->io.iov_pos = 0; + ocdev_io->io.iov_off = 0; + + lba = bdev_ocssd_to_disk_lba(ocssd_bdev, zone->write_pointer); + rc = spdk_nvme_ns_cmd_writev_with_md(nvme_bdev->nvme_ns->ns, nvme_ioch->qpair, lba, + bdev_io->u.bdev.num_blocks, bdev_ocssd_write_cb, + bdev_io, 0, bdev_ocssd_reset_sgl, + bdev_ocssd_next_sge, bdev_io->u.bdev.md_buf, 0, 0); +out: + if (spdk_unlikely(rc != 0)) { + __atomic_store_n(&zone->busy, false, __ATOMIC_SEQ_CST); + } + + return rc; +} + static void bdev_ocssd_io_get_buf_cb(struct spdk_io_channel *ioch, struct spdk_bdev_io *bdev_io, bool success) { @@ -667,6 +715,10 @@ bdev_ocssd_submit_request(struct spdk_io_channel *ioch, struct spdk_bdev_io *bde rc = bdev_ocssd_get_zone_info(ioch, bdev_io); break; + case SPDK_BDEV_IO_TYPE_ZONE_APPEND: + rc = bdev_ocssd_zone_append(ioch, bdev_io); + break; + default: rc = -EINVAL; break; @@ -694,6 +746,7 @@ bdev_ocssd_io_type_supported(void *ctx, enum spdk_bdev_io_type type) case SPDK_BDEV_IO_TYPE_READ: case SPDK_BDEV_IO_TYPE_WRITE: case SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT: + case SPDK_BDEV_IO_TYPE_ZONE_APPEND: return true; default: