Commit bca7570c authored by Aleksey Marchuk's avatar Aleksey Marchuk Committed by Tomasz Zawadzki
Browse files

nvmf: Fix DIF ctx initialization



The issue was found when size of spdk_bdev_ext_io_opts in
nvmf_bdev_ctrlr_read_cmd was set to a correct value. As result,
dif_check_flags_exclude_mask fit into the size and was actually used by
bdev layer.
If initiator doesn't specify any DIF related fields then
dif_check_flags_exclude_mask is set to SPDK_NVME_IO_FLAGS_PRCHK_MASK and
bdev layer disables all DIF operations. However, transport layer still
attempts to verify DIF on read and get the following errors
(fio_dif_1_default test):

[2025-09-29 10:18:07.256795] dif.c: 922:_dif_verify: *ERROR*: Failed to compare Guard: LBA=0,  Expected=0, Actual=e4c3
[2025-09-29 10:18:07.256803] tcp.c:2953:_nvmf_tcp_send_c2h_data: *ERROR*: DIF error detected. type=4, offset=0
[2025-09-29 10:18:07.256826] dif.c: 922:_dif_verify: *ERROR*: Failed to compare Guard: LBA=0,  Expected=0, Actual=a366
[2025-09-29 10:18:07.256832] tcp.c:2953:_nvmf_tcp_send_c2h_data: *ERROR*: DIF error detected. type=4, offset=0
[2025-09-29 10:18:07.256853] dif.c: 922:_dif_verify: *ERROR*: Failed to compare Guard: LBA=0,  Expected=0, Actual=9503
[2025-09-29 10:18:07.256859] tcp.c:2953:_nvmf_tcp_send_c2h_data: *ERROR*: DIF error detected. type=4, offset=0
[2025-09-29 10:18:07.256914] bdev_nvme.c:7994:bdev_nvme_readv_done: *ERROR*: readv completed with PI error (sct=2, sc=130)
[2025-09-29 10:18:07.257014] bdev_nvme.c:7994:bdev_nvme_readv_done: *ERROR*: readv completed with PI error (sct=2, sc=130)
[2025-09-29 10:18:07.257032] bdev_nvme.c:7994:bdev_nvme_readv_done: *ERROR*: readv completed with PI error (sct=2, sc=130)

The fix is to set dif_check_flags_exclude_mask if dif_insert_or_strip in
transport is disabled

Change-Id: Ib65f6645d0a46edafa083db9cf6906c585b1e831
Signed-off-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/26794


Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Reviewed-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
Community-CI: Mellanox Build Bot
parent 9f0b07a9
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -315,7 +315,8 @@ nvmf_bdev_ctrlr_get_rw_params(const struct spdk_nvme_cmd *cmd, uint64_t *start_l

static void
nvmf_bdev_ctrlr_get_rw_ext_params(const struct spdk_nvme_cmd *cmd,
				  struct spdk_bdev_ext_io_opts *opts)
				  struct spdk_bdev_ext_io_opts *opts,
				  bool set_dif_mask)
{
	/* Get CDW12 values */
	opts->nvme_cdw12.raw = from_le32(&cmd->cdw12);
@@ -327,8 +328,10 @@ nvmf_bdev_ctrlr_get_rw_ext_params(const struct spdk_nvme_cmd *cmd,
	 * it does not check DIF check flags in CDW because DIF is not NVMe
	 * specific. Hence, copy DIF check flags from CDW12 to dif_check_flags_exclude_mask.
	 */
	if (set_dif_mask) {
		opts->dif_check_flags_exclude_mask = (~opts->nvme_cdw12.raw) & SPDK_NVME_IO_FLAGS_PRCHK_MASK;
	}
}

static bool
nvmf_bdev_ctrlr_lba_in_range(uint64_t bdev_num_blocks, uint64_t io_start_lba,
@@ -394,7 +397,7 @@ nvmf_bdev_ctrlr_read_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
			 struct spdk_io_channel *ch, struct spdk_nvmf_request *req)
{
	struct spdk_bdev_ext_io_opts opts = {
		.size = SPDK_SIZEOF(&opts, accel_sequence),
		.size = SPDK_SIZEOF(&opts, nvme_cdw13),
		.memory_domain = req->memory_domain,
		.memory_domain_ctx = req->memory_domain_ctx,
		.accel_sequence = req->accel_sequence,
@@ -408,7 +411,7 @@ nvmf_bdev_ctrlr_read_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
	int rc;

	nvmf_bdev_ctrlr_get_rw_params(cmd, &start_lba, &num_blocks);
	nvmf_bdev_ctrlr_get_rw_ext_params(cmd, &opts);
	nvmf_bdev_ctrlr_get_rw_ext_params(cmd, &opts, !req->dif_enabled);

	if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, start_lba, num_blocks))) {
		SPDK_ERRLOG("end of media\n");
@@ -461,7 +464,7 @@ nvmf_bdev_ctrlr_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
	int rc;

	nvmf_bdev_ctrlr_get_rw_params(cmd, &start_lba, &num_blocks);
	nvmf_bdev_ctrlr_get_rw_ext_params(cmd, &opts);
	nvmf_bdev_ctrlr_get_rw_ext_params(cmd, &opts, !req->dif_enabled);

	if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, start_lba, num_blocks))) {
		SPDK_ERRLOG("end of media\n");
+1 −1
Original line number Diff line number Diff line
@@ -374,7 +374,7 @@ test_get_rw_ext_params(void)
	to_le32(&cmd.cdw12, 0x9875 | SPDK_NVME_IO_FLAGS_DATA_PLACEMENT_DIRECTIVE |
		SPDK_NVME_IO_FLAGS_PRCHK_GUARD);
	to_le32(&cmd.cdw13, 0x2 << 16);
	nvmf_bdev_ctrlr_get_rw_ext_params(&cmd, &opts);
	nvmf_bdev_ctrlr_get_rw_ext_params(&cmd, &opts, true);
	CU_ASSERT(opts.nvme_cdw12.raw == 0x10209875);
	CU_ASSERT(opts.nvme_cdw13.raw == 0x20000);
	CU_ASSERT((opts.dif_check_flags_exclude_mask ^ SPDK_NVME_IO_FLAGS_PRCHK_MASK)