[RFC PATCH v2 06/11] bfq: expire other class if CLASS_RT is waiting

From: brookxu
Date: Fri Mar 12 2021 - 06:09:52 EST


From: Chunguang Xu <brookxu@xxxxxxxxxxx>

Expire bfqq not belong to CLASS_RT and CLASS_RT is waiting for
service, we can further guarantee the latency for CLASS_RT.

Signed-off-by: Chunguang Xu <brookxu@xxxxxxxxxxx>
---
block/bfq-iosched.c | 15 ++++++++++-----
block/bfq-iosched.h | 8 ++++++++
block/bfq-wf2q.c | 12 ++++++++++++
3 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index ab00b664348c..8af73473c45c 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -428,6 +428,7 @@ void bfq_schedule_dispatch(struct bfq_data *bfqd)
}
}

+#define bfq_class_rt(bfqq) ((bfqq)->ioprio_class == IOPRIO_CLASS_RT)
#define bfq_class_idle(bfqq) ((bfqq)->ioprio_class == IOPRIO_CLASS_IDLE)

#define bfq_sample_valid(samples) ((samples) > 80)
@@ -4709,12 +4710,16 @@ static struct request *bfq_dispatch_rq_from_bfqq(struct bfq_data *bfqd,
/*
* Expire bfqq, pretending that its budget expired, if bfqq
* belongs to CLASS_IDLE and other queues are waiting for
- * service.
+ * service, or if bfqq not belongs to CLASS_RT and CLASS_RT
+ * is waiting for service.
*/
- if (!(bfq_tot_busy_queues(bfqd) > 1 && bfq_class_idle(bfqq)))
- goto return_rq;
-
- bfq_bfqq_expire(bfqd, bfqq, false, BFQQE_BUDGET_EXHAUSTED);
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+ if ((bfq_tot_busy_queues(bfqd) > 1 && bfq_class_idle(bfqq)) ||
+ (!bfq_class_rt(bfqq) && bfqd->busy_groups[0]))
+#else
+ if (bfq_tot_busy_queues(bfqd) > 1 && bfq_class_idle(bfqq))
+#endif
+ bfq_bfqq_expire(bfqd, bfqq, false, BFQQE_BUDGET_EXHAUSTED);

return_rq:
return rq;
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
index de7301664ad3..6b87ba53db94 100644
--- a/block/bfq-iosched.h
+++ b/block/bfq-iosched.h
@@ -531,6 +531,14 @@ struct bfq_data {
*/
unsigned int num_groups_with_pending_reqs;

+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+ /*
+ * Per-class (RT, BE, IDLE) number of bfq_groups waiting for
+ * service.
+ */
+ unsigned int busy_groups[3];
+#endif
+
/*
* Per-class (RT, BE, IDLE) number of bfq_queues containing
* requests (including the queue in service, even if it is
diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c
index 0ac35fd4f2ab..f6c67a80e454 100644
--- a/block/bfq-wf2q.c
+++ b/block/bfq-wf2q.c
@@ -1032,11 +1032,14 @@ static void __bfq_activate_entity(struct bfq_entity *entity,
if (!bfq_entity_to_bfqq(entity)) { /* bfq_group */
struct bfq_group *bfqg = bfq_entity_to_bfqg(entity);
struct bfq_data *bfqd = bfqg->bfqd;
+ int idx = bfq_class_idx(entity);

if (!entity->in_groups_with_pending_reqs) {
entity->in_groups_with_pending_reqs = true;
bfqd->num_groups_with_pending_reqs++;
}
+
+ bfqd->busy_groups[idx]++;
}
#endif

@@ -1188,6 +1191,9 @@ bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree)
{
struct bfq_sched_data *sd = entity->sched_data;
struct bfq_service_tree *st;
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+ struct bfq_group *bfqg;
+#endif
int idx = bfq_class_idx(entity);
bool is_in_service;

@@ -1229,6 +1235,12 @@ bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree)
bfq_idle_insert(st, entity);

sd->bfq_class_last_service[idx] = jiffies;
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+ bfqg = bfq_entity_to_bfqg(entity);
+ if (bfqg)
+ bfqg->bfqd->busy_groups[idx]--;
+#endif
+
return true;
}

--
2.30.0