Commit 61e8486c authored by GangCao's avatar GangCao Committed by Daniel Verkamp
Browse files

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: default avatarGangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/393221


Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 310f324e
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -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));
+12 −0
Original line number Diff line number Diff line
@@ -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
+14 −0
Original line number Diff line number Diff line
@@ -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)
+14 −0
Original line number Diff line number Diff line
@@ -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;
+14 −0
Original line number Diff line number Diff line
@@ -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)