diff --git a/module/bdev/nvme/bdev_ocssd.c b/module/bdev/nvme/bdev_ocssd.c index c8295f8dd..ed0262ae9 100644 --- a/module/bdev/nvme/bdev_ocssd.c +++ b/module/bdev/nvme/bdev_ocssd.c @@ -37,6 +37,7 @@ #include "spdk/likely.h" #include "spdk/log.h" #include "spdk/string.h" +#include "spdk/util.h" #include "spdk/nvme_ocssd.h" #include "spdk/nvme_ocssd_spec.h" #include "spdk_internal/log.h" @@ -51,6 +52,13 @@ struct bdev_ocssd_lba_offsets { uint32_t lbk; }; +struct bdev_ocssd_zone { + uint64_t slba; + uint64_t write_pointer; + uint64_t capacity; + bool busy; +}; + struct bdev_ocssd_io { union { struct { @@ -66,7 +74,8 @@ struct bdev_ocssd_io { }; struct ocssd_bdev { - struct nvme_bdev nvme_bdev; + struct nvme_bdev nvme_bdev; + struct bdev_ocssd_zone *zones; }; struct bdev_ocssd_ns { @@ -126,6 +135,7 @@ bdev_ocssd_free_bdev(struct ocssd_bdev *ocssd_bdev) return; } + free(ocssd_bdev->zones); free(ocssd_bdev->nvme_bdev.disk.name); free(ocssd_bdev); } @@ -558,11 +568,173 @@ static struct spdk_bdev_fn_table ocssdlib_fn_table = { .get_io_channel = bdev_ocssd_get_io_channel, }; +struct bdev_ocssd_create_ctx { + struct ocssd_bdev *ocssd_bdev; + bdev_ocssd_create_cb cb_fn; + void *cb_arg; + uint64_t chunk_offset; + uint64_t num_total_chunks; + uint64_t num_chunks; +#define OCSSD_BDEV_CHUNK_INFO_COUNT 128 + struct spdk_ocssd_chunk_information_entry chunk_info[OCSSD_BDEV_CHUNK_INFO_COUNT]; +}; + +static void +bdev_ocssd_create_complete(struct bdev_ocssd_create_ctx *create_ctx, int status) +{ + const char *bdev_name = create_ctx->ocssd_bdev->nvme_bdev.disk.name; + + if (spdk_unlikely(status != 0)) { + bdev_ocssd_free_bdev(create_ctx->ocssd_bdev); + } + + create_ctx->cb_fn(bdev_name, status, create_ctx->cb_arg); + free(create_ctx); +} + +static struct bdev_ocssd_zone * +bdev_ocssd_get_zone_by_slba(struct ocssd_bdev *ocssd_bdev, uint64_t slba) +{ + struct nvme_bdev *nvme_bdev = &ocssd_bdev->nvme_bdev; + size_t zone_size = nvme_bdev->disk.zone_size; + + if (slba % zone_size != 0) { + return NULL; + } + + if (slba >= nvme_bdev->disk.blockcnt) { + return NULL; + } + + return &ocssd_bdev->zones[slba / zone_size]; +} + +static int bdev_ocssd_init_zone(struct bdev_ocssd_create_ctx *create_ctx); + +static void +bdev_ocssd_register_bdev(void *ctx) +{ + struct bdev_ocssd_create_ctx *create_ctx = ctx; + struct ocssd_bdev *ocssd_bdev = create_ctx->ocssd_bdev; + struct nvme_bdev *nvme_bdev = &ocssd_bdev->nvme_bdev; + int rc; + + rc = spdk_bdev_register(&nvme_bdev->disk); + if (spdk_likely(rc == 0)) { + nvme_bdev_attach_bdev_to_ns(nvme_bdev->nvme_ns, nvme_bdev); + } else { + SPDK_ERRLOG("Failed to register bdev %s\n", nvme_bdev->disk.name); + } + + bdev_ocssd_create_complete(create_ctx, rc); +} + +static void +bdev_occsd_init_zone_cb(void *ctx, const struct spdk_nvme_cpl *cpl) +{ + struct bdev_ocssd_create_ctx *create_ctx = ctx; + struct bdev_ocssd_zone *ocssd_zone; + struct ocssd_bdev *ocssd_bdev = create_ctx->ocssd_bdev; + struct spdk_bdev_zone_info zone_info = {}; + uint64_t offset; + int rc = 0; + + if (spdk_nvme_cpl_is_error(cpl)) { + SPDK_ERRLOG("Chunk information log page failed\n"); + bdev_ocssd_create_complete(create_ctx, -EIO); + return; + } + + for (offset = 0; offset < create_ctx->num_chunks; ++offset) { + bdev_ocssd_fill_zone_info(ocssd_bdev, &zone_info, &create_ctx->chunk_info[offset]); + + ocssd_zone = bdev_ocssd_get_zone_by_slba(ocssd_bdev, zone_info.zone_id); + if (!ocssd_zone) { + SPDK_ERRLOG("Received invalid zone starting LBA: %"PRIu64"\n", + zone_info.zone_id); + bdev_ocssd_create_complete(create_ctx, -EINVAL); + return; + } + + /* Make sure we're not filling the same zone twice */ + assert(ocssd_zone->busy); + + ocssd_zone->busy = false; + ocssd_zone->slba = zone_info.zone_id; + ocssd_zone->capacity = zone_info.capacity; + ocssd_zone->write_pointer = zone_info.write_pointer; + } + + create_ctx->chunk_offset += create_ctx->num_chunks; + if (create_ctx->chunk_offset < create_ctx->num_total_chunks) { + rc = bdev_ocssd_init_zone(create_ctx); + if (spdk_unlikely(rc != 0)) { + SPDK_ERRLOG("Failed to send chunk info log page\n"); + bdev_ocssd_create_complete(create_ctx, rc); + } + } else { + /* Make sure all zones have been processed */ + for (offset = 0; offset < create_ctx->num_total_chunks; ++offset) { + assert(!ocssd_bdev->zones[offset].busy); + } + + /* Schedule the last bit of work (io_device, bdev registration) to be done in a + * context that is not tied to admin command's completion callback. + */ + spdk_thread_send_msg(spdk_get_thread(), bdev_ocssd_register_bdev, create_ctx); + } +} + +static int +bdev_ocssd_init_zone(struct bdev_ocssd_create_ctx *create_ctx) +{ + struct ocssd_bdev *ocssd_bdev = create_ctx->ocssd_bdev; + struct nvme_bdev *nvme_bdev = &ocssd_bdev->nvme_bdev; + + create_ctx->num_chunks = spdk_min(create_ctx->num_total_chunks - create_ctx->chunk_offset, + OCSSD_BDEV_CHUNK_INFO_COUNT); + assert(create_ctx->num_chunks > 0); + + return spdk_nvme_ctrlr_cmd_get_log_page(nvme_bdev->nvme_bdev_ctrlr->ctrlr, + SPDK_OCSSD_LOG_CHUNK_INFO, + spdk_nvme_ns_get_id(nvme_bdev->nvme_ns->ns), + &create_ctx->chunk_info, + sizeof(create_ctx->chunk_info[0]) * + create_ctx->num_chunks, + sizeof(create_ctx->chunk_info[0]) * + create_ctx->chunk_offset, + bdev_occsd_init_zone_cb, create_ctx); +} + +static int +bdev_ocssd_init_zones(struct bdev_ocssd_create_ctx *create_ctx) +{ + struct ocssd_bdev *ocssd_bdev = create_ctx->ocssd_bdev; + struct spdk_bdev *bdev = &ocssd_bdev->nvme_bdev.disk; + uint64_t offset; + + ocssd_bdev->zones = calloc(bdev->blockcnt / bdev->zone_size, sizeof(*ocssd_bdev->zones)); + if (!ocssd_bdev->zones) { + return -ENOMEM; + } + + create_ctx->num_total_chunks = bdev->blockcnt / bdev->zone_size; + create_ctx->chunk_offset = 0; + + /* Mark all zones as busy and clear it as their info is filled */ + for (offset = 0; offset < create_ctx->num_total_chunks; ++offset) { + ocssd_bdev->zones[offset].busy = true; + } + + return bdev_ocssd_init_zone(create_ctx); +} + void bdev_ocssd_create_bdev(const char *ctrlr_name, const char *bdev_name, uint32_t nsid, bdev_ocssd_create_cb cb_fn, void *cb_arg) { struct nvme_bdev_ctrlr *nvme_bdev_ctrlr; + struct bdev_ocssd_create_ctx *create_ctx = NULL; struct nvme_bdev *nvme_bdev = NULL; struct ocssd_bdev *ocssd_bdev = NULL; struct spdk_nvme_ns *ns; @@ -575,20 +747,20 @@ bdev_ocssd_create_bdev(const char *ctrlr_name, const char *bdev_name, uint32_t n if (!nvme_bdev_ctrlr) { SPDK_ERRLOG("Unable to find controller %s\n", ctrlr_name); rc = -ENODEV; - goto finish; + goto error; } ns = spdk_nvme_ctrlr_get_ns(nvme_bdev_ctrlr->ctrlr, nsid); if (!ns) { SPDK_ERRLOG("Unable to retrieve namespace %"PRIu32"\n", nsid); rc = -ENODEV; - goto finish; + goto error; } if (!spdk_nvme_ns_is_active(ns)) { SPDK_ERRLOG("Namespace %"PRIu32" is inactive\n", nsid); rc = -EACCES; - goto finish; + goto error; } assert(nsid <= nvme_bdev_ctrlr->num_ns); @@ -596,20 +768,20 @@ bdev_ocssd_create_bdev(const char *ctrlr_name, const char *bdev_name, uint32_t n if (nvme_ns == NULL) { SPDK_ERRLOG("Namespace %"PRIu32" is not initialized\n", nsid); rc = -EINVAL; - goto finish; + goto error; } ocssd_ns = bdev_ocssd_get_ns_from_nvme(nvme_ns); if (ocssd_ns == NULL) { SPDK_ERRLOG("Namespace %"PRIu32" is not an OCSSD namespace\n", nsid); rc = -EINVAL; - goto finish; + goto error; } if (spdk_bdev_get_by_name(bdev_name) != NULL) { SPDK_ERRLOG("Device with provided name (%s) already exists\n", bdev_name); rc = -EEXIST; - goto finish; + goto error; } /* Only allow one bdev per namespace for now */ @@ -617,15 +789,25 @@ bdev_ocssd_create_bdev(const char *ctrlr_name, const char *bdev_name, uint32_t n SPDK_ERRLOG("Namespace %"PRIu32" was already claimed by bdev %s\n", nsid, TAILQ_FIRST(&nvme_ns->bdevs)->disk.name); rc = -EEXIST; - goto finish; + goto error; } ocssd_bdev = calloc(1, sizeof(*ocssd_bdev)); if (!ocssd_bdev) { rc = -ENOMEM; - goto finish; + goto error; } + create_ctx = calloc(1, sizeof(*create_ctx)); + if (!create_ctx) { + rc = -ENOMEM; + goto error; + } + + create_ctx->ocssd_bdev = ocssd_bdev; + create_ctx->cb_fn = cb_fn; + create_ctx->cb_arg = cb_arg; + nvme_bdev = &ocssd_bdev->nvme_bdev; nvme_bdev->nvme_ns = nvme_ns; nvme_bdev->nvme_bdev_ctrlr = nvme_bdev_ctrlr; @@ -634,7 +816,7 @@ bdev_ocssd_create_bdev(const char *ctrlr_name, const char *bdev_name, uint32_t n nvme_bdev->disk.name = strdup(bdev_name); if (!nvme_bdev->disk.name) { rc = -ENOMEM; - goto finish; + goto error; } nvme_bdev->disk.product_name = "Open Channel SSD"; @@ -657,20 +839,17 @@ bdev_ocssd_create_bdev(const char *ctrlr_name, const char *bdev_name, uint32_t n nvme_bdev->disk.max_open_zones = geometry->maxocpu; } - rc = spdk_bdev_register(&nvme_bdev->disk); + rc = bdev_ocssd_init_zones(create_ctx); if (spdk_unlikely(rc != 0)) { - SPDK_ERRLOG("Failed to register bdev %s\n", nvme_bdev->disk.name); - goto finish; + SPDK_ERRLOG("Failed to initialize zones on bdev %s\n", nvme_bdev->disk.name); + goto error; } - nvme_bdev_attach_bdev_to_ns(nvme_ns, nvme_bdev); -finish: - if (spdk_unlikely(rc != 0)) { - bdev_ocssd_free_bdev(ocssd_bdev); - bdev_name = NULL; - } - - cb_fn(bdev_name, rc, cb_arg); + return; +error: + bdev_ocssd_free_bdev(ocssd_bdev); + cb_fn(NULL, rc, cb_arg); + free(create_ctx); } struct bdev_ocssd_delete_ctx { diff --git a/test/unit/lib/bdev/bdev_ocssd.c/bdev_ocssd_ut.c b/test/unit/lib/bdev/bdev_ocssd.c/bdev_ocssd_ut.c index 62e020e16..525b781b6 100644 --- a/test/unit/lib/bdev/bdev_ocssd.c/bdev_ocssd_ut.c +++ b/test/unit/lib/bdev/bdev_ocssd.c/bdev_ocssd_ut.c @@ -108,12 +108,31 @@ free_controller(struct spdk_nvme_ctrlr *ctrlr) free(ctrlr); } +static uint64_t +chunk_offset_to_lba(struct spdk_ocssd_geometry_data *geo, uint64_t offset) +{ + uint64_t chk, pu, grp; + uint64_t chk_off, pu_off, grp_off; + + chk_off = geo->lbaf.lbk_len; + pu_off = geo->lbaf.chk_len + chk_off; + grp_off = geo->lbaf.pu_len + pu_off; + + chk = offset % geo->num_chk; + pu = (offset / geo->num_chk) % geo->num_pu; + grp = (offset / (geo->num_chk * geo->num_pu)) % geo->num_grp; + + return chk << chk_off | + pu << pu_off | + grp << grp_off; +} + static struct spdk_nvme_ctrlr * create_controller(const struct spdk_nvme_transport_id *trid, uint32_t ns_count, const struct spdk_ocssd_geometry_data *geo) { struct spdk_nvme_ctrlr *ctrlr; - uint32_t nsid; + uint32_t nsid, offset; SPDK_CU_ASSERT_FATAL(!find_controller(trid)); @@ -135,6 +154,13 @@ create_controller(const struct spdk_nvme_transport_id *trid, uint32_t ns_count, ctrlr->trid = *trid; ctrlr->ns_count = ns_count; ctrlr->admin_qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0); + + for (offset = 0; offset < ctrlr->num_chunks; ++offset) { + ctrlr->chunk_info[offset].cs.free = 1; + ctrlr->chunk_info[offset].slba = chunk_offset_to_lba(&ctrlr->geometry, offset); + ctrlr->chunk_info[offset].wp = ctrlr->chunk_info[offset].slba; + } + SPDK_CU_ASSERT_FATAL(ctrlr->admin_qpair != NULL); LIST_INSERT_HEAD(&g_ctrlr_list, ctrlr, list); @@ -460,10 +486,12 @@ create_bdev_cb(const char *bdev_name, int status, void *ctx) static int create_bdev(const char *ctrlr_name, const char *bdev_name, uint32_t nsid) { - int status; + int status = EFAULT; bdev_ocssd_create_bdev(ctrlr_name, bdev_name, nsid, create_bdev_cb, &status); + while (spdk_thread_poll(g_thread, 0, 0) > 0) {} + return status; } @@ -514,6 +542,22 @@ test_create_controller(void) uint32_t nsid; int rc; + geometry = (struct spdk_ocssd_geometry_data) { + .clba = 512, + .num_chk = 64, + .num_pu = 8, + .num_grp = 4, + .maxoc = 69, + .maxocpu = 68, + .ws_opt = 86, + .lbaf = { + .lbk_len = 9, + .chk_len = 6, + .pu_len = 3, + .grp_len = 2, + } + }; + ctrlr = create_controller(&trid, ns_count, &geometry); nvme_bdev_ctrlr = create_nvme_bdev_controller(&trid, controller_name); @@ -575,6 +619,12 @@ test_device_geometry(void) .maxoc = 69, .maxocpu = 68, .ws_opt = 86, + .lbaf = { + .lbk_len = 9, + .chk_len = 6, + .pu_len = 3, + .grp_len = 2, + } }; ctrlr = create_controller(&trid, 1, &geometry); @@ -764,19 +814,41 @@ alloc_ocssd_io(void) return bdev_io; } -static void -set_chunk_info(struct spdk_nvme_ctrlr *ctrlr, uint64_t offset, - const struct spdk_ocssd_chunk_information_entry *chunk_info) +static struct spdk_ocssd_chunk_information_entry * +get_chunk_info(struct spdk_nvme_ctrlr *ctrlr, uint64_t offset) { assert(offset < ctrlr->num_chunks); SPDK_CU_ASSERT_FATAL(offset < ctrlr->num_chunks); - ctrlr->chunk_info[offset] = *chunk_info; + return &ctrlr->chunk_info[offset]; } +enum chunk_state { + CHUNK_STATE_FREE, + CHUNK_STATE_CLOSED, + CHUNK_STATE_OPEN, + CHUNK_STATE_OFFLINE +}; + static void -clear_chunk_info(struct spdk_nvme_ctrlr *ctrlr) +set_chunk_state(struct spdk_ocssd_chunk_information_entry *chunk, enum chunk_state state) { - memset(ctrlr->chunk_info, 0, sizeof(*ctrlr->chunk_info) * ctrlr->num_chunks); + memset(&chunk->cs, 0, sizeof(chunk->cs)); + switch (state) { + case CHUNK_STATE_FREE: + chunk->cs.free = 1; + break; + case CHUNK_STATE_CLOSED: + chunk->cs.closed = 1; + break; + case CHUNK_STATE_OPEN: + chunk->cs.open = 1; + break; + case CHUNK_STATE_OFFLINE: + chunk->cs.offline = 1; + break; + default: + SPDK_CU_ASSERT_FATAL(0 && "Invalid state"); + } } static void @@ -785,14 +857,13 @@ test_get_zone_info(void) struct spdk_nvme_ctrlr *ctrlr; struct nvme_bdev_ctrlr *nvme_bdev_ctrlr; struct spdk_nvme_transport_id trid = { .traddr = "00:00:00" }; - struct ocssd_bdev *ocssd_bdev; const char *controller_name = "nvme0"; const char *bdev_name = "nvme0n1"; struct spdk_bdev *bdev; struct spdk_bdev_io *bdev_io; #define MAX_ZONE_INFO_COUNT 64 struct spdk_bdev_zone_info zone_info[MAX_ZONE_INFO_COUNT]; - struct spdk_ocssd_chunk_information_entry chunk_info = {}; + struct spdk_ocssd_chunk_information_entry *chunk_info; struct spdk_ocssd_geometry_data geometry; uint64_t chunk_offset; int rc, offset; @@ -818,7 +889,6 @@ test_get_zone_info(void) bdev = spdk_bdev_get_by_name(bdev_name); SPDK_CU_ASSERT_FATAL(bdev != NULL); - ocssd_bdev = SPDK_CONTAINEROF(bdev, struct ocssd_bdev, nvme_bdev.disk); bdev_io = alloc_ocssd_io(); bdev_io->internal.cb = get_zone_info_cb; @@ -828,13 +898,12 @@ test_get_zone_info(void) bdev_io->u.zone_mgmt.zone_id = 0; bdev_io->u.zone_mgmt.num_zones = 1; bdev_io->u.zone_mgmt.buf = &zone_info; - chunk_info.cs.free = 1; - chunk_info.wp = 0; - set_chunk_info(ctrlr, 0, &chunk_info); + chunk_info = get_chunk_info(ctrlr, 0); + set_chunk_state(chunk_info, CHUNK_STATE_FREE); + chunk_info->wp = 0; rc = bdev_ocssd_get_zone_info(NULL, bdev_io); CU_ASSERT_EQUAL(rc, 0); - clear_chunk_info(ctrlr); CU_ASSERT_EQUAL(zone_info[0].state, SPDK_BDEV_ZONE_STATE_EMPTY); CU_ASSERT_EQUAL(zone_info[0].zone_id, 0); @@ -845,36 +914,30 @@ test_get_zone_info(void) bdev_io->u.zone_mgmt.zone_id = bdev->zone_size; bdev_io->u.zone_mgmt.num_zones = 1; bdev_io->u.zone_mgmt.buf = &zone_info; - memset(&chunk_info, 0, sizeof(chunk_info)); - chunk_info.cs.open = 1; - chunk_info.wp = bdev_ocssd_to_disk_lba(ocssd_bdev, bdev_io->u.zone_mgmt.zone_id + 68); - chunk_info.slba = bdev_ocssd_to_disk_lba(ocssd_bdev, bdev_io->u.zone_mgmt.zone_id); - chunk_info.cnlb = 511; - chunk_info.ct.size_deviate = 1; - set_chunk_info(ctrlr, generate_chunk_offset(&geometry, 0, 1, 0), &chunk_info); + chunk_info = get_chunk_info(ctrlr, generate_chunk_offset(&geometry, 0, 1, 0)); + set_chunk_state(chunk_info, CHUNK_STATE_OPEN); + chunk_info->wp = chunk_info->slba + 68; + chunk_info->cnlb = 511; + chunk_info->ct.size_deviate = 1; rc = bdev_ocssd_get_zone_info(NULL, bdev_io); CU_ASSERT_EQUAL(rc, 0); - clear_chunk_info(ctrlr); CU_ASSERT_EQUAL(zone_info[0].state, SPDK_BDEV_ZONE_STATE_OPEN); CU_ASSERT_EQUAL(zone_info[0].zone_id, bdev->zone_size); CU_ASSERT_EQUAL(zone_info[0].write_pointer, bdev->zone_size + 68); - CU_ASSERT_EQUAL(zone_info[0].capacity, chunk_info.cnlb); + CU_ASSERT_EQUAL(zone_info[0].capacity, chunk_info->cnlb); /* Verify offline zone at 2nd chunk */ bdev_io->u.zone_mgmt.zone_id = bdev->zone_size * geometry.num_pu * geometry.num_grp; bdev_io->u.zone_mgmt.num_zones = 1; bdev_io->u.zone_mgmt.buf = &zone_info; - memset(&chunk_info, 0, sizeof(chunk_info)); - chunk_info.cs.offline = 1; - chunk_info.wp = bdev_ocssd_to_disk_lba(ocssd_bdev, bdev_io->u.zone_mgmt.zone_id); - chunk_info.slba = bdev_ocssd_to_disk_lba(ocssd_bdev, bdev_io->u.zone_mgmt.zone_id); - set_chunk_info(ctrlr, generate_chunk_offset(&geometry, 1, 0, 0), &chunk_info); + chunk_info = get_chunk_info(ctrlr, generate_chunk_offset(&geometry, 1, 0, 0)); + set_chunk_state(chunk_info, CHUNK_STATE_OFFLINE); + chunk_info->wp = chunk_info->slba; rc = bdev_ocssd_get_zone_info(NULL, bdev_io); CU_ASSERT_EQUAL(rc, 0); - clear_chunk_info(ctrlr); CU_ASSERT_EQUAL(zone_info[0].state, SPDK_BDEV_ZONE_STATE_OFFLINE); CU_ASSERT_EQUAL(zone_info[0].zone_id, bdev_io->u.zone_mgmt.zone_id); @@ -892,11 +955,10 @@ test_get_zone_info(void) (offset / geometry.num_pu) % geometry.num_grp); - memset(&chunk_info, 0, sizeof(chunk_info)); - chunk_info.cs.open = 1; - chunk_info.wp = bdev_ocssd_to_disk_lba(ocssd_bdev, offset * bdev->zone_size + 68); - chunk_info.slba = bdev_ocssd_to_disk_lba(ocssd_bdev, offset * bdev->zone_size); - set_chunk_info(ctrlr, chunk_offset, &chunk_info); + chunk_info = get_chunk_info(ctrlr, chunk_offset); + set_chunk_state(chunk_info, CHUNK_STATE_OPEN); + chunk_info->wp = chunk_info->slba + 68; + chunk_info->ct.size_deviate = 0; } rc = bdev_ocssd_get_zone_info(NULL, bdev_io); @@ -909,8 +971,6 @@ test_get_zone_info(void) CU_ASSERT_EQUAL(zone_info[offset].capacity, geometry.clba); } - clear_chunk_info(ctrlr); - /* Verify misaligned start zone LBA */ bdev_io->u.zone_mgmt.zone_id = 1; bdev_io->u.zone_mgmt.num_zones = MAX_ZONE_INFO_COUNT; @@ -923,6 +983,8 @@ test_get_zone_info(void) bdev_io->u.zone_mgmt.zone_id = 0; bdev_io->u.zone_mgmt.num_zones = MAX_ZONE_INFO_COUNT; bdev_io->u.zone_mgmt.buf = &zone_info; + chunk_info = get_chunk_info(ctrlr, 0); + set_chunk_state(chunk_info, CHUNK_STATE_FREE); rc = bdev_ocssd_get_zone_info(NULL, bdev_io); CU_ASSERT_EQUAL(rc, 0);