Commit 3ba5dd28 authored by Kozlowski Mateusz's avatar Kozlowski Mateusz Committed by Tomasz Zawadzki
Browse files

bdev/zone: Per zone information



Added zone specific information during initialization (starting LBA,
capacity etc.)

Signed-off-by: default avatarKozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: If0599960f0f872117691c801dce497649da20da6
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468034


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 214483e8
Loading
Loading
Loading
Loading
+56 −7
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@

#include "spdk/config.h"
#include "spdk/nvme.h"
#include "spdk/bdev_zone.h"

#include "spdk_internal/log.h"

@@ -70,10 +71,16 @@ struct bdev_zone_block_config {
};
static TAILQ_HEAD(, bdev_zone_block_config) g_bdev_configs = TAILQ_HEAD_INITIALIZER(g_bdev_configs);

struct block_zone {
	struct spdk_bdev_zone_info zone_info;
};

/* List of block vbdevs and associated info for each. */
struct bdev_zone_block {
	struct spdk_bdev		bdev;    /* the block zoned bdev */
	struct spdk_bdev_desc		*base_desc; /* its descriptor we get from open */
	struct block_zone		*zones; /* array of zones */
	uint64_t			num_zones; /* number of zones */
	uint64_t			zone_capacity; /* zone capacity */
	TAILQ_ENTRY(bdev_zone_block)	link;
};
@@ -148,6 +155,7 @@ _device_unregister_cb(void *io_device)
	struct bdev_zone_block *bdev_node  = io_device;

	free(bdev_node->bdev.name);
	free(bdev_node->zones);
	free(bdev_node);
}

@@ -297,11 +305,27 @@ zone_block_insert_name(const char *bdev_name, const char *vbdev_name, uint64_t z
	return 0;
}

static void
zone_block_init_zone_info(struct bdev_zone_block *bdev_node)
{
	size_t i;
	struct block_zone *zone;

	for (i = 0; i < bdev_node->num_zones; i++) {
		zone = &bdev_node->zones[i];
		zone->zone_info.zone_id = bdev_node->bdev.zone_size * i;
		zone->zone_info.capacity = bdev_node->zone_capacity;
		zone->zone_info.write_pointer = zone->zone_info.zone_id + zone->zone_info.capacity;
		zone->zone_info.state = SPDK_BDEV_ZONE_STATE_FULL;
	}
}

static int
zone_block_register(struct spdk_bdev *base_bdev)
{
	struct bdev_zone_block_config *name, *tmp;
	struct bdev_zone_block *bdev_node;
	uint64_t zone_size;
	int rc = 0;

	/* Check our list of names from config versus this bdev and if
@@ -332,14 +356,40 @@ zone_block_register(struct spdk_bdev *base_bdev)
			SPDK_ERRLOG("could not allocate bdev_node name\n");
			goto strdup_failed;
		}

		zone_size = spdk_align64pow2(name->zone_capacity);
		if (zone_size == 0) {
			rc = -EINVAL;
			SPDK_ERRLOG("invalid zone size\n");
			goto roundup_failed;
		}
		bdev_node->num_zones = base_bdev->blockcnt / zone_size;

		/* Align num_zones to optimal_open_zones */
		bdev_node->num_zones -= bdev_node->num_zones % name->optimal_open_zones;
		bdev_node->zones = calloc(bdev_node->num_zones, sizeof(struct block_zone));
		if (!bdev_node->zones) {
			rc = -ENOMEM;
			SPDK_ERRLOG("could not allocate zones\n");
			goto calloc_failed;
		}

		bdev_node->bdev.product_name = "zone_block";

		/* Copy some properties from the underlying base bdev. */
		bdev_node->bdev.write_cache = base_bdev->write_cache;
		bdev_node->bdev.required_alignment = base_bdev->required_alignment;
		bdev_node->bdev.optimal_io_boundary = base_bdev->optimal_io_boundary;

		bdev_node->bdev.blocklen = base_bdev->blocklen;
		bdev_node->bdev.blockcnt = base_bdev->blockcnt;
		bdev_node->bdev.blockcnt = bdev_node->num_zones * zone_size;

		if (bdev_node->num_zones * name->zone_capacity != base_bdev->blockcnt) {
			SPDK_DEBUGLOG(SPDK_LOG_VBDEV_ZONE_BLOCK,
				      "Lost %lu blocks due to zone capacity and base bdev size misalignment\n",
				      base_bdev->blockcnt - bdev_node->num_zones * name->zone_capacity);
		}

		bdev_node->bdev.write_unit_size = base_bdev->write_unit_size;

		bdev_node->bdev.md_interleave = base_bdev->md_interleave;
@@ -354,16 +404,13 @@ zone_block_register(struct spdk_bdev *base_bdev)
		bdev_node->bdev.module = &bdev_zoned_if;

		/* bdev specific info */
		bdev_node->bdev.zone_size = spdk_align64pow2(name->zone_capacity);
		if (bdev_node->bdev.zone_size == 0) {
			rc = -EINVAL;
			SPDK_ERRLOG("invalid zone size\n");
			goto roundup_failed;
		}
		bdev_node->bdev.zone_size = zone_size;

		bdev_node->zone_capacity = name->zone_capacity;
		bdev_node->bdev.optimal_open_zones = name->optimal_open_zones;
		bdev_node->bdev.max_open_zones = 0;
		zone_block_init_zone_info(bdev_node);

		TAILQ_INSERT_TAIL(&g_bdev_nodes, bdev_node, link);

		spdk_io_device_register(bdev_node, _zone_block_ch_create_cb, _zone_block_ch_destroy_cb,
@@ -399,6 +446,8 @@ claim_failed:
open_failed:
	TAILQ_REMOVE(&g_bdev_nodes, bdev_node, link);
	spdk_io_device_unregister(bdev_node, NULL);
	free(bdev_node->zones);
calloc_failed:
roundup_failed:
	free(bdev_node->bdev.name);
strdup_failed:
+21 −7
Original line number Diff line number Diff line
@@ -374,7 +374,7 @@ verify_zone_config(bool presence)
			}
			CU_ASSERT(strcmp(r->base_bdev, cfg->bdev_name) == 0);
			CU_ASSERT(r->zone_capacity == cfg->zone_capacity);
			CU_ASSERT(r->optimal_open_zones == cfg->optimal_open_zones);
			CU_ASSERT(spdk_max(r->optimal_open_zones, 1) == cfg->optimal_open_zones);
			break;
		}
	}
@@ -390,8 +390,12 @@ static void
verify_zone_bdev(bool presence)
{
	struct rpc_construct_zone_block *r = g_rpc_req;
	struct block_zone *zone;
	struct bdev_zone_block *bdev;
	bool bdev_found = false;
	uint32_t i;
	uint64_t expected_num_zones;
	uint64_t expected_optimal_open_zones;

	TAILQ_FOREACH(bdev, &g_bdev_nodes, link) {
		if (strcmp(bdev->bdev.name, r->name) == 0) {
@@ -400,17 +404,27 @@ verify_zone_bdev(bool presence)
				break;
			}

			expected_optimal_open_zones = spdk_max(r->optimal_open_zones, 1);
			expected_num_zones = BLOCK_CNT / spdk_align64pow2(r->zone_capacity) / expected_optimal_open_zones;
			expected_num_zones *= expected_optimal_open_zones;

			CU_ASSERT(bdev->num_zones == expected_num_zones);
			CU_ASSERT(bdev->bdev.zoned == true);
			CU_ASSERT(bdev->bdev.blockcnt == BLOCK_CNT);
			CU_ASSERT(bdev->bdev.blockcnt == expected_num_zones * spdk_align64pow2(r->zone_capacity));
			CU_ASSERT(bdev->bdev.blocklen == BLOCK_SIZE);
			CU_ASSERT(bdev->bdev.ctxt == bdev);
			CU_ASSERT(bdev->bdev.fn_table == &zone_block_fn_table);
			CU_ASSERT(bdev->bdev.module == &bdev_zoned_if);
			CU_ASSERT(bdev->bdev.write_unit_size == 1);
			CU_ASSERT(bdev->bdev.zone_size == spdk_align64pow2(r->zone_capacity));
			CU_ASSERT(bdev->bdev.optimal_open_zones == r->optimal_open_zones);
			CU_ASSERT(bdev->bdev.optimal_open_zones == expected_optimal_open_zones);
			CU_ASSERT(bdev->bdev.max_open_zones == 0);

			for (i = 0; i < bdev->num_zones; i++) {
				zone = &bdev->zones[i];
				CU_ASSERT(zone->zone_info.state == SPDK_BDEV_ZONE_STATE_FULL);
				CU_ASSERT(zone->zone_info.capacity == r->zone_capacity);
			}
			break;
		}
	}
@@ -458,7 +472,7 @@ test_zone_block_create(void)
{
	struct spdk_bdev *bdev;
	char *name = "Nvme0n1";
	size_t num_zones = 20;
	size_t num_zones = 16;
	size_t zone_capacity = BLOCK_CNT / num_zones;

	CU_ASSERT(zone_block_init() == 0);
@@ -492,7 +506,7 @@ static void
test_zone_block_create_invalid(void)
{
	char *name = "Nvme0n1";
	size_t num_zones = 10;
	size_t num_zones = 8;
	size_t zone_capacity = BLOCK_CNT / num_zones;

	CU_ASSERT(zone_block_init() == 0);
@@ -512,10 +526,10 @@ test_zone_block_create_invalid(void)
	send_delete_vbdev("zone_dev1", true);

	/* Try to create zoned virtual device with 0 zone size */
	send_create_vbdev("zone_dev2", name, 0, 1, false, false);
	send_create_vbdev("zone_dev1", name, 0, 1, false, false);

	/* Try to create zoned virtual device with 0 optimal number of zones */
	send_create_vbdev("zone_dev2", name, zone_capacity, 0, false, false);
	send_create_vbdev("zone_dev1", name, zone_capacity, 0, false, false);

	while (spdk_thread_poll(g_thread, 0, 0) > 0) {}
	test_cleanup();