Commit e1f15ba5 authored by Changpeng Liu's avatar Changpeng Liu Committed by Konrad Sztyber
Browse files

bdev/malloc: generate Protection Information for deallocated ranges



Malloc bdev will zeroout all data buffer include the metadata after
UNMAP and WRITE ZEROES, but for the protection information we should
fill `SPDK_DIF_APPTAG_IGNORE` and `SPDK_DIF_REFTAG_IGNORE` for
Application Tag and Reference Tag in protection information.

Here, after UNMAP and WRITE ZEORES done, we fill the protection
information fields with above values, then when reading to the
deallocated ranges, the verify API will skip checking the
protection information.

Fix issue #3156.

Change-Id: I403a1c7f5da54146db6e760081d93f6346b0b2d7
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/20493


Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
parent 247e4e6e
Loading
Loading
Loading
Loading
+69 −2
Original line number Diff line number Diff line
@@ -96,6 +96,62 @@ malloc_verify_pi(struct spdk_bdev_io *bdev_io)
	return rc;
}

static int
malloc_unmap_write_zeroes_generate_pi(struct spdk_bdev_io *bdev_io)
{
	struct spdk_bdev *bdev = bdev_io->bdev;
	struct malloc_disk *mdisk = bdev_io->bdev->ctxt;
	uint32_t block_size = bdev_io->bdev->blocklen;
	struct spdk_dif_ctx dif_ctx;
	struct spdk_dif_ctx_init_ext_opts dif_opts;
	int rc;

	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
	rc = spdk_dif_ctx_init(&dif_ctx,
			       bdev->blocklen,
			       bdev->md_len,
			       bdev->md_interleave,
			       bdev->dif_is_head_of_md,
			       bdev->dif_type,
			       bdev->dif_check_flags,
			       SPDK_DIF_REFTAG_IGNORE,
			       0xFFFF, SPDK_DIF_APPTAG_IGNORE,
			       0, 0, &dif_opts);
	if (rc != 0) {
		SPDK_ERRLOG("Initialization of DIF/DIX context failed\n");
		return rc;
	}

	if (bdev->md_interleave) {
		struct iovec iov = {
			.iov_base	= mdisk->malloc_buf + bdev_io->u.bdev.offset_blocks * block_size,
			.iov_len	= bdev_io->u.bdev.num_blocks * block_size,
		};

		rc = spdk_dif_generate(&iov, 1, bdev_io->u.bdev.num_blocks, &dif_ctx);
	} else {
		struct iovec iov = {
			.iov_base	= mdisk->malloc_buf + bdev_io->u.bdev.offset_blocks * block_size,
			.iov_len	= bdev_io->u.bdev.num_blocks * block_size,
		};

		struct iovec md_iov = {
			.iov_base	= mdisk->malloc_md_buf + bdev_io->u.bdev.offset_blocks * bdev->md_len,
			.iov_len	= bdev_io->u.bdev.num_blocks * bdev->md_len,
		};

		rc = spdk_dix_generate(&iov, 1, &md_iov, bdev_io->u.bdev.num_blocks, &dif_ctx);
	}

	if (rc != 0) {
		SPDK_ERRLOG("Formatting by DIF/DIX failed\n");
	}


	return rc;
}

static void
malloc_done(void *ref, int status)
{
@@ -126,6 +182,15 @@ malloc_done(void *ref, int status)
		}
	}

	if (bdev_io->bdev->dif_type != SPDK_DIF_DISABLE &&
	    (bdev_io->type == SPDK_BDEV_IO_TYPE_UNMAP || bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE_ZEROES) &&
	    task->status == SPDK_BDEV_IO_STATUS_SUCCESS) {
		rc = malloc_unmap_write_zeroes_generate_pi(bdev_io);
		if (rc != 0) {
			task->status = SPDK_BDEV_IO_STATUS_FAILED;
		}
	}

	assert(!bdev_io->u.bdev.accel_sequence || task->status == SPDK_BDEV_IO_STATUS_NOMEM);
	spdk_bdev_io_complete(spdk_bdev_io_from_ctx(task), task->status);
}
@@ -573,6 +638,7 @@ malloc_disk_setup_pi(struct malloc_disk *mdisk)

	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
	/* Set APPTAG|REFTAG_IGNORE to PI fields after creation of malloc bdev */
	rc = spdk_dif_ctx_init(&dif_ctx,
			       bdev->blocklen,
			       bdev->md_len,
@@ -580,8 +646,9 @@ malloc_disk_setup_pi(struct malloc_disk *mdisk)
			       bdev->dif_is_head_of_md,
			       bdev->dif_type,
			       bdev->dif_check_flags,
			       0,	/* configure the whole buffers */
			       0, 0, 0, 0, &dif_opts);
			       SPDK_DIF_REFTAG_IGNORE,
			       0xFFFF, SPDK_DIF_APPTAG_IGNORE,
			       0, 0, &dif_opts);
	if (rc != 0) {
		SPDK_ERRLOG("Initialization of DIF/DIX context failed\n");
		return rc;