bdev/zone: Per zone information

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

Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: If0599960f0f872117691c801dce497649da20da6
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468034
Tested-by: SPDK 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: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Kozlowski Mateusz 2020-01-07 07:06:48 -05:00 committed by Tomasz Zawadzki
parent 214483e834
commit 3ba5dd2852
2 changed files with 77 additions and 14 deletions

View File

@ -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:

View File

@ -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();