From 248ccd86070d81ce1471ca9bc920fb73651c1c86 Mon Sep 17 00:00:00 2001 From: Alexey Marchuk Date: Mon, 31 Jan 2022 15:10:53 +0300 Subject: [PATCH] lvol: Use blobstore ext API in data path The new blobstore ext API is used when the user provides ext_io_opts in bdev layer. To store blobstore ext_io_opts, vbdev_lvol reports non-zero get_ctx_size in bdev module interface. Signed-off-by: Alexey Marchuk Change-Id: I64076b5369533be0c1d69ca48aef9d70a9abe488 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/11373 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- module/bdev/lvol/vbdev_lvol.c | 45 ++++++++++++++-- .../lib/bdev/vbdev_lvol.c/vbdev_lvol_ut.c | 53 ++++++++++++++++++- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/module/bdev/lvol/vbdev_lvol.c b/module/bdev/lvol/vbdev_lvol.c index 3f72c03ca..38f716a51 100644 --- a/module/bdev/lvol/vbdev_lvol.c +++ b/module/bdev/lvol/vbdev_lvol.c @@ -3,6 +3,7 @@ * * Copyright (c) Intel Corporation. * All rights reserved. + * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,6 +41,10 @@ #include "vbdev_lvol.h" +struct vbdev_lvol_io { + struct spdk_blob_ext_io_opts ext_io_opts; +}; + static TAILQ_HEAD(, lvol_store_bdev) g_spdk_lvol_pairs = TAILQ_HEAD_INITIALIZER( g_spdk_lvol_pairs); @@ -840,8 +845,23 @@ lvol_read(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) start_page = bdev_io->u.bdev.offset_blocks; num_pages = bdev_io->u.bdev.num_blocks; - spdk_blob_io_readv(blob, ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, start_page, - num_pages, lvol_op_comp, bdev_io); + if (bdev_io->u.bdev.ext_opts) { + struct vbdev_lvol_io *lvol_io = (struct vbdev_lvol_io *)bdev_io->driver_ctx; + + lvol_io->ext_io_opts.size = sizeof(lvol_io->ext_io_opts); + lvol_io->ext_io_opts.memory_domain = bdev_io->u.bdev.ext_opts->memory_domain; + lvol_io->ext_io_opts.memory_domain_ctx = bdev_io->u.bdev.ext_opts->memory_domain_ctx; + /* Save a pointer to ext_opts passed by the user, it will be used in bs_dev readv/writev_ext functions + * to restore ext_opts structure. That is done since bdev and blob extended functions use different + * extended opts structures */ + lvol_io->ext_io_opts.user_ctx = bdev_io->u.bdev.ext_opts; + + spdk_blob_io_readv_ext(blob, ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, start_page, + num_pages, lvol_op_comp, bdev_io, &lvol_io->ext_io_opts); + } else { + spdk_blob_io_readv(blob, ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, start_page, + num_pages, lvol_op_comp, bdev_io); + } } static void @@ -853,8 +873,23 @@ lvol_write(struct spdk_lvol *lvol, struct spdk_io_channel *ch, struct spdk_bdev_ start_page = bdev_io->u.bdev.offset_blocks; num_pages = bdev_io->u.bdev.num_blocks; - spdk_blob_io_writev(blob, ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, start_page, - num_pages, lvol_op_comp, bdev_io); + if (bdev_io->u.bdev.ext_opts) { + struct vbdev_lvol_io *lvol_io = (struct vbdev_lvol_io *)bdev_io->driver_ctx; + + lvol_io->ext_io_opts.size = sizeof(lvol_io->ext_io_opts); + lvol_io->ext_io_opts.memory_domain = bdev_io->u.bdev.ext_opts->memory_domain; + lvol_io->ext_io_opts.memory_domain_ctx = bdev_io->u.bdev.ext_opts->memory_domain_ctx; + /* Save a pointer to ext_opts passed by the user, it will be used in bs_dev readv/writev_ext functions + * to restore ext_opts structure. That is done since bdev and blob extended functions use different + * extended opts structures */ + lvol_io->ext_io_opts.user_ctx = bdev_io->u.bdev.ext_opts; + + spdk_blob_io_writev_ext(blob, ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, start_page, + num_pages, lvol_op_comp, bdev_io, &lvol_io->ext_io_opts); + } else { + spdk_blob_io_writev(blob, ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, start_page, + num_pages, lvol_op_comp, bdev_io); + } } static int @@ -1278,7 +1313,7 @@ vbdev_lvs_fini_start(void) static int vbdev_lvs_get_ctx_size(void) { - return 0; + return sizeof(struct vbdev_lvol_io); } static void 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 ba1db673e..0dd5b3b37 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 @@ -3,6 +3,7 @@ * * Copyright (c) Intel Corporation. * All rights reserved. + * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -60,6 +61,7 @@ bool lvol_already_opened = false; bool g_examine_done = false; bool g_bdev_alias_already_exists = false; bool g_lvs_with_name_already_exists = false; +bool g_ext_api_called; DEFINE_STUB_V(spdk_bdev_module_fini_start_done, (void)); @@ -562,6 +564,23 @@ spdk_blob_io_writev(struct spdk_blob *blob, struct spdk_io_channel *channel, cb_fn(cb_arg, 0); } +void +spdk_blob_io_writev_ext(struct spdk_blob *blob, struct spdk_io_channel *channel, + struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, + spdk_blob_op_complete cb_fn, void *cb_arg, + struct spdk_blob_ext_io_opts *io_opts) +{ + struct vbdev_lvol_io *lvol_io = (struct vbdev_lvol_io *)g_io->driver_ctx; + + CU_ASSERT(blob == NULL); + CU_ASSERT(channel == g_ch); + CU_ASSERT(offset == g_io->u.bdev.offset_blocks); + CU_ASSERT(length == g_io->u.bdev.num_blocks); + CU_ASSERT(io_opts == &lvol_io->ext_io_opts); + g_ext_api_called = true; + cb_fn(cb_arg, 0); +} + void spdk_blob_io_readv(struct spdk_blob *blob, struct spdk_io_channel *channel, struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, @@ -574,6 +593,23 @@ spdk_blob_io_readv(struct spdk_blob *blob, struct spdk_io_channel *channel, cb_fn(cb_arg, 0); } +void +spdk_blob_io_readv_ext(struct spdk_blob *blob, struct spdk_io_channel *channel, + struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, + spdk_blob_op_complete cb_fn, void *cb_arg, + struct spdk_blob_ext_io_opts *io_opts) +{ + struct vbdev_lvol_io *lvol_io = (struct vbdev_lvol_io *)g_io->driver_ctx; + + CU_ASSERT(blob == NULL); + CU_ASSERT(channel == g_ch); + CU_ASSERT(offset == g_io->u.bdev.offset_blocks); + CU_ASSERT(length == g_io->u.bdev.num_blocks); + CU_ASSERT(io_opts == &lvol_io->ext_io_opts); + g_ext_api_called = true; + cb_fn(cb_arg, 0); +} + void spdk_bdev_module_list_add(struct spdk_bdev_module *bdev_module) { @@ -1356,7 +1392,9 @@ ut_vbdev_lvol_io_type_supported(void) static void ut_lvol_read_write(void) { - g_io = calloc(1, sizeof(struct spdk_bdev_io)); + struct spdk_bdev_ext_io_opts bdev_ext_opts = {}; + + 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); @@ -1374,6 +1412,19 @@ ut_lvol_read_write(void) lvol_write(g_lvol, g_ch, g_io); CU_ASSERT(g_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS); + g_ext_api_called = false; + g_io->u.bdev.ext_opts = &bdev_ext_opts; + + lvol_read(g_ch, g_io); + CU_ASSERT(g_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS); + CU_ASSERT(g_ext_api_called == true); + g_ext_api_called = false; + + lvol_write(g_lvol, g_ch, g_io); + CU_ASSERT(g_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS); + CU_ASSERT(g_ext_api_called == true); + g_ext_api_called = false; + free(g_io); free(g_base_bdev); free(g_lvol);