From 67bb33160ae09c9204b952f3dbce990970728d0d Mon Sep 17 00:00:00 2001 From: Damiano Cipriani Date: Mon, 5 Sep 2022 15:22:18 +0200 Subject: [PATCH] vbdev_lvol: Implement SEEK_[DATA,HOLE] io type Two functions have been added to implement bdev io type SEEK_DATA and SEEK_HOLE. Blob functions to find next [un]allocated io_unit are used Signed-off-by: Damiano Cipriani Change-Id: Ic3be3c0c86bd3010a23ba2681f0f00c62abcaaba Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14362 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- module/bdev/lvol/vbdev_lvol.c | 26 +++++++ .../lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c | 78 +++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/module/bdev/lvol/vbdev_lvol.c b/module/bdev/lvol/vbdev_lvol.c index f7a28afc9..dadf6c01d 100644 --- a/module/bdev/lvol/vbdev_lvol.c +++ b/module/bdev/lvol/vbdev_lvol.c @@ -765,6 +765,8 @@ vbdev_lvol_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) return !spdk_blob_is_read_only(lvol->blob); case SPDK_BDEV_IO_TYPE_RESET: case SPDK_BDEV_IO_TYPE_READ: + case SPDK_BDEV_IO_TYPE_SEEK_DATA: + case SPDK_BDEV_IO_TYPE_SEEK_HOLE: return true; default: return false; @@ -800,6 +802,24 @@ lvol_unmap(struct spdk_lvol *lvol, struct spdk_io_channel *ch, struct spdk_bdev_ spdk_blob_io_unmap(blob, ch, start_page, num_pages, lvol_op_comp, bdev_io); } +static void +lvol_seek_data(struct spdk_lvol *lvol, struct spdk_bdev_io *bdev_io) +{ + bdev_io->u.bdev.seek.offset = spdk_blob_get_next_allocated_io_unit(lvol->blob, + bdev_io->u.bdev.offset_blocks); + + spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); +} + +static void +lvol_seek_hole(struct spdk_lvol *lvol, struct spdk_bdev_io *bdev_io) +{ + bdev_io->u.bdev.seek.offset = spdk_blob_get_next_unallocated_io_unit(lvol->blob, + bdev_io->u.bdev.offset_blocks); + + spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); +} + static void lvol_write_zeroes(struct spdk_lvol *lvol, struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) { @@ -910,6 +930,12 @@ vbdev_lvol_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_ case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: lvol_write_zeroes(lvol, ch, bdev_io); break; + case SPDK_BDEV_IO_TYPE_SEEK_DATA: + lvol_seek_data(lvol, bdev_io); + break; + case SPDK_BDEV_IO_TYPE_SEEK_HOLE: + lvol_seek_hole(lvol, bdev_io); + break; default: SPDK_INFOLOG(vbdev_lvol, "lvol: unsupported I/O type %d\n", bdev_io->type); spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); diff --git a/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c b/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c index c860c9f20..23232a434 100644 --- a/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c +++ b/test/unit/lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c @@ -169,6 +169,33 @@ spdk_blob_get_num_clusters(struct spdk_blob *b) return 0; } +/* Simulation of a blob with: + * - 1 io_unit per cluster + * - 20 data cluster + * - only last cluster allocated + */ +uint64_t g_blob_allocated_io_unit_offset = 20; + +uint64_t +spdk_blob_get_next_allocated_io_unit(struct spdk_blob *blob, uint64_t offset) +{ + if (offset <= g_blob_allocated_io_unit_offset) { + return g_blob_allocated_io_unit_offset; + } else { + return UINT64_MAX; + } +} + +uint64_t +spdk_blob_get_next_unallocated_io_unit(struct spdk_blob *blob, uint64_t offset) +{ + if (offset < g_blob_allocated_io_unit_offset) { + return offset; + } else { + return UINT64_MAX; + } +} + int spdk_blob_get_clones(struct spdk_blob_store *bs, spdk_blob_id blobid, spdk_blob_id *ids, size_t *count) @@ -1347,6 +1374,10 @@ ut_vbdev_lvol_io_type_supported(void) CU_ASSERT(ret == true); ret = vbdev_lvol_io_type_supported(lvol, SPDK_BDEV_IO_TYPE_WRITE_ZEROES); CU_ASSERT(ret == true); + ret = vbdev_lvol_io_type_supported(lvol, SPDK_BDEV_IO_TYPE_SEEK_DATA); + CU_ASSERT(ret == true); + ret = vbdev_lvol_io_type_supported(lvol, SPDK_BDEV_IO_TYPE_SEEK_HOLE); + CU_ASSERT(ret == true); /* Unsupported types */ ret = vbdev_lvol_io_type_supported(lvol, SPDK_BDEV_IO_TYPE_FLUSH); @@ -1363,6 +1394,10 @@ ut_vbdev_lvol_io_type_supported(void) CU_ASSERT(ret == true); ret = vbdev_lvol_io_type_supported(lvol, SPDK_BDEV_IO_TYPE_RESET); CU_ASSERT(ret == true); + ret = vbdev_lvol_io_type_supported(lvol, SPDK_BDEV_IO_TYPE_SEEK_DATA); + CU_ASSERT(ret == true); + ret = vbdev_lvol_io_type_supported(lvol, SPDK_BDEV_IO_TYPE_SEEK_HOLE); + CU_ASSERT(ret == true); /* Unsupported types */ ret = vbdev_lvol_io_type_supported(lvol, SPDK_BDEV_IO_TYPE_WRITE); @@ -1495,6 +1530,48 @@ ut_lvs_rename(void) free(g_base_bdev); } +static void +ut_lvol_seek(void) +{ + g_io = calloc(1, sizeof(struct spdk_bdev_io) + vbdev_lvs_get_ctx_size()); + SPDK_CU_ASSERT_FATAL(g_io != NULL); + g_base_bdev = calloc(1, sizeof(struct spdk_bdev)); + SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL); + g_lvol = calloc(1, sizeof(struct spdk_lvol)); + SPDK_CU_ASSERT_FATAL(g_lvol != NULL); + + g_io->bdev = g_base_bdev; + g_io->bdev->ctxt = g_lvol; + + /* Data found */ + g_io->u.bdev.offset_blocks = 10; + lvol_seek_data(g_lvol, g_io); + CU_ASSERT(g_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS); + CU_ASSERT(g_io->u.bdev.seek.offset == g_blob_allocated_io_unit_offset); + + /* Data not found */ + g_io->u.bdev.offset_blocks = 30; + lvol_seek_data(g_lvol, g_io); + CU_ASSERT(g_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS); + CU_ASSERT(g_io->u.bdev.seek.offset == UINT64_MAX); + + /* Hole found */ + g_io->u.bdev.offset_blocks = 10; + lvol_seek_hole(g_lvol, g_io); + CU_ASSERT(g_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS); + CU_ASSERT(g_io->u.bdev.seek.offset == 10); + + /* Hole not found */ + g_io->u.bdev.offset_blocks = 30; + lvol_seek_hole(g_lvol, g_io); + CU_ASSERT(g_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS); + CU_ASSERT(g_io->u.bdev.seek.offset == UINT64_MAX); + + free(g_io); + free(g_base_bdev); + free(g_lvol); +} + int main(int argc, char **argv) { @@ -1523,6 +1600,7 @@ main(int argc, char **argv) CU_ADD_TEST(suite, ut_lvol_rename); CU_ADD_TEST(suite, ut_bdev_finish); CU_ADD_TEST(suite, ut_lvs_rename); + CU_ADD_TEST(suite, ut_lvol_seek); CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests();