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). */ /** Maximum allowed IOs or bytes to be issued in one timeslice (e.g., 1ms). */
uint32_t max_per_timeslice; 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 { 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 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; int i;
for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; 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) { 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; continue;
} }
switch (i) { switch (i) {
case SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT: 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; break;
case SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT: 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; break;
case SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES:
default: default:
break; break;
} }
@ -1275,30 +1306,35 @@ _spdk_bdev_qos_update_per_io(struct spdk_bdev_qos *qos, uint64_t io_size_in_byte
static int static int
_spdk_bdev_qos_io_submit(struct spdk_bdev_channel *ch, struct spdk_bdev_qos *qos) _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 *bdev = ch->bdev;
struct spdk_bdev_shared_resource *shared_resource = ch->shared_resource; struct spdk_bdev_shared_resource *shared_resource = ch->shared_resource;
int i, submitted_ios = 0; 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) {
for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { if (_spdk_bdev_qos_io_to_limit(bdev_io) == true) {
if (qos->rate_limits[i].max_per_timeslice > 0 && for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
(qos->rate_limits[i].remaining_this_timeslice <= 0)) { if (!qos->rate_limits[i].queue_io) {
return submitted_ios; 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); TAILQ_REMOVE(&qos->queued, bdev_io, internal.link);
ch->io_outstanding++; ch->io_outstanding++;
shared_resource->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); bdev->fn_table->submit_request(ch->channel, bdev_io);
submitted_ios++; 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; qos->rate_limits[i].remaining_this_timeslice = qos->rate_limits[i].max_per_timeslice;
} }
_spdk_bdev_qos_set_ops(qos);
} }
static int static int