diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 3c8c1ab54..46ed18c70 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -282,6 +282,12 @@ struct spdk_bdev_iostat_ctx { void *cb_arg; }; +struct set_qos_limit_ctx { + void (*cb_fn)(void *cb_arg, int status); + void *cb_arg; + struct spdk_bdev *bdev; +}; + #define __bdev_to_io_dev(bdev) (((char *)bdev) + 1) #define __bdev_from_io_dev(io_dev) ((struct spdk_bdev *)(((char *)io_dev) - 1)) @@ -289,6 +295,9 @@ static void _spdk_bdev_write_zero_buffer_done(struct spdk_bdev_io *bdev_io, bool void *cb_arg); static void _spdk_bdev_write_zero_buffer_next(void *_bdev_io); +static void _spdk_bdev_enable_qos_msg(struct spdk_io_channel_iter *i); +static void _spdk_bdev_enable_qos_done(struct spdk_io_channel_iter *i, int status); + void spdk_bdev_get_opts(struct spdk_bdev_opts *opts) { @@ -3744,6 +3753,7 @@ spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_ { struct spdk_bdev_desc *desc; struct spdk_thread *thread; + struct set_qos_limit_ctx *ctx; thread = spdk_get_thread(); if (!thread) { @@ -3778,6 +3788,22 @@ spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_ return -EPERM; } + /* Enable QoS */ + if (bdev->internal.qos && bdev->internal.qos->thread == NULL) { + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + SPDK_ERRLOG("Failed to allocate memory for QoS context\n"); + pthread_mutex_unlock(&bdev->internal.mutex); + free(desc); + *_desc = NULL; + return -ENOMEM; + } + ctx->bdev = bdev; + spdk_for_each_channel(__bdev_to_io_dev(bdev), + _spdk_bdev_enable_qos_msg, ctx, + _spdk_bdev_enable_qos_done); + } + TAILQ_INSERT_TAIL(&bdev->internal.open_descs, desc, link); pthread_mutex_unlock(&bdev->internal.mutex); @@ -3984,12 +4010,6 @@ _spdk_bdev_write_zero_buffer_done(struct spdk_bdev_io *bdev_io, bool success, vo _spdk_bdev_write_zero_buffer_next(parent_io); } -struct set_qos_limit_ctx { - void (*cb_fn)(void *cb_arg, int status); - void *cb_arg; - struct spdk_bdev *bdev; -}; - static void _spdk_bdev_set_qos_limit_done(struct set_qos_limit_ctx *ctx, int status) { @@ -3997,7 +4017,9 @@ _spdk_bdev_set_qos_limit_done(struct set_qos_limit_ctx *ctx, int status) ctx->bdev->internal.qos_mod_in_progress = false; pthread_mutex_unlock(&ctx->bdev->internal.mutex); - ctx->cb_fn(ctx->cb_arg, status); + if (ctx->cb_fn) { + ctx->cb_fn(ctx->cb_arg, status); + } free(ctx); } diff --git a/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c b/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c index ebba23002..b9888c313 100644 --- a/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c +++ b/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c @@ -671,6 +671,22 @@ basic_qos(void) poll_threads(); CU_ASSERT(status == SPDK_BDEV_IO_STATUS_SUCCESS); + /* + * Close the descriptor only, which should stop the qos channel as + * the last descriptor removed. + */ + spdk_bdev_close(g_desc); + poll_threads(); + CU_ASSERT(bdev->internal.qos->ch == NULL); + + /* + * Open the bdev again which shall setup the qos channel as the + * channels are valid. + */ + spdk_bdev_open(bdev, true, NULL, NULL, &g_desc); + poll_threads(); + CU_ASSERT(bdev->internal.qos->ch != NULL); + /* Tear down the channels */ set_thread(0); spdk_put_io_channel(io_ch[0]); @@ -684,7 +700,10 @@ basic_qos(void) poll_threads(); CU_ASSERT(bdev->internal.qos->ch == NULL); + /* Open the bdev again, no qos channel setup without valid channels. */ spdk_bdev_open(bdev, true, NULL, NULL, &g_desc); + poll_threads(); + CU_ASSERT(bdev->internal.qos->ch == NULL); /* Create the channels in reverse order. */ set_thread(1);