From: brookxu <brookxu.cn@gmail.com> To: paolo.valente@linaro.org, axboe@kernel.dk, tj@kernel.org Cc: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/8] bfq: keep the minimun bandwidth for CLASS_BE Date: Tue, 20 Apr 2021 19:20:21 +0800 [thread overview] Message-ID: <49f0e733ab19bee96fce0bdd205366a5b0d3b51e.1618916839.git.brookxu@tencent.com> (raw) In-Reply-To: <cover.1618916839.git.brookxu@tencent.com> In-Reply-To: <cover.1618916839.git.brookxu@tencent.com> From: Chunguang Xu <brookxu@tencent.com> CLASS_RT will preempt other classes, which may starve. At present, CLASS_IDLE has alleviated the starvation problem through the minimum bandwidth mechanism. Similarly, we should do the same for CLASS_BE. Signed-off-by: Chunguang Xu <brookxu@tencent.com> --- block/bfq-iosched.c | 6 ++++-- block/bfq-iosched.h | 11 ++++++---- block/bfq-wf2q.c | 59 ++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 29940ec..89d4646 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -6537,9 +6537,11 @@ static void bfq_init_root_group(struct bfq_group *root_group, root_group->bfqd = bfqd; #endif root_group->rq_pos_tree = RB_ROOT; - for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { root_group->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; - root_group->sched_data.bfq_class_idle_last_service = jiffies; + root_group->sched_data.bfq_class_last_service[i] = jiffies; + } + root_group->sched_data.class_timeout_last_check = jiffies; } static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h index 28d8590..da636a8 100644 --- a/block/bfq-iosched.h +++ b/block/bfq-iosched.h @@ -13,7 +13,7 @@ #include "blk-cgroup-rwstat.h" #define BFQ_IOPRIO_CLASSES 3 -#define BFQ_CL_IDLE_TIMEOUT (HZ/5) +#define BFQ_CLASS_TIMEOUT (HZ/5) #define BFQ_MIN_WEIGHT 1 #define BFQ_MAX_WEIGHT 1000 @@ -97,9 +97,12 @@ struct bfq_sched_data { struct bfq_entity *next_in_service; /* array of service trees, one per ioprio_class */ struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; - /* last time CLASS_IDLE was served */ - unsigned long bfq_class_idle_last_service; - + /* last time the class was served */ + unsigned long bfq_class_last_service[BFQ_IOPRIO_CLASSES]; + /* last time class timeout was checked */ + unsigned long class_timeout_last_check; + /* next index to check class timeout */ + unsigned int next_class_index; }; /** diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c index 276f225..619ed21 100644 --- a/block/bfq-wf2q.c +++ b/block/bfq-wf2q.c @@ -1168,6 +1168,7 @@ 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; + int idx = bfq_class_idx(entity); bool is_in_service; if (!entity->on_st_or_in_serv) /* @@ -1207,6 +1208,7 @@ bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree) else bfq_idle_insert(st, entity); + sd->bfq_class_last_service[idx] = jiffies; return true; } @@ -1435,6 +1437,45 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st, return entity; } +static int bfq_select_next_class(struct bfq_sched_data *sd) +{ + struct bfq_service_tree *st = sd->service_tree; + unsigned long last_check, last_serve; + int i, class_idx, next_class = 0; + bool found = false; + + /* + * we needed to guarantee a minimum bandwidth for each class (if + * there is some active entity in this class). This should also + * mitigate priority-inversion problems in case a low priority + * task is holding file system resources. + */ + last_check = sd->class_timeout_last_check; + if (time_is_after_jiffies(last_check + BFQ_CLASS_TIMEOUT)) + return next_class; + + sd->class_timeout_last_check = jiffies; + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { + class_idx = (sd->next_class_index + i) % BFQ_IOPRIO_CLASSES; + last_serve = sd->bfq_class_last_service[class_idx]; + + if (time_is_after_jiffies(last_serve + BFQ_CLASS_TIMEOUT)) + continue; + + if (!RB_EMPTY_ROOT(&(st + class_idx)->active)) { + if (found) + continue; + + next_class = class_idx++; + class_idx %= BFQ_IOPRIO_CLASSES; + sd->next_class_index = class_idx; + found = true; + } + sd->bfq_class_last_service[class_idx] = jiffies; + } + return next_class; +} + /** * bfq_lookup_next_entity - return the first eligible entity in @sd. * @sd: the sched_data. @@ -1448,24 +1489,8 @@ static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, bool expiration) { struct bfq_service_tree *st = sd->service_tree; - struct bfq_service_tree *idle_class_st = st + (BFQ_IOPRIO_CLASSES - 1); struct bfq_entity *entity = NULL; - int class_idx = 0; - - /* - * Choose from idle class, if needed to guarantee a minimum - * bandwidth to this class (and if there is some active entity - * in idle class). This should also mitigate - * priority-inversion problems in case a low priority task is - * holding file system resources. - */ - if (time_is_before_jiffies(sd->bfq_class_idle_last_service + - BFQ_CL_IDLE_TIMEOUT)) { - if (!RB_EMPTY_ROOT(&idle_class_st->active)) - class_idx = BFQ_IOPRIO_CLASSES - 1; - /* About to be served if backlogged, or not yet backlogged */ - sd->bfq_class_idle_last_service = jiffies; - } + int class_idx = bfq_select_next_class(sd); /* * Find the next entity to serve for the highest-priority -- 1.8.3.1
WARNING: multiple messages have this Message-ID (diff)
From: brookxu <brookxu.cn@gmail.com> To: paolo.valente@linaro.org, axboe@kernel.dk Cc: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RESEND PATCH 4/8] bfq: keep the minimun bandwidth for CLASS_BE Date: Thu, 10 Jun 2021 15:22:33 +0800 [thread overview] Message-ID: <49f0e733ab19bee96fce0bdd205366a5b0d3b51e.1618916839.git.brookxu@tencent.com> (raw) Message-ID: <20210610072233.PYL1PUn_OqJ7je0WFh3xeaeTUOWNLXb9z9qDCgcu-CU@z> (raw) In-Reply-To: <1ce935f1bb10e0c7ecea7b79b826ff4cfc89acf0.1618916839.git.brookxu@tencent.com> In-Reply-To: <cover.1618916839.git.brookxu@tencent.com> From: Chunguang Xu <brookxu@tencent.com> CLASS_RT will preempt other classes, which may starve. At present, CLASS_IDLE has alleviated the starvation problem through the minimum bandwidth mechanism. Similarly, we should do the same for CLASS_BE. Signed-off-by: Chunguang Xu <brookxu@tencent.com> --- block/bfq-iosched.c | 6 ++++-- block/bfq-iosched.h | 11 ++++++---- block/bfq-wf2q.c | 59 ++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 29940ec..89d4646 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -6537,9 +6537,11 @@ static void bfq_init_root_group(struct bfq_group *root_group, root_group->bfqd = bfqd; #endif root_group->rq_pos_tree = RB_ROOT; - for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { root_group->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; - root_group->sched_data.bfq_class_idle_last_service = jiffies; + root_group->sched_data.bfq_class_last_service[i] = jiffies; + } + root_group->sched_data.class_timeout_last_check = jiffies; } static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h index 28d8590..da636a8 100644 --- a/block/bfq-iosched.h +++ b/block/bfq-iosched.h @@ -13,7 +13,7 @@ #include "blk-cgroup-rwstat.h" #define BFQ_IOPRIO_CLASSES 3 -#define BFQ_CL_IDLE_TIMEOUT (HZ/5) +#define BFQ_CLASS_TIMEOUT (HZ/5) #define BFQ_MIN_WEIGHT 1 #define BFQ_MAX_WEIGHT 1000 @@ -97,9 +97,12 @@ struct bfq_sched_data { struct bfq_entity *next_in_service; /* array of service trees, one per ioprio_class */ struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; - /* last time CLASS_IDLE was served */ - unsigned long bfq_class_idle_last_service; - + /* last time the class was served */ + unsigned long bfq_class_last_service[BFQ_IOPRIO_CLASSES]; + /* last time class timeout was checked */ + unsigned long class_timeout_last_check; + /* next index to check class timeout */ + unsigned int next_class_index; }; /** diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c index 276f225..619ed21 100644 --- a/block/bfq-wf2q.c +++ b/block/bfq-wf2q.c @@ -1168,6 +1168,7 @@ 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; + int idx = bfq_class_idx(entity); bool is_in_service; if (!entity->on_st_or_in_serv) /* @@ -1207,6 +1208,7 @@ bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree) else bfq_idle_insert(st, entity); + sd->bfq_class_last_service[idx] = jiffies; return true; } @@ -1435,6 +1437,45 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st, return entity; } +static int bfq_select_next_class(struct bfq_sched_data *sd) +{ + struct bfq_service_tree *st = sd->service_tree; + unsigned long last_check, last_serve; + int i, class_idx, next_class = 0; + bool found = false; + + /* + * we needed to guarantee a minimum bandwidth for each class (if + * there is some active entity in this class). This should also + * mitigate priority-inversion problems in case a low priority + * task is holding file system resources. + */ + last_check = sd->class_timeout_last_check; + if (time_is_after_jiffies(last_check + BFQ_CLASS_TIMEOUT)) + return next_class; + + sd->class_timeout_last_check = jiffies; + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { + class_idx = (sd->next_class_index + i) % BFQ_IOPRIO_CLASSES; + last_serve = sd->bfq_class_last_service[class_idx]; + + if (time_is_after_jiffies(last_serve + BFQ_CLASS_TIMEOUT)) + continue; + + if (!RB_EMPTY_ROOT(&(st + class_idx)->active)) { + if (found) + continue; + + next_class = class_idx++; + class_idx %= BFQ_IOPRIO_CLASSES; + sd->next_class_index = class_idx; + found = true; + } + sd->bfq_class_last_service[class_idx] = jiffies; + } + return next_class; +} + /** * bfq_lookup_next_entity - return the first eligible entity in @sd. * @sd: the sched_data. @@ -1448,24 +1489,8 @@ static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, bool expiration) { struct bfq_service_tree *st = sd->service_tree; - struct bfq_service_tree *idle_class_st = st + (BFQ_IOPRIO_CLASSES - 1); struct bfq_entity *entity = NULL; - int class_idx = 0; - - /* - * Choose from idle class, if needed to guarantee a minimum - * bandwidth to this class (and if there is some active entity - * in idle class). This should also mitigate - * priority-inversion problems in case a low priority task is - * holding file system resources. - */ - if (time_is_before_jiffies(sd->bfq_class_idle_last_service + - BFQ_CL_IDLE_TIMEOUT)) { - if (!RB_EMPTY_ROOT(&idle_class_st->active)) - class_idx = BFQ_IOPRIO_CLASSES - 1; - /* About to be served if backlogged, or not yet backlogged */ - sd->bfq_class_idle_last_service = jiffies; - } + int class_idx = bfq_select_next_class(sd); /* * Find the next entity to serve for the highest-priority -- 1.8.3.1
next prev parent reply other threads:[~2021-04-20 11:20 UTC|newest] Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-04-20 11:20 [PATCH 0/8] bfq: misc updates brookxu 2021-04-20 11:20 ` [PATCH 1/8] bfq: introduce bfq_entity_to_bfqg helper method brookxu 2021-06-10 7:22 ` [RESEND PATCH " brookxu 2021-06-10 8:31 ` Oleksandr Natalenko 2021-06-10 9:05 ` brookxu 2021-06-10 9:18 ` Piotr Górski 2021-04-20 11:20 ` [PATCH 2/8] bfq: convert the type of bfq_group.bfqd to bfq_data* brookxu 2021-06-10 7:22 ` [RESEND PATCH " brookxu 2021-04-20 11:20 ` [PATCH 3/8] bfq: limit the IO depth of CLASS_IDLE to 1 brookxu 2021-06-10 7:22 ` [RESEND PATCH " brookxu 2021-04-20 11:20 ` brookxu [this message] 2021-06-10 7:22 ` [RESEND PATCH 4/8] bfq: keep the minimun bandwidth for CLASS_BE brookxu 2021-04-20 11:20 ` [PATCH 5/8] bfq: remove unnecessary initialization logic brookxu 2021-06-10 7:22 ` [RESEND PATCH " brookxu 2021-04-20 11:20 ` [PATCH 6/8] bfq: optimize the calculation of bfq_weight_to_ioprio() brookxu 2021-06-10 7:22 ` [RESEND PATCH " brookxu 2021-04-20 11:20 ` [PATCH 7/8] bfq: reset entity->prio_changed in bfq_init_entity() brookxu 2021-06-10 7:22 ` [RESEND PATCH " brookxu 2021-04-20 11:20 ` [PATCH 8/8] bfq: remove unnecessary BFQ_DEFAULT_GRP_IOPRIO brookxu 2021-06-10 7:22 ` [RESEND PATCH " brookxu
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=49f0e733ab19bee96fce0bdd205366a5b0d3b51e.1618916839.git.brookxu@tencent.com \ --to=brookxu.cn@gmail.com \ --cc=axboe@kernel.dk \ --cc=linux-block@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=paolo.valente@linaro.org \ --cc=tj@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).