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)