QoS: enable rate limit when opening the bdev

There are some cases that virtual bdev open and close
the device and QoS will be disabled at the last close.
In this case, when a new bdev open operation comes again,
the QoS needs to be enabled again.

Change-Id: I792e610f4592bad1cac55c6c55261d4946c6b3e2
Signed-off-by: GangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/c/442953 (master)
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/447455
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
GangCao 2019-02-01 14:21:03 -05:00 committed by Ben Walker
parent bf881b09a7
commit d45c6e54ae
2 changed files with 48 additions and 7 deletions

View File

@ -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);
}

View File

@ -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);