Commit cd4dd43a authored by GangCao's avatar GangCao Committed by Jim Harris
Browse files

bdev/qos: add the function pointers for qos operations



This patch added two new function pointers (queue_io,
update_io) for related qos operations like iops and
bandwidth rate limits.

Change-Id: I2ffd67c5f1c421eab448fd5e95f809da55805fcd
Signed-off-by: default avatarGangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/c/438157


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
parent ff3c2e3c
Loading
Loading
Loading
Loading
+56 −18
Original line number Diff line number Diff line
@@ -141,6 +141,12 @@ struct spdk_bdev_qos_limit {

	/** Maximum allowed IOs or bytes to be issued in one timeslice (e.g., 1ms). */
	uint32_t max_per_timeslice;

	/** Function to check whether to queue the IO. */
	bool (*queue_io)(const struct spdk_bdev_qos_limit *limit, struct spdk_bdev_io *io);

	/** Function to update for the submitted IO. */
	void (*update_quota)(struct spdk_bdev_qos_limit *limit, struct spdk_bdev_io *io);
};

struct spdk_bdev_qos {
@@ -1248,24 +1254,49 @@ _spdk_bdev_get_io_size_in_byte(struct spdk_bdev_io *bdev_io)
	}
}

static bool
_spdk_bdev_qos_rw_queue_io(const struct spdk_bdev_qos_limit *limit, struct spdk_bdev_io *io)
{
	if (limit->max_per_timeslice > 0 && limit->remaining_this_timeslice <= 0) {
		return true;
	} else {
		return false;
	}
}

static void
_spdk_bdev_qos_rw_iops_update_quota(struct spdk_bdev_qos_limit *limit, struct spdk_bdev_io *io)
{
	limit->remaining_this_timeslice--;
}

static void
_spdk_bdev_qos_rw_bps_update_quota(struct spdk_bdev_qos_limit *limit, struct spdk_bdev_io *io)
{
	limit->remaining_this_timeslice -= _spdk_bdev_get_io_size_in_byte(io);
}

static void
_spdk_bdev_qos_update_per_io(struct spdk_bdev_qos *qos, uint64_t io_size_in_byte)
_spdk_bdev_qos_set_ops(struct spdk_bdev_qos *qos)
{
	int i;

	for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
		if (qos->rate_limits[i].limit == SPDK_BDEV_QOS_LIMIT_NOT_DEFINED) {
			qos->rate_limits[i].queue_io = NULL;
			qos->rate_limits[i].update_quota = NULL;
			continue;
		}

		switch (i) {
		case SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT:
			qos->rate_limits[i].remaining_this_timeslice--;
			qos->rate_limits[i].queue_io = _spdk_bdev_qos_rw_queue_io;
			qos->rate_limits[i].update_quota = _spdk_bdev_qos_rw_iops_update_quota;
			break;
		case SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT:
			qos->rate_limits[i].remaining_this_timeslice -= io_size_in_byte;
			qos->rate_limits[i].queue_io = _spdk_bdev_qos_rw_queue_io;
			qos->rate_limits[i].update_quota = _spdk_bdev_qos_rw_bps_update_quota;
			break;
		case SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES:
		default:
			break;
		}
@@ -1275,30 +1306,35 @@ _spdk_bdev_qos_update_per_io(struct spdk_bdev_qos *qos, uint64_t io_size_in_byte
static int
_spdk_bdev_qos_io_submit(struct spdk_bdev_channel *ch, struct spdk_bdev_qos *qos)
{
	struct spdk_bdev_io		*bdev_io = NULL;
	struct spdk_bdev_io		*bdev_io = NULL, *tmp = NULL;
	struct spdk_bdev		*bdev = ch->bdev;
	struct spdk_bdev_shared_resource *shared_resource = ch->shared_resource;
	int				i, submitted_ios = 0;
	bool				to_limit_io;
	uint64_t			io_size_in_byte;

	while (!TAILQ_EMPTY(&qos->queued)) {
	TAILQ_FOREACH_SAFE(bdev_io, &qos->queued, internal.link, tmp) {
		if (_spdk_bdev_qos_io_to_limit(bdev_io) == true) {
			for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
			if (qos->rate_limits[i].max_per_timeslice > 0 &&
			    (qos->rate_limits[i].remaining_this_timeslice <= 0)) {
				if (!qos->rate_limits[i].queue_io) {
					continue;
				}

				if (qos->rate_limits[i].queue_io(&qos->rate_limits[i],
								 bdev_io) == true) {
					return submitted_ios;
				}
			}
			for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
				if (!qos->rate_limits[i].update_quota) {
					continue;
				}

				qos->rate_limits[i].update_quota(&qos->rate_limits[i], bdev_io);
			}
		}

		bdev_io = TAILQ_FIRST(&qos->queued);
		TAILQ_REMOVE(&qos->queued, bdev_io, internal.link);
		ch->io_outstanding++;
		shared_resource->io_outstanding++;
		to_limit_io = _spdk_bdev_qos_io_to_limit(bdev_io);
		if (to_limit_io == true) {
			io_size_in_byte = _spdk_bdev_get_io_size_in_byte(bdev_io);
			_spdk_bdev_qos_update_per_io(qos, io_size_in_byte);
		}
		bdev->fn_table->submit_request(ch->channel, bdev_io);
		submitted_ios++;
	}
@@ -1688,6 +1724,8 @@ spdk_bdev_qos_update_max_quota_per_timeslice(struct spdk_bdev_qos *qos)

		qos->rate_limits[i].remaining_this_timeslice = qos->rate_limits[i].max_per_timeslice;
	}

	_spdk_bdev_qos_set_ops(qos);
}

static int