Skip to content

Commit 24d90bb

Browse files
Algodev-githubaxboe
authored andcommitted
block, bfq: guarantee update_next_in_service always returns an eligible entity
If the function bfq_update_next_in_service is invoked as a consequence of the activation or requeueing of an entity, say E, then it doesn't invoke bfq_lookup_next_entity to get the next-in-service entity. In contrast, it follows a shorter path: if E happens to be eligible (see commit "bfq-sq-mq: make lookup_next_entity push up vtime on expirations" for details on eligibility) and to have a lower virtual finish time than the current candidate as next-in-service entity, then E directly becomes the next-in-service entity. Unfortunately, there is a corner case for which this shorter path makes bfq_update_next_in_service choose a non eligible entity: it occurs if both E and the current next-in-service entity happen to be non eligible when bfq_update_next_in_service is invoked. In this case, E is not set as next-in-service, and, since bfq_lookup_next_entity is not invoked, the state of the parent entity is not updated so as to end up with an eligible entity as the proper next-in-service entity. In this respect, next-in-service is actually allowed to be non eligible while some queue is in service: since no system-virtual-time push-up can be performed in that case (see again commit "bfq-sq-mq: make lookup_next_entity push up vtime on expirations" for details), next-in-service is chosen, speculatively, as a function of the possible value that the system virtual time may get after a push up. But the correctness of the schedule breaks if next-in-service is still a non eligible entity when it is time to set in service the next entity. Unfortunately, this may happen in the above corner case. This commit fixes this problem by making bfq_update_next_in_service invoke bfq_lookup_next_entity not only if the above shorter path cannot be taken, but also if the shorter path is taken but fails to yield an eligible next-in-service entity. Signed-off-by: Paolo Valente <[email protected]> Tested-by: Lee Tibbert <[email protected]> Tested-by: Oleksandr Natalenko <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent a02195c commit 24d90bb

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

block/bfq-wf2q.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
8080
{
8181
struct bfq_entity *next_in_service = sd->next_in_service;
8282
bool parent_sched_may_change = false;
83+
bool change_without_lookup = false;
8384

8485
/*
8586
* If this update is triggered by the activation, requeueing
@@ -99,7 +100,7 @@ static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
99100
* set to true, and left as true if
100101
* sd->next_in_service is NULL.
101102
*/
102-
bool replace_next = true;
103+
change_without_lookup = true;
103104

104105
/*
105106
* If there is already a next_in_service candidate
@@ -112,7 +113,7 @@ static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
112113
struct bfq_service_tree *st =
113114
sd->service_tree + new_entity_class_idx;
114115

115-
replace_next =
116+
change_without_lookup =
116117
(new_entity_class_idx ==
117118
bfq_class_idx(next_in_service)
118119
&&
@@ -122,15 +123,16 @@ static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
122123
new_entity->finish));
123124
}
124125

125-
if (replace_next)
126+
if (change_without_lookup)
126127
next_in_service = new_entity;
127-
} else /* invoked because of a deactivation: lookup needed */
128+
}
129+
130+
if (!change_without_lookup) /* lookup needed */
128131
next_in_service = bfq_lookup_next_entity(sd, expiration);
129132

130-
if (next_in_service) {
133+
if (next_in_service)
131134
parent_sched_may_change = !sd->next_in_service ||
132135
bfq_update_parent_budget(next_in_service);
133-
}
134136

135137
sd->next_in_service = next_in_service;
136138

0 commit comments

Comments
 (0)