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 <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/393221
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
GangCao 2017-12-28 16:49:46 -05:00 committed by Daniel Verkamp
parent 310f324e38
commit 61e8486c10
5 changed files with 104 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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