From 68c3a79a158bd1bd6e8797b9bd7eed6a7012696c Mon Sep 17 00:00:00 2001 From: Mateusz Kozlowski Date: Fri, 13 Sep 2019 16:15:31 +0200 Subject: [PATCH] bdev/zone: Add finish zone handling to zoned vbdev Handle finish zone management function to zoned block vbdev Signed-off-by: Mateusz Kozlowski Change-Id: Iffe24572609e741a79b6bb92f72b56cede4906ca Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468041 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris Reviewed-by: Konrad Sztyber --- module/bdev/zone_block/vbdev_zone_block.c | 15 ++++ .../vbdev_zone_block.c/vbdev_zone_block_ut.c | 70 ++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/module/bdev/zone_block/vbdev_zone_block.c b/module/bdev/zone_block/vbdev_zone_block.c index 51f628f36f..46dc47bb0f 100644 --- a/module/bdev/zone_block/vbdev_zone_block.c +++ b/module/bdev/zone_block/vbdev_zone_block.c @@ -307,6 +307,19 @@ zone_block_close_zone(struct block_zone *zone, struct spdk_bdev_io *bdev_io) } } +static int +zone_block_finish_zone(struct block_zone *zone, struct spdk_bdev_io *bdev_io) +{ + pthread_spin_lock(&zone->lock); + + zone->zone_info.write_pointer = zone->zone_info.zone_id + zone->zone_info.capacity; + zone->zone_info.state = SPDK_BDEV_ZONE_STATE_FULL; + + pthread_spin_unlock(&zone->lock); + spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); + return 0; +} + static int zone_block_zone_management(struct bdev_zone_block *bdev_node, struct zone_block_io_channel *ch, struct spdk_bdev_io *bdev_io) @@ -325,6 +338,8 @@ zone_block_zone_management(struct bdev_zone_block *bdev_node, struct zone_block_ return zone_block_open_zone(zone, bdev_io); case SPDK_BDEV_ZONE_CLOSE: return zone_block_close_zone(zone, bdev_io); + case SPDK_BDEV_ZONE_FINISH: + return zone_block_finish_zone(zone, bdev_io); default: return -EINVAL; } diff --git a/test/unit/lib/bdev/vbdev_zone_block.c/vbdev_zone_block_ut.c b/test/unit/lib/bdev/vbdev_zone_block.c/vbdev_zone_block_ut.c index 373b3ab394..cfbc7b88e9 100644 --- a/test/unit/lib/bdev/vbdev_zone_block.c/vbdev_zone_block_ut.c +++ b/test/unit/lib/bdev/vbdev_zone_block.c/vbdev_zone_block_ut.c @@ -948,6 +948,13 @@ send_close_zone(struct bdev_zone_block *bdev, struct spdk_io_channel *ch, uint64 send_zone_management(bdev, ch, zone_id, output_index, SPDK_BDEV_ZONE_CLOSE, success); } +static void +send_finish_zone(struct bdev_zone_block *bdev, struct spdk_io_channel *ch, uint64_t zone_id, + uint32_t output_index, bool success) +{ + send_zone_management(bdev, ch, zone_id, output_index, SPDK_BDEV_ZONE_FINISH, success); +} + static void test_reset_zone(void) { @@ -1299,6 +1306,66 @@ test_close_zone(void) test_cleanup(); } +static void +test_finish_zone(void) +{ + struct spdk_io_channel *ch; + struct bdev_zone_block *bdev; + char *name = "Nvme0n1"; + uint32_t num_zones = 20; + uint64_t zone_id, wp; + uint32_t output_index = 0; + + init_test_globals(20 * 1024ul); + CU_ASSERT(zone_block_init() == 0); + + /* Create zone dev */ + bdev = create_and_get_vbdev("zone_dev1", name, num_zones, 1, true); + + ch = calloc(1, sizeof(struct spdk_io_channel) + sizeof(struct zone_block_io_channel)); + SPDK_CU_ASSERT_FATAL(ch != NULL); + + /* Reset an unused zone */ + send_reset_zone(bdev, ch, bdev->bdev.zone_size, output_index, true); + + /* Finish a full zone */ + zone_id = 0; + wp = bdev->bdev.zone_size; + send_finish_zone(bdev, ch, zone_id, output_index, true); + send_zone_info(bdev, ch, zone_id, wp, SPDK_BDEV_ZONE_STATE_FULL, output_index, true); + + /* Finish an empty zone */ + send_reset_zone(bdev, ch, zone_id, output_index, true); + send_finish_zone(bdev, ch, zone_id, output_index, true); + send_zone_info(bdev, ch, zone_id, wp, SPDK_BDEV_ZONE_STATE_FULL, output_index, true); + + /* Finish an open zone */ + send_reset_zone(bdev, ch, zone_id, output_index, true); + send_write_zone(bdev, ch, zone_id, 1, output_index, true); + send_finish_zone(bdev, ch, zone_id, output_index, true); + send_zone_info(bdev, ch, zone_id, wp, SPDK_BDEV_ZONE_STATE_FULL, output_index, true); + + /* Send finish with misaligned LBA */ + zone_id = 1; + send_finish_zone(bdev, ch, zone_id, output_index, false); + + /* Send finish to non-existing zone */ + zone_id = num_zones * bdev->bdev.zone_size; + send_finish_zone(bdev, ch, zone_id, output_index, false); + + /* Make sure unused zone wasn't written to */ + zone_id = bdev->bdev.zone_size; + send_zone_info(bdev, ch, zone_id, zone_id, SPDK_BDEV_ZONE_STATE_EMPTY, output_index, true); + + /* Delete zone dev */ + send_delete_vbdev("zone_dev1", true); + + while (spdk_thread_poll(g_thread, 0, 0) > 0) {} + free(ch); + + test_cleanup(); +} + int main(int argc, char **argv) { CU_pSuite suite = NULL; @@ -1323,7 +1390,8 @@ int main(int argc, char **argv) CU_add_test(suite, "test_open_zone", test_open_zone) == NULL || CU_add_test(suite, "test_zone_write", test_zone_write) == NULL || CU_add_test(suite, "test_zone_read", test_zone_read) == NULL || - CU_add_test(suite, "test_close_zone", test_close_zone) == NULL + CU_add_test(suite, "test_close_zone", test_close_zone) == NULL || + CU_add_test(suite, "test_finish_zone", test_finish_zone) == NULL ) { CU_cleanup_registry(); return CU_get_error();