From 0dba6fce0902446d1e134e345f9af4c79e06351c Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Sat, 17 May 2014 16:23:53 +0200 Subject: [PATCH] block: Switch from BFQ-v7r3 for 3.0.0 to BFQ-v7r4 for 3.0.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 | 64 ++++++++++++++++------------------------------------- block/bfq-sched.c | 8 +++---- block/bfq.h | 26 +++++++++++++++++----- 3 files changed, 43 insertions(+), 55 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 435a131..588063d4 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -686,8 +686,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)); @@ -700,10 +699,9 @@ 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-> + "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 + @@ -779,10 +777,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); @@ -1410,26 +1407,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; @@ -1989,7 +1966,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++; } @@ -2243,8 +2220,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); } /* @@ -2331,13 +2307,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); @@ -2352,8 +2327,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)); @@ -2928,7 +2902,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--; } @@ -3091,7 +3065,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)) { @@ -3912,7 +3886,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 960732a..c5be9ed 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); @@ -1128,7 +1128,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)) { @@ -1163,7 +1163,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 3e30274..70f89db 100644 --- a/block/bfq.h +++ b/block/bfq.h @@ -1,5 +1,5 @@ /* - * BFQ-v7r3 for 3.0: data structures and common functions prototypes. + * BFQ-v7r4 for 3.0: data structures and common functions prototypes. * * Based on ideas and code from CFQ: * Copyright (C) 2003 Jens Axboe @@ -309,14 +309,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. @@ -534,7 +548,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