From 61e8486c10bd179811225d792add75a8fcc936ce Mon Sep 17 00:00:00 2001 From: GangCao Date: Thu, 28 Dec 2017 16:49:46 -0500 Subject: [PATCH] bdev/qos: add the QoS setting in conf file For application like vhost/iSCSI target/NVMe-oF target/etc, a new section as below can be added for the QoS rate limiting. [QoS] Limit_IOPS Malloc0 100000 Limit_IOPS Nvme0n1 500000 Also added a sample change at test/lib/bdev/bdev.conf.in Change-Id: I7c7d951fbe1352ca2571f135c657bc4fa43b56c7 Signed-off-by: GangCao Reviewed-on: https://review.gerrithub.io/393221 Reviewed-by: Shuhei Matsumoto Tested-by: SPDK Automated Test System Reviewed-by: Daniel Verkamp --- lib/bdev/bdev.c | 50 ++++++++++++++++++++++++++ test/bdev/bdev.conf.in | 12 +++++++ test/unit/lib/bdev/bdev.c/bdev_ut.c | 14 ++++++++ test/unit/lib/bdev/mt/bdev.c/bdev_ut.c | 14 ++++++++ test/unit/lib/bdev/part.c/part_ut.c | 14 ++++++++ 5 files changed, 104 insertions(+) diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index de441f776..7d4c54b5c 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -35,6 +35,7 @@ #include "spdk/stdinc.h" #include "spdk/bdev.h" +#include "spdk/conf.h" #include "spdk/env.h" #include "spdk/event.h" @@ -64,6 +65,7 @@ int __itt_init_ittlib(const char *, __itt_group_id); #define SPDK_BDEV_QOS_TIMESLICE_IN_USEC 1000 #define SPDK_BDEV_SEC_TO_USEC 1000000ULL #define SPDK_BDEV_QOS_MIN_IO_PER_TIMESLICE 1 +#define SPDK_BDEV_QOS_MIN_IOS_PER_SEC 10000 typedef TAILQ_HEAD(, spdk_bdev_io) bdev_io_tailq_t; typedef STAILQ_HEAD(, spdk_bdev_io) bdev_io_stailq_t; @@ -2400,6 +2402,52 @@ spdk_bdev_io_get_thread(struct spdk_bdev_io *bdev_io) return spdk_io_channel_get_thread(bdev_io->ch->channel); } +static void +_spdk_bdev_qos_config(struct spdk_bdev *bdev) +{ + struct spdk_conf_section *sp = NULL; + const char *val = NULL; + int ios_per_sec = 0; + int i = 0; + + sp = spdk_conf_find_section(NULL, "QoS"); + if (!sp) { + return; + } + + while (true) { + val = spdk_conf_section_get_nmval(sp, "Limit_IOPS", i, 0); + if (!val) { + break; + } + + if (strcmp(bdev->name, val) != 0) { + i++; + continue; + } + + val = spdk_conf_section_get_nmval(sp, "Limit_IOPS", i, 1); + if (!val) { + return; + } + + ios_per_sec = (int)strtol(val, NULL, 10); + if (ios_per_sec > 0) { + if (ios_per_sec % SPDK_BDEV_QOS_MIN_IOS_PER_SEC) { + SPDK_ERRLOG("Assigned IOPS %u on bdev %s is not multiple of %u\n", + ios_per_sec, bdev->name, SPDK_BDEV_QOS_MIN_IOS_PER_SEC); + SPDK_ERRLOG("Failed to enable QoS on this bdev %s\n", bdev->name); + } else { + bdev->ios_per_sec = (uint64_t)ios_per_sec; + SPDK_DEBUGLOG(SPDK_LOG_BDEV, "Bdev:%s QoS:%lu\n", + bdev->name, bdev->ios_per_sec); + } + } + + return; + } +} + static int spdk_bdev_init(struct spdk_bdev *bdev) { @@ -2423,6 +2471,8 @@ spdk_bdev_init(struct spdk_bdev *bdev) bdev->reset_in_progress = NULL; + _spdk_bdev_qos_config(bdev); + spdk_io_device_register(__bdev_to_io_dev(bdev), spdk_bdev_channel_create, spdk_bdev_channel_destroy, sizeof(struct spdk_bdev_channel)); diff --git a/test/bdev/bdev.conf.in b/test/bdev/bdev.conf.in index 8d7ac2e8f..c1d116366 100644 --- a/test/bdev/bdev.conf.in +++ b/test/bdev/bdev.conf.in @@ -20,3 +20,15 @@ [Ioat] Disable Yes + +[QoS] + # QoS section defines limitation on performance + # metric like IOPS + # + # Format: Limit_IOPS Bdev_Name IOPS_Limit_Value + # + # IOPS limit must be 10000 or greater and be multiple + # of 10000 + # + # Assign 20000 IOPS for the Malloc0 block device + Limit_IOPS Malloc0 20000 diff --git a/test/unit/lib/bdev/bdev.c/bdev_ut.c b/test/unit/lib/bdev/bdev.c/bdev_ut.c index 1fe07f78f..3cf37ba68 100644 --- a/test/unit/lib/bdev/bdev.c/bdev_ut.c +++ b/test/unit/lib/bdev/bdev.c/bdev_ut.c @@ -41,6 +41,20 @@ #include "bdev/bdev.c" +/* Return NULL to test hardcoded defaults. */ +struct spdk_conf_section * +spdk_conf_find_section(struct spdk_conf *cp, const char *name) +{ + return NULL; +} + +/* Return NULL to test hardcoded defaults. */ +char * +spdk_conf_section_get_nmval(struct spdk_conf_section *sp, const char *key, int idx1, int idx2) +{ + return NULL; +} + void spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io, int *sc, int *sk, int *asc, int *ascq) 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 b9564c2f1..ff07d2f3e 100644 --- a/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c +++ b/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c @@ -47,6 +47,20 @@ DEFINE_STUB_V(spdk_scsi_nvme_translate, (const struct spdk_bdev_io *bdev_io, int *sc, int *sk, int *asc, int *ascq)); +/* Return NULL to test hardcoded defaults. */ +struct spdk_conf_section * +spdk_conf_find_section(struct spdk_conf *cp, const char *name) +{ + return NULL; +} + +/* Return NULL to test hardcoded defaults. */ +char * +spdk_conf_section_get_nmval(struct spdk_conf_section *sp, const char *key, int idx1, int idx2) +{ + return NULL; +} + struct ut_bdev { struct spdk_bdev bdev; void *io_target; diff --git a/test/unit/lib/bdev/part.c/part_ut.c b/test/unit/lib/bdev/part.c/part_ut.c index 3c94d7a1e..de251af6f 100644 --- a/test/unit/lib/bdev/part.c/part_ut.c +++ b/test/unit/lib/bdev/part.c/part_ut.c @@ -42,6 +42,20 @@ #include "bdev/bdev.c" #include "bdev/part.c" +/* Return NULL to test hardcoded defaults. */ +struct spdk_conf_section * +spdk_conf_find_section(struct spdk_conf *cp, const char *name) +{ + return NULL; +} + +/* Return NULL to test hardcoded defaults. */ +char * +spdk_conf_section_get_nmval(struct spdk_conf_section *sp, const char *key, int idx1, int idx2) +{ + return NULL; +} + void spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io, int *sc, int *sk, int *asc, int *ascq)