summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorPaolo Valente <paolo.valente@linaro.org>2017-07-03 04:00:10 -0400
committerJens Axboe <axboe@kernel.dk>2017-07-03 18:50:00 -0400
commit431b17f9d5453533cba7d73e7e40428e4f90b35d (patch)
treee42cf25bcbfbc315f6b4fc3660dce0890cfdbbe2 /block
parent7a69f9c60b49699579f5bfb71f928cceba0afe1a (diff)
block, bfq: don't change ioprio class for a bfq_queue on a service tree
On each deactivation or re-scheduling (after being served) of a bfq_queue, BFQ invokes the function __bfq_entity_update_weight_prio(), to perform pending updates of ioprio, weight and ioprio class for the bfq_queue. BFQ also invokes this function on I/O-request dispatches, to raise or lower weights more quickly when needed, thereby improving latency. However, the entity representing the bfq_queue may be on the active (sub)tree of a service tree when this happens, and, although with a very low probability, the bfq_queue may happen to also have a pending change of its ioprio class. If both conditions hold when __bfq_entity_update_weight_prio() is invoked, then the entity moves to a sort of hybrid state: the new service tree for the entity, as returned by bfq_entity_service_tree(), differs from service tree on which the entity still is. The functions that handle activations and deactivations of entities do not cope with such a hybrid state (and would need to become more complex to cope). This commit addresses this issue by just making __bfq_entity_update_weight_prio() not perform also a possible pending change of ioprio class, when invoked on an I/O-request dispatch for a bfq_queue. Such a change is thus postponed to when __bfq_entity_update_weight_prio() is invoked on deactivation or re-scheduling of the bfq_queue. Reported-by: Marco Piazza <mpiazza@gmail.com> Reported-by: Laurentiu Nicola <lnicola@dend.ro> Signed-off-by: Paolo Valente <paolo.valente@linaro.org> Tested-by: Marco Piazza <mpiazza@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/bfq-iosched.c14
-rw-r--r--block/bfq-iosched.h3
-rw-r--r--block/bfq-wf2q.c39
3 files changed, 46 insertions, 10 deletions
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 12bbc6b8657d..60a6835265fc 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -3483,11 +3483,17 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq)
3483 } 3483 }
3484 } 3484 }
3485 } 3485 }
3486 /* Update weight both if it must be raised and if it must be lowered */ 3486 /*
3487 * To improve latency (for this or other queues), immediately
3488 * update weight both if it must be raised and if it must be
3489 * lowered. Since, entity may be on some active tree here, and
3490 * might have a pending change of its ioprio class, invoke
3491 * next function with the last parameter unset (see the
3492 * comments on the function).
3493 */
3487 if ((entity->weight > entity->orig_weight) != (bfqq->wr_coeff > 1)) 3494 if ((entity->weight > entity->orig_weight) != (bfqq->wr_coeff > 1))
3488 __bfq_entity_update_weight_prio( 3495 __bfq_entity_update_weight_prio(bfq_entity_service_tree(entity),
3489 bfq_entity_service_tree(entity), 3496 entity, false);
3490 entity);
3491} 3497}
3492 3498
3493/* 3499/*
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
index 5c3bf9861492..8fd83b885774 100644
--- a/block/bfq-iosched.h
+++ b/block/bfq-iosched.h
@@ -892,7 +892,8 @@ void bfq_put_idle_entity(struct bfq_service_tree *st,
892 struct bfq_entity *entity); 892 struct bfq_entity *entity);
893struct bfq_service_tree * 893struct bfq_service_tree *
894__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, 894__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
895 struct bfq_entity *entity); 895 struct bfq_entity *entity,
896 bool update_class_too);
896void bfq_bfqq_served(struct bfq_queue *bfqq, int served); 897void bfq_bfqq_served(struct bfq_queue *bfqq, int served);
897void bfq_bfqq_charge_time(struct bfq_data *bfqd, struct bfq_queue *bfqq, 898void bfq_bfqq_charge_time(struct bfq_data *bfqd, struct bfq_queue *bfqq,
898 unsigned long time_ms); 899 unsigned long time_ms);
diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c
index 8726ede19eef..5ec05cd42b80 100644
--- a/block/bfq-wf2q.c
+++ b/block/bfq-wf2q.c
@@ -694,10 +694,28 @@ struct bfq_service_tree *bfq_entity_service_tree(struct bfq_entity *entity)
694 return sched_data->service_tree + idx; 694 return sched_data->service_tree + idx;
695} 695}
696 696
697 697/*
698 * Update weight and priority of entity. If update_class_too is true,
699 * then update the ioprio_class of entity too.
700 *
701 * The reason why the update of ioprio_class is controlled through the
702 * last parameter is as follows. Changing the ioprio class of an
703 * entity implies changing the destination service trees for that
704 * entity. If such a change occurred when the entity is already on one
705 * of the service trees for its previous class, then the state of the
706 * entity would become more complex: none of the new possible service
707 * trees for the entity, according to bfq_entity_service_tree(), would
708 * match any of the possible service trees on which the entity
709 * is. Complex operations involving these trees, such as entity
710 * activations and deactivations, should take into account this
711 * additional complexity. To avoid this issue, this function is
712 * invoked with update_class_too unset in the points in the code where
713 * entity may happen to be on some tree.
714 */
698struct bfq_service_tree * 715struct bfq_service_tree *
699__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, 716__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
700 struct bfq_entity *entity) 717 struct bfq_entity *entity,
718 bool update_class_too)
701{ 719{
702 struct bfq_service_tree *new_st = old_st; 720 struct bfq_service_tree *new_st = old_st;
703 721
@@ -739,9 +757,15 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
739 bfq_weight_to_ioprio(entity->orig_weight); 757 bfq_weight_to_ioprio(entity->orig_weight);
740 } 758 }
741 759
742 if (bfqq) 760 if (bfqq && update_class_too)
743 bfqq->ioprio_class = bfqq->new_ioprio_class; 761 bfqq->ioprio_class = bfqq->new_ioprio_class;
744 entity->prio_changed = 0; 762
763 /*
764 * Reset prio_changed only if the ioprio_class change
765 * is not pending any longer.
766 */
767 if (!bfqq || bfqq->ioprio_class == bfqq->new_ioprio_class)
768 entity->prio_changed = 0;
745 769
746 /* 770 /*
747 * NOTE: here we may be changing the weight too early, 771 * NOTE: here we may be changing the weight too early,
@@ -867,7 +891,12 @@ static void bfq_update_fin_time_enqueue(struct bfq_entity *entity,
867{ 891{
868 struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 892 struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
869 893
870 st = __bfq_entity_update_weight_prio(st, entity); 894 /*
895 * When this function is invoked, entity is not in any service
896 * tree, then it is safe to invoke next function with the last
897 * parameter set (see the comments on the function).
898 */
899 st = __bfq_entity_update_weight_prio(st, entity, true);
871 bfq_calc_finish(entity, entity->budget); 900 bfq_calc_finish(entity, entity->budget);
872 901
873 /* 902 /*