Commit 3e911e17 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Ben Walker
Browse files

lib/ftl: non-volatile cache's header validation function



Moved metadata header verification to a separate function, since the
metadata read callback got pretty large.

Change-Id: I0c8b2eb493631a6495ce2ef7d9586d2c7cb7772f
Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/460795


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 5c9a5039
Loading
Loading
Loading
Loading
+49 −45
Original line number Diff line number Diff line
@@ -863,68 +863,75 @@ ftl_nv_cache_scan_block(struct ftl_nv_cache_block *block)
	return 0;
}

static void
ftl_nv_cache_read_header_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
static bool
ftl_nv_cache_header_valid(struct spdk_ftl_dev *dev, const struct ftl_nv_cache_header *hdr)
{
	struct ftl_restore *restore = cb_arg;
	struct spdk_ftl_dev *dev = restore->dev;
	struct spdk_bdev *bdev;
	struct ftl_nv_cache *nv_cache = &dev->nv_cache;
	struct ftl_nv_cache_header *hdr;
	struct iovec *iov = NULL;
	int iov_cnt = 0, i, rc;
	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(dev->nv_cache.bdev_desc);
	uint32_t checksum;

	if (!success) {
		SPDK_ERRLOG("Unable to read non-volatile cache metadata header\n");
		ftl_restore_complete(restore, -ENOTRECOVERABLE);
		goto out;
	}

	bdev = spdk_bdev_desc_get_bdev(nv_cache->bdev_desc);
	spdk_bdev_io_get_iovec(bdev_io, &iov, &iov_cnt);
	if (!iov) {
		SPDK_ERRLOG("Unable to get the iov for non-volatile cache metadata header\n");
		ftl_restore_complete(restore, -ENOTRECOVERABLE);
		goto out;
	}
	hdr = iov[0].iov_base;

	checksum = spdk_crc32c_update(hdr, offsetof(struct ftl_nv_cache_header, checksum), 0);
	if (checksum != hdr->checksum) {
		SPDK_ERRLOG("Invalid header checksum (found: %"PRIu32", expected: %"PRIu32")\n",
			    checksum, hdr->checksum);
		ftl_restore_complete(restore, -ENOTRECOVERABLE);
		goto out;
		return false;
	}

	if (hdr->version != FTL_NV_CACHE_HEADER_VERSION) {
		SPDK_ERRLOG("Invalid header version (found: %"PRIu32", expected: %"PRIu32")\n",
			    hdr->version, FTL_NV_CACHE_HEADER_VERSION);
		ftl_restore_complete(restore, -ENOTRECOVERABLE);
		goto out;
		return false;
	}

	if (hdr->size != spdk_bdev_get_num_blocks(bdev)) {
		SPDK_ERRLOG("Unexpected size of the non-volatile cache bdev (%"PRIu64", expected: %"
			    PRIu64")\n", hdr->size, spdk_bdev_get_num_blocks(bdev));
		ftl_restore_complete(restore, -ENOTRECOVERABLE);
		goto out;
		return false;
	}

	if (spdk_uuid_compare(&hdr->uuid, &dev->uuid)) {
		SPDK_ERRLOG("Invalid device UUID\n");
		return false;
	}

	if (!ftl_nv_cache_phase_is_valid(hdr->phase) && hdr->phase != 0) {
		return false;
	}

	return true;
}

static void
ftl_nv_cache_read_header_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{
	struct ftl_restore *restore = cb_arg;
	struct spdk_ftl_dev *dev = restore->dev;
	struct ftl_nv_cache *nv_cache = &dev->nv_cache;
	struct ftl_nv_cache_header *hdr;
	struct iovec *iov = NULL;
	int iov_cnt = 0, i, rc;

	if (!success) {
		SPDK_ERRLOG("Unable to read non-volatile cache metadata header\n");
		ftl_restore_complete(restore, -ENOTRECOVERABLE);
		goto out;
	}

	spdk_bdev_io_get_iovec(bdev_io, &iov, &iov_cnt);
	assert(iov != NULL);
	hdr = iov[0].iov_base;

	if (!ftl_nv_cache_header_valid(dev, hdr)) {
		ftl_restore_complete(restore, -ENOTRECOVERABLE);
		goto out;
	}

	if (!ftl_nv_cache_phase_is_valid(hdr->phase)) {
	/* Remember the latest phase */
	nv_cache->phase = hdr->phase;

	/* If the phase equals zero, we lost power during recovery. We need to finish it up
	 * by scrubbing the device once again.
	 */
		if (hdr->phase != 0) {
			ftl_restore_complete(restore, -ENOTRECOVERABLE);
		} else {
	if (hdr->phase == 0) {
		SPDK_DEBUGLOG(SPDK_LOG_FTL_INIT, "Detected phase 0, restarting scrub\n");
		rc = ftl_nv_cache_scrub(nv_cache, ftl_nv_cache_scrub_cb, restore);
		if (spdk_unlikely(rc != 0)) {
@@ -932,13 +939,10 @@ ftl_nv_cache_read_header_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb
				    spdk_strerror(-rc));
			ftl_restore_complete(restore, -ENOTRECOVERABLE);
		}
		}

		goto out;
	}

	/* Remember the latest phase */
	nv_cache->phase = hdr->phase;
	restore->nv_cache.current_addr = FTL_NV_CACHE_DATA_OFFSET;

	for (i = 0; i < FTL_NV_CACHE_RESTORE_DEPTH; ++i) {