From 32a961fc5db60be8050b8cc36717a3823e0760c6 Mon Sep 17 00:00:00 2001 From: Maciej Szwed Date: Fri, 13 Dec 2019 10:56:17 +0100 Subject: [PATCH] bdev: Add check for atomic compare and write unit Compare and write fused operation num_blocks should not exceed value of 'atomic compare and write unit'. In case of NVMe native support we should read this value from 'namespace atomic compare and write unit' if set in namespace identify data, otherwise from 'atomic and write unit' field in controller identify data. If bdev does not support this natively we should set this value to 1. Signed-off-by: Maciej Szwed Change-Id: Ib1ea02dbf9d1eed476d9dd0114ea96b1376e0c45 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/477911 Tested-by: SPDK CI Jenkins Community-CI: Broadcom SPDK FC-NVMe CI Reviewed-by: Ben Walker Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris --- include/spdk/bdev_module.h | 3 +++ lib/bdev/bdev.c | 9 +++++++++ module/bdev/nvme/bdev_nvme.c | 11 ++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/spdk/bdev_module.h b/include/spdk/bdev_module.h index debd695a3..c30d17119 100644 --- a/include/spdk/bdev_module.h +++ b/include/spdk/bdev_module.h @@ -271,6 +271,9 @@ struct spdk_bdev { /** Number of blocks required for write */ uint32_t write_unit_size; + /** Atomic compare & write unit */ + uint16_t acwu; + /** * Specifies an alignment requirement for data buffers associated with an spdk_bdev_io. * 0 = no alignment requirement diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 38f526554..b4cd6a683 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -3657,6 +3657,10 @@ spdk_bdev_comparev_and_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io return -EINVAL; } + if (num_blocks > bdev->acwu) { + return -EINVAL; + } + bdev_io = bdev_channel_get_io(channel); if (!bdev_io) { return -ENOMEM; @@ -4750,6 +4754,11 @@ bdev_init(struct spdk_bdev *bdev) bdev->write_unit_size = 1; } + /* Set ACWU value to 1 if bdev module did not set it (does not support it natively) */ + if (bdev->acwu == 0) { + bdev->acwu = 1; + } + TAILQ_INIT(&bdev->internal.open_descs); TAILQ_INIT(&bdev->internal.locked_ranges); TAILQ_INIT(&bdev->internal.pending_locked_ranges); diff --git a/module/bdev/nvme/bdev_nvme.c b/module/bdev/nvme/bdev_nvme.c index 32b2fd7bb..482744ea4 100644 --- a/module/bdev/nvme/bdev_nvme.c +++ b/module/bdev/nvme/bdev_nvme.c @@ -899,9 +899,10 @@ nvme_ctrlr_populate_standard_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr, bdev->disk.uuid = *uuid; } + nsdata = spdk_nvme_ns_get_data(ns); + bdev->disk.md_len = spdk_nvme_ns_get_md_size(ns); if (bdev->disk.md_len != 0) { - nsdata = spdk_nvme_ns_get_data(ns); bdev->disk.md_interleave = nsdata->flbas.extended; bdev->disk.dif_type = (enum spdk_dif_type)spdk_nvme_ns_get_pi_type(ns); if (bdev->disk.dif_type != SPDK_DIF_DISABLE) { @@ -910,6 +911,14 @@ nvme_ctrlr_populate_standard_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr, } } + if (!bdev_nvme_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_COMPARE_AND_WRITE)) { + bdev->disk.acwu = 0; + } else if (nsdata->nsfeat.ns_atomic_write_unit) { + bdev->disk.acwu = nsdata->nacwu; + } else { + bdev->disk.acwu = cdata->acwu; + } + bdev->disk.ctxt = bdev; bdev->disk.fn_table = &nvmelib_fn_table; bdev->disk.module = &nvme_if;