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:
parent
214483e834
commit
3ba5dd2852
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include "spdk/config.h"
|
#include "spdk/config.h"
|
||||||
#include "spdk/nvme.h"
|
#include "spdk/nvme.h"
|
||||||
|
#include "spdk/bdev_zone.h"
|
||||||
|
|
||||||
#include "spdk_internal/log.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);
|
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. */
|
/* List of block vbdevs and associated info for each. */
|
||||||
struct bdev_zone_block {
|
struct bdev_zone_block {
|
||||||
struct spdk_bdev bdev; /* the block zoned bdev */
|
struct spdk_bdev bdev; /* the block zoned bdev */
|
||||||
struct spdk_bdev_desc *base_desc; /* its descriptor we get from open */
|
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 */
|
uint64_t zone_capacity; /* zone capacity */
|
||||||
TAILQ_ENTRY(bdev_zone_block) link;
|
TAILQ_ENTRY(bdev_zone_block) link;
|
||||||
};
|
};
|
||||||
@ -148,6 +155,7 @@ _device_unregister_cb(void *io_device)
|
|||||||
struct bdev_zone_block *bdev_node = io_device;
|
struct bdev_zone_block *bdev_node = io_device;
|
||||||
|
|
||||||
free(bdev_node->bdev.name);
|
free(bdev_node->bdev.name);
|
||||||
|
free(bdev_node->zones);
|
||||||
free(bdev_node);
|
free(bdev_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,11 +305,27 @@ zone_block_insert_name(const char *bdev_name, const char *vbdev_name, uint64_t z
|
|||||||
return 0;
|
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
|
static int
|
||||||
zone_block_register(struct spdk_bdev *base_bdev)
|
zone_block_register(struct spdk_bdev *base_bdev)
|
||||||
{
|
{
|
||||||
struct bdev_zone_block_config *name, *tmp;
|
struct bdev_zone_block_config *name, *tmp;
|
||||||
struct bdev_zone_block *bdev_node;
|
struct bdev_zone_block *bdev_node;
|
||||||
|
uint64_t zone_size;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/* Check our list of names from config versus this bdev and if
|
/* 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");
|
SPDK_ERRLOG("could not allocate bdev_node name\n");
|
||||||
goto strdup_failed;
|
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";
|
bdev_node->bdev.product_name = "zone_block";
|
||||||
|
|
||||||
/* Copy some properties from the underlying base bdev. */
|
/* Copy some properties from the underlying base bdev. */
|
||||||
bdev_node->bdev.write_cache = base_bdev->write_cache;
|
bdev_node->bdev.write_cache = base_bdev->write_cache;
|
||||||
bdev_node->bdev.required_alignment = base_bdev->required_alignment;
|
bdev_node->bdev.required_alignment = base_bdev->required_alignment;
|
||||||
bdev_node->bdev.optimal_io_boundary = base_bdev->optimal_io_boundary;
|
bdev_node->bdev.optimal_io_boundary = base_bdev->optimal_io_boundary;
|
||||||
|
|
||||||
bdev_node->bdev.blocklen = base_bdev->blocklen;
|
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.write_unit_size = base_bdev->write_unit_size;
|
||||||
|
|
||||||
bdev_node->bdev.md_interleave = base_bdev->md_interleave;
|
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_node->bdev.module = &bdev_zoned_if;
|
||||||
|
|
||||||
/* bdev specific info */
|
/* bdev specific info */
|
||||||
bdev_node->bdev.zone_size = spdk_align64pow2(name->zone_capacity);
|
bdev_node->bdev.zone_size = zone_size;
|
||||||
if (bdev_node->bdev.zone_size == 0) {
|
|
||||||
rc = -EINVAL;
|
|
||||||
SPDK_ERRLOG("invalid zone size\n");
|
|
||||||
goto roundup_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bdev_node->zone_capacity = name->zone_capacity;
|
bdev_node->zone_capacity = name->zone_capacity;
|
||||||
bdev_node->bdev.optimal_open_zones = name->optimal_open_zones;
|
bdev_node->bdev.optimal_open_zones = name->optimal_open_zones;
|
||||||
bdev_node->bdev.max_open_zones = 0;
|
bdev_node->bdev.max_open_zones = 0;
|
||||||
|
zone_block_init_zone_info(bdev_node);
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&g_bdev_nodes, bdev_node, link);
|
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,
|
spdk_io_device_register(bdev_node, _zone_block_ch_create_cb, _zone_block_ch_destroy_cb,
|
||||||
@ -399,6 +446,8 @@ claim_failed:
|
|||||||
open_failed:
|
open_failed:
|
||||||
TAILQ_REMOVE(&g_bdev_nodes, bdev_node, link);
|
TAILQ_REMOVE(&g_bdev_nodes, bdev_node, link);
|
||||||
spdk_io_device_unregister(bdev_node, NULL);
|
spdk_io_device_unregister(bdev_node, NULL);
|
||||||
|
free(bdev_node->zones);
|
||||||
|
calloc_failed:
|
||||||
roundup_failed:
|
roundup_failed:
|
||||||
free(bdev_node->bdev.name);
|
free(bdev_node->bdev.name);
|
||||||
strdup_failed:
|
strdup_failed:
|
||||||
|
@ -374,7 +374,7 @@ verify_zone_config(bool presence)
|
|||||||
}
|
}
|
||||||
CU_ASSERT(strcmp(r->base_bdev, cfg->bdev_name) == 0);
|
CU_ASSERT(strcmp(r->base_bdev, cfg->bdev_name) == 0);
|
||||||
CU_ASSERT(r->zone_capacity == cfg->zone_capacity);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,8 +390,12 @@ static void
|
|||||||
verify_zone_bdev(bool presence)
|
verify_zone_bdev(bool presence)
|
||||||
{
|
{
|
||||||
struct rpc_construct_zone_block *r = g_rpc_req;
|
struct rpc_construct_zone_block *r = g_rpc_req;
|
||||||
|
struct block_zone *zone;
|
||||||
struct bdev_zone_block *bdev;
|
struct bdev_zone_block *bdev;
|
||||||
bool bdev_found = false;
|
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) {
|
TAILQ_FOREACH(bdev, &g_bdev_nodes, link) {
|
||||||
if (strcmp(bdev->bdev.name, r->name) == 0) {
|
if (strcmp(bdev->bdev.name, r->name) == 0) {
|
||||||
@ -400,17 +404,27 @@ verify_zone_bdev(bool presence)
|
|||||||
break;
|
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.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.blocklen == BLOCK_SIZE);
|
||||||
CU_ASSERT(bdev->bdev.ctxt == bdev);
|
CU_ASSERT(bdev->bdev.ctxt == bdev);
|
||||||
CU_ASSERT(bdev->bdev.fn_table == &zone_block_fn_table);
|
CU_ASSERT(bdev->bdev.fn_table == &zone_block_fn_table);
|
||||||
CU_ASSERT(bdev->bdev.module == &bdev_zoned_if);
|
CU_ASSERT(bdev->bdev.module == &bdev_zoned_if);
|
||||||
CU_ASSERT(bdev->bdev.write_unit_size == 1);
|
CU_ASSERT(bdev->bdev.write_unit_size == 1);
|
||||||
CU_ASSERT(bdev->bdev.zone_size == spdk_align64pow2(r->zone_capacity));
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,7 +472,7 @@ test_zone_block_create(void)
|
|||||||
{
|
{
|
||||||
struct spdk_bdev *bdev;
|
struct spdk_bdev *bdev;
|
||||||
char *name = "Nvme0n1";
|
char *name = "Nvme0n1";
|
||||||
size_t num_zones = 20;
|
size_t num_zones = 16;
|
||||||
size_t zone_capacity = BLOCK_CNT / num_zones;
|
size_t zone_capacity = BLOCK_CNT / num_zones;
|
||||||
|
|
||||||
CU_ASSERT(zone_block_init() == 0);
|
CU_ASSERT(zone_block_init() == 0);
|
||||||
@ -492,7 +506,7 @@ static void
|
|||||||
test_zone_block_create_invalid(void)
|
test_zone_block_create_invalid(void)
|
||||||
{
|
{
|
||||||
char *name = "Nvme0n1";
|
char *name = "Nvme0n1";
|
||||||
size_t num_zones = 10;
|
size_t num_zones = 8;
|
||||||
size_t zone_capacity = BLOCK_CNT / num_zones;
|
size_t zone_capacity = BLOCK_CNT / num_zones;
|
||||||
|
|
||||||
CU_ASSERT(zone_block_init() == 0);
|
CU_ASSERT(zone_block_init() == 0);
|
||||||
@ -512,10 +526,10 @@ test_zone_block_create_invalid(void)
|
|||||||
send_delete_vbdev("zone_dev1", true);
|
send_delete_vbdev("zone_dev1", true);
|
||||||
|
|
||||||
/* Try to create zoned virtual device with 0 zone size */
|
/* 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 */
|
/* 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) {}
|
while (spdk_thread_poll(g_thread, 0, 0) > 0) {}
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
|
Loading…
Reference in New Issue
Block a user