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: GangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/c/438157
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
GangCao 2018-12-24 16:46:42 -05:00 committed by Jim Harris
parent ff3c2e3c84
commit cd4dd43ab8

View File

@ -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_update_per_io(struct spdk_bdev_qos *qos, uint64_t io_size_in_byte)
_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_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)) {
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)) {
return submitted_ios;
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].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