bdev/zone: Zone append handling added to vbdev
Changed write function to be able to work in zone append mode. Signed-off-by: Mateusz Kozlowski <mateusz.kozlowski@intel.com> Change-Id: I3af98f1d8e69eac6922e19addebabbc6ce847c63 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468042 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
This commit is contained in:
parent
68c3a79a15
commit
a6ff97602c
@ -351,6 +351,10 @@ _zone_block_complete_write(struct spdk_bdev_io *bdev_io, bool success, void *cb_
|
|||||||
struct spdk_bdev_io *orig_io = cb_arg;
|
struct spdk_bdev_io *orig_io = cb_arg;
|
||||||
int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
|
int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
|
||||||
|
|
||||||
|
if (success && orig_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND) {
|
||||||
|
orig_io->u.bdev.offset_blocks = bdev_io->u.bdev.offset_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
/* Complete the original IO and then free the one that we created here
|
/* Complete the original IO and then free the one that we created here
|
||||||
* as a result of issuing an IO via submit_reqeust.
|
* as a result of issuing an IO via submit_reqeust.
|
||||||
*/
|
*/
|
||||||
@ -367,8 +371,13 @@ zone_block_write(struct bdev_zone_block *bdev_node, struct zone_block_io_channel
|
|||||||
uint64_t lba = bdev_io->u.bdev.offset_blocks;
|
uint64_t lba = bdev_io->u.bdev.offset_blocks;
|
||||||
uint64_t num_blocks_left, wp;
|
uint64_t num_blocks_left, wp;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
bool is_append = bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND;
|
||||||
|
|
||||||
|
if (is_append) {
|
||||||
|
zone = zone_block_get_zone_by_slba(bdev_node, lba);
|
||||||
|
} else {
|
||||||
zone = zone_block_get_zone_containing_lba(bdev_node, lba);
|
zone = zone_block_get_zone_containing_lba(bdev_node, lba);
|
||||||
|
}
|
||||||
if (!zone) {
|
if (!zone) {
|
||||||
SPDK_ERRLOG("Trying to write to invalid zone (lba 0x%lx)\n", lba);
|
SPDK_ERRLOG("Trying to write to invalid zone (lba 0x%lx)\n", lba);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -389,12 +398,15 @@ zone_block_write(struct bdev_zone_block *bdev_node, struct zone_block_io_channel
|
|||||||
}
|
}
|
||||||
|
|
||||||
wp = zone->zone_info.write_pointer;
|
wp = zone->zone_info.write_pointer;
|
||||||
|
if (is_append) {
|
||||||
|
lba = wp;
|
||||||
|
} else {
|
||||||
if (lba != wp) {
|
if (lba != wp) {
|
||||||
SPDK_ERRLOG("Trying to write to zone with invalid address (lba 0x%lx, wp 0x%lx)\n", lba, wp);
|
SPDK_ERRLOG("Trying to write to zone with invalid address (lba 0x%lx, wp 0x%lx)\n", lba, wp);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto write_fail;
|
goto write_fail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
num_blocks_left = zone->zone_info.zone_id + zone->zone_info.capacity - wp;
|
num_blocks_left = zone->zone_info.zone_id + zone->zone_info.capacity - wp;
|
||||||
if (len > num_blocks_left) {
|
if (len > num_blocks_left) {
|
||||||
@ -494,6 +506,7 @@ zone_block_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_
|
|||||||
rc = zone_block_zone_management(bdev_node, dev_ch, bdev_io);
|
rc = zone_block_zone_management(bdev_node, dev_ch, bdev_io);
|
||||||
break;
|
break;
|
||||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||||
|
case SPDK_BDEV_IO_TYPE_ZONE_APPEND:
|
||||||
rc = zone_block_write(bdev_node, dev_ch, bdev_io);
|
rc = zone_block_write(bdev_node, dev_ch, bdev_io);
|
||||||
break;
|
break;
|
||||||
case SPDK_BDEV_IO_TYPE_READ:
|
case SPDK_BDEV_IO_TYPE_READ:
|
||||||
@ -523,6 +536,7 @@ zone_block_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
|
|||||||
case SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT:
|
case SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT:
|
||||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||||
case SPDK_BDEV_IO_TYPE_READ:
|
case SPDK_BDEV_IO_TYPE_READ:
|
||||||
|
case SPDK_BDEV_IO_TYPE_ZONE_APPEND:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -782,7 +782,7 @@ test_supported_io_types(void)
|
|||||||
bdev = create_and_get_vbdev("zone_dev1", name, num_zones, 1, true);
|
bdev = create_and_get_vbdev("zone_dev1", name, num_zones, 1, true);
|
||||||
|
|
||||||
CU_ASSERT(zone_block_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT) == true);
|
CU_ASSERT(zone_block_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT) == true);
|
||||||
CU_ASSERT(zone_block_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_ZONE_APPEND) == false);
|
CU_ASSERT(zone_block_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_ZONE_APPEND) == true);
|
||||||
CU_ASSERT(zone_block_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_READ) == true);
|
CU_ASSERT(zone_block_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_READ) == true);
|
||||||
CU_ASSERT(zone_block_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE) == true);
|
CU_ASSERT(zone_block_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE) == true);
|
||||||
|
|
||||||
@ -1044,6 +1044,28 @@ send_read_zone(struct bdev_zone_block *bdev, struct spdk_io_channel *ch, uint64_
|
|||||||
bdev_io_cleanup(bdev_io);
|
bdev_io_cleanup(bdev_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_append_zone(struct bdev_zone_block *bdev, struct spdk_io_channel *ch, uint64_t lba,
|
||||||
|
uint64_t blocks, uint32_t output_index, bool success, uint64_t wp)
|
||||||
|
{
|
||||||
|
struct spdk_bdev_io *bdev_io;
|
||||||
|
|
||||||
|
bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct zone_block_io));
|
||||||
|
SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
|
||||||
|
bdev_io_initialize(bdev_io, &bdev->bdev, lba, blocks, SPDK_BDEV_IO_TYPE_ZONE_APPEND);
|
||||||
|
memset(g_io_output, 0, (g_max_io_size * sizeof(struct io_output)));
|
||||||
|
g_io_output_index = output_index;
|
||||||
|
|
||||||
|
g_io_comp_status = !success;
|
||||||
|
zone_block_submit_request(ch, bdev_io);
|
||||||
|
|
||||||
|
CU_ASSERT(g_io_comp_status == success);
|
||||||
|
if (success) {
|
||||||
|
CU_ASSERT(bdev_io->u.bdev.offset_blocks == wp);
|
||||||
|
}
|
||||||
|
bdev_io_cleanup(bdev_io);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_open_zone(void)
|
test_open_zone(void)
|
||||||
{
|
{
|
||||||
@ -1366,6 +1388,78 @@ test_finish_zone(void)
|
|||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_append_zone(void)
|
||||||
|
{
|
||||||
|
struct spdk_io_channel *ch;
|
||||||
|
struct bdev_zone_block *bdev;
|
||||||
|
char *name = "Nvme0n1";
|
||||||
|
uint32_t num_zones = 20;
|
||||||
|
uint64_t zone_id, block_len, i;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Append to full zone */
|
||||||
|
zone_id = 0;
|
||||||
|
send_append_zone(bdev, ch, zone_id, 1, output_index, false, 0);
|
||||||
|
|
||||||
|
/* Append out of device range */
|
||||||
|
zone_id = g_block_cnt;
|
||||||
|
send_append_zone(bdev, ch, zone_id, 1, output_index, false, 0);
|
||||||
|
|
||||||
|
/* Append 1 sector to zone 0 */
|
||||||
|
zone_id = 0;
|
||||||
|
send_reset_zone(bdev, ch, zone_id, output_index, true);
|
||||||
|
send_append_zone(bdev, ch, zone_id, 1, output_index, true, zone_id);
|
||||||
|
send_zone_info(bdev, ch, zone_id, 1, SPDK_BDEV_ZONE_STATE_OPEN, output_index, true);
|
||||||
|
|
||||||
|
/* Append to another zone */
|
||||||
|
zone_id = bdev->bdev.zone_size;
|
||||||
|
send_reset_zone(bdev, ch, zone_id, output_index, true);
|
||||||
|
send_append_zone(bdev, ch, zone_id, 5, output_index, true, zone_id);
|
||||||
|
send_zone_info(bdev, ch, zone_id, zone_id + 5, SPDK_BDEV_ZONE_STATE_OPEN, output_index, true);
|
||||||
|
|
||||||
|
/* Fill zone 0 and verify zone state change */
|
||||||
|
zone_id = 0;
|
||||||
|
block_len = 15;
|
||||||
|
send_append_zone(bdev, ch, zone_id, block_len, output_index, true, 1);
|
||||||
|
block_len++;
|
||||||
|
for (i = block_len; i < bdev->zone_capacity; i += block_len) {
|
||||||
|
send_append_zone(bdev, ch, zone_id, block_len, output_index, true, i);
|
||||||
|
}
|
||||||
|
send_zone_info(bdev, ch, zone_id, bdev->bdev.zone_size, SPDK_BDEV_ZONE_STATE_FULL, output_index,
|
||||||
|
true);
|
||||||
|
|
||||||
|
/* Append to two zones at once */
|
||||||
|
for (i = 0; i < num_zones; i++) {
|
||||||
|
zone_id = i * bdev->bdev.zone_size;
|
||||||
|
send_reset_zone(bdev, ch, zone_id, output_index, true);
|
||||||
|
send_zone_info(bdev, ch, zone_id, zone_id, SPDK_BDEV_ZONE_STATE_EMPTY, output_index, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
zone_id = 0;
|
||||||
|
block_len = 16;
|
||||||
|
for (i = 0; i < bdev->zone_capacity - block_len; i += block_len) {
|
||||||
|
send_append_zone(bdev, ch, zone_id, block_len, output_index, true, zone_id + i);
|
||||||
|
}
|
||||||
|
send_append_zone(bdev, ch, zone_id, 32, output_index, false, 0);
|
||||||
|
/* 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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
CU_pSuite suite = NULL;
|
CU_pSuite suite = NULL;
|
||||||
@ -1391,7 +1485,8 @@ int main(int argc, char **argv)
|
|||||||
CU_add_test(suite, "test_zone_write", test_zone_write) == 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_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_add_test(suite, "test_finish_zone", test_finish_zone) == NULL ||
|
||||||
|
CU_add_test(suite, "test_append_zone", test_append_zone) == NULL
|
||||||
) {
|
) {
|
||||||
CU_cleanup_registry();
|
CU_cleanup_registry();
|
||||||
return CU_get_error();
|
return CU_get_error();
|
||||||
|
Loading…
Reference in New Issue
Block a user