From b0427430218735bd49881ccc545a59bc64e332a4 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Sat, 17 May 2014 14:11:09 +0200 Subject: [PATCH] block: Switch from BFQ-v7r3 for 3.5.0 to BFQ-v7r4 for 3.5.0 . BUGFIX. Modified the code so as to be robust against late detection of NCQ support for a rotational device. . BUGFIX. Removed a bug that hindered the correct throughput distribution on flash-based devices when not every process had to receive the same fraction of the throughput. This fix entailed also a little efficiency improvement, because it implied the removal of a short function executed in a hot path. . CODESTYLE IMPROVEMENT: removed quoted strings split across lines. Signed-off-by: Paolo Valente Reported-by: Steven Barrett Reported-by: Claire Farron Signed-off-by: Arianna Avanzini --- block/bfq-iosched.c | 69 ++++++++++++++++------------------------------------- block/bfq-sched.c | 8 +++---- block/bfq.h | 26 +++++++++++++++----- 3 files changed, 45 insertions(+), 58 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 118e649..262c920 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -668,8 +668,7 @@ static void bfq_add_request(struct request *rq) bfqq->wr_cur_max_time = bfqd->bfq_wr_rt_max_time; bfq_log_bfqq(bfqd, bfqq, - "wrais starting at %lu, " - "rais_max_time %u", + "wrais starting at %lu, rais_max_time %u", jiffies, jiffies_to_msecs(bfqq->wr_cur_max_time)); } else if (old_wr_coeff > 1) { @@ -680,11 +679,10 @@ static void bfq_add_request(struct request *rq) !soft_rt) { bfqq->wr_coeff = 1; bfq_log_bfqq(bfqd, bfqq, - "wrais ending at %lu, " - "rais_max_time %u", - jiffies, - jiffies_to_msecs(bfqq-> - wr_cur_max_time)); + "wrais ending at %lu, rais_max_time %u", + jiffies, + jiffies_to_msecs(bfqq-> + wr_cur_max_time)); } else if (time_before( bfqq->last_wr_start_finish + bfqq->wr_cur_max_time, @@ -759,10 +757,9 @@ add_bfqq_busy: bfqd->raised_busy_queues++; entity->ioprio_changed = 1; bfq_log_bfqq(bfqd, bfqq, - "non-idle wrais starting at %lu, " - "rais_max_time %u", - jiffies, - jiffies_to_msecs(bfqq->wr_cur_max_time)); + "non-idle wrais starting at %lu, rais_max_time %u", + jiffies, + jiffies_to_msecs(bfqq->wr_cur_max_time)); } if (prev != bfqq->next_rq) bfq_updated_next_req(bfqd, bfqq); @@ -1375,26 +1372,6 @@ static inline unsigned long bfq_min_budget(struct bfq_data *bfqd) return bfqd->bfq_max_budget / 32; } -/* - * Decides whether idling should be done for given device and - * given in-service queue. - */ -static inline bool bfq_queue_nonrot_noidle(struct bfq_data *bfqd, - struct bfq_queue *in_service_bfqq) -{ - if (in_service_bfqq == NULL) - return false; - /* - * If the device is non-rotational, and hence has no seek penalty, - * disable idling; but do so only if: - * - device does not support queuing, otherwise we still have - * a problem with sync vs async workloads; - * - the queue is not weight-raised, to preserve guarantees. - */ - return blk_queue_nonrot(bfqd->queue) && bfqd->hw_tag && - (in_service_bfqq->wr_coeff == 1); -} - static void bfq_arm_slice_timer(struct bfq_data *bfqd) { struct bfq_queue *bfqq = bfqd->in_service_queue; @@ -1952,7 +1929,7 @@ static void bfq_bfqq_expire(struct bfq_data *bfqd, if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT && !bfq_bfqq_constantly_seeky(bfqq)) { bfq_mark_bfqq_constantly_seeky(bfqq); - if (!blk_queue_nonrot(bfqq->bfqd->queue) && bfqd->hw_tag) + if (!blk_queue_nonrot(bfqd->queue)) bfqd->const_seeky_busy_in_flight_queues++; } @@ -2204,8 +2181,7 @@ static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) struct bfq_data *bfqd = bfqq->bfqd; return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 && - bfq_bfqq_must_not_expire(bfqq) && - !bfq_queue_nonrot_noidle(bfqd, bfqq); + bfq_bfqq_must_not_expire(bfqq); } /* @@ -2292,13 +2268,12 @@ static void bfq_update_raising_data(struct bfq_data *bfqd, struct bfq_entity *entity = &bfqq->entity; if (bfqq->wr_coeff > 1) { /* queue is being weight-raised */ bfq_log_bfqq(bfqd, bfqq, - "raising period dur %u/%u msec, " - "old raising coeff %u, w %d(%d)", - jiffies_to_msecs(jiffies - - bfqq->last_wr_start_finish), - jiffies_to_msecs(bfqq->wr_cur_max_time), - bfqq->wr_coeff, - bfqq->entity.weight, bfqq->entity.orig_weight); + "raising period dur %u/%u msec, old raising coeff %u, w %d(%d)", + jiffies_to_msecs(jiffies - + bfqq->last_wr_start_finish), + jiffies_to_msecs(bfqq->wr_cur_max_time), + bfqq->wr_coeff, + bfqq->entity.weight, bfqq->entity.orig_weight); BUG_ON(bfqq != bfqd->in_service_queue && entity->weight != entity->orig_weight * bfqq->wr_coeff); @@ -2313,8 +2288,7 @@ static void bfq_update_raising_data(struct bfq_data *bfqd, bfqq->wr_cur_max_time)) { bfqq->last_wr_start_finish = jiffies; bfq_log_bfqq(bfqd, bfqq, - "wrais ending at %lu, " - "rais_max_time %u", + "wrais ending at %lu, rais_max_time %u", bfqq->last_wr_start_finish, jiffies_to_msecs(bfqq-> wr_cur_max_time)); @@ -2939,7 +2913,7 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, bfq_update_io_seektime(bfqd, bfqq, rq); if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) { bfq_clear_bfqq_constantly_seeky(bfqq); - if (!blk_queue_nonrot(bfqq->bfqd->queue) && bfqd->hw_tag) { + if (!blk_queue_nonrot(bfqd->queue)) { BUG_ON(!bfqd->const_seeky_busy_in_flight_queues); bfqd->const_seeky_busy_in_flight_queues--; } @@ -3100,7 +3074,7 @@ static void bfq_completed_request(struct request_queue *q, struct request *rq) if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) { bfq_weights_tree_remove(bfqd, &bfqq->entity, &bfqd->queue_weights_tree); - if (!blk_queue_nonrot(bfqq->bfqd->queue) && bfqd->hw_tag) { + if (!blk_queue_nonrot(bfqd->queue)) { BUG_ON(!bfqd->busy_in_flight_queues); bfqd->busy_in_flight_queues--; if (bfq_bfqq_constantly_seeky(bfqq)) { @@ -3589,8 +3563,7 @@ static ssize_t bfq_weights_show(struct elevator_queue *e, char *page) num_char += sprintf(page + num_char, "Active:\n"); list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) { num_char += sprintf(page + num_char, - "pid%d: weight %hu, nr_queued %d %d," - " dur %d/%u\n", + "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n", bfqq->pid, bfqq->entity.weight, bfqq->queued[0], @@ -3843,7 +3816,7 @@ static int __init bfq_init(void) device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; elv_register(&iosched_bfq); - pr_info("BFQ I/O-scheduler version: v7r3"); + pr_info("BFQ I/O-scheduler version: v7r4"); return 0; } diff --git a/block/bfq-sched.c b/block/bfq-sched.c index daf1b4b..0fd077c 100644 --- a/block/bfq-sched.c +++ b/block/bfq-sched.c @@ -381,7 +381,7 @@ static void bfq_active_insert(struct bfq_service_tree *st, BUG_ON(!bfqd); bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree); } - if (bfqd->hw_tag && bfqg != bfqd->root_group) { + if (bfqg != bfqd->root_group) { BUG_ON(!bfqg); BUG_ON(!bfqd); bfqg->active_entities++; @@ -492,7 +492,7 @@ static void bfq_active_extract(struct bfq_service_tree *st, bfq_weights_tree_remove(bfqd, entity, &bfqd->group_weights_tree); } - if (bfqd->hw_tag && bfqg != bfqd->root_group) { + if (bfqg != bfqd->root_group) { BUG_ON(!bfqg); BUG_ON(!bfqd); BUG_ON(!bfqg->active_entities); @@ -1130,7 +1130,7 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, if (!bfqq->dispatched) { bfq_weights_tree_remove(bfqd, &bfqq->entity, &bfqd->queue_weights_tree); - if (!blk_queue_nonrot(bfqd->queue) && bfqd->hw_tag) { + if (!blk_queue_nonrot(bfqd->queue)) { BUG_ON(!bfqd->busy_in_flight_queues); bfqd->busy_in_flight_queues--; if (bfq_bfqq_constantly_seeky(bfqq)) { @@ -1165,7 +1165,7 @@ static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) if (bfqq->wr_coeff == 1) bfq_weights_tree_add(bfqd, &bfqq->entity, &bfqd->queue_weights_tree); - if (!blk_queue_nonrot(bfqd->queue) && bfqd->hw_tag) { + if (!blk_queue_nonrot(bfqd->queue)) { bfqd->busy_in_flight_queues++; if (bfq_bfqq_constantly_seeky(bfqq)) bfqd->const_seeky_busy_in_flight_queues++; diff --git a/block/bfq.h b/block/bfq.h index 8cb1692..ac12ea4 100644 --- a/block/bfq.h +++ b/block/bfq.h @@ -1,5 +1,5 @@ /* - * BFQ-v7r3 for 3.5.0: data structures and common functions prototypes. + * BFQ-v7r4 for 3.5.0: data structures and common functions prototypes. * * Based on ideas and code from CFQ: * Copyright (C) 2003 Jens Axboe @@ -342,14 +342,28 @@ enum bfq_device_speed { * queue under service, even if it is idling). * @busy_in_flight_queues: number of @bfq_queues containing pending or * in-flight requests, plus the @bfq_queue in service, - * even if idle but waiting for the possible arrival - * of its next sync request. + * even if idle but waiting for the possible arrival + * of its next sync request. This field is updated only + * if the device is rotational, but used only if the + * device is also NCQ-capable. The reason why the field + * is updated also for non-NCQ-capable rotational + * devices is related to the fact that the value of + * hw_tag may be set also later than when this field may + * need to be incremented for the first time(s). + * Taking also this possibility into account, to avoid + * unbalanced increments/decrements, would imply more + * overhead than just updating this field regardless of + * the value of hw_tag. * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues * (that is, seeky queues that expired * for budget timeout at least once) * containing pending or in-flight - * requests, including the in-service - * @bfq_queue if constantly seeky. + * requests, including the in-service + * @bfq_queue if constantly seeky. This + * field is updated only if the device + * is rotational, but used only if the + * device is also NCQ-capable (see the + * comments to @busy_in_flight_queues). * @raised_busy_queues: number of weight-raised busy bfq_queues. * @queued: number of queued requests. * @rq_in_driver: number of requests dispatched and waiting for completion. @@ -561,7 +575,7 @@ enum bfqq_expiration { * @active_entities: number of active entities belonging to the group; unused * for the root group. Used to know whether there are groups * with more than one active @bfq_entity (see the comments - * to the function bfq_bfqq_must_not_expire()). + * to the function bfq_bfqq_must_not_expire()). * * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup * there is a set of bfq_groups, each one collecting the lower-level -- 1.9.2