1 |
From 46452443d7974185a080ac1719554b22fc422cbd Mon Sep 17 00:00:00 2001 |
2 |
From: Paolo Valente <paolo.valente@linaro.org> |
3 |
Date: Fri, 21 Jul 2017 12:08:57 +0200 |
4 |
Subject: [PATCH 2/4] block, bfq: reset in_service_entity if it becomes idle |
5 |
|
6 |
BFQ implements hierarchical scheduling by representing each group of |
7 |
queues with a generic parent entity. For each parent entity, BFQ |
8 |
maintains an in_service_entity pointer: if one of the child entities |
9 |
happens to be in service, in_service_entity points to it. The |
10 |
resetting of these pointers happens only on queue expirations: when |
11 |
the in-service queue is expired, i.e., stops to be the queue in |
12 |
service, BFQ resets all in_service_entity pointers along the |
13 |
parent-entity path from this queue to the root entity. |
14 |
|
15 |
Functions handling the scheduling of entities assume, naturally, that |
16 |
in-service entities are active, i.e., have pending I/O requests (or, |
17 |
as a special case, even if they have no pending requests, they are |
18 |
expected to receive a new request very soon, with the scheduler idling |
19 |
the storage device while waiting for such an event). Unfortunately, |
20 |
the above resetting scheme of the in_service_entity pointers may cause |
21 |
this assumption to be violated. For example, the in-service queue may |
22 |
happen to remain without requests because of a request merge. In this |
23 |
case the queue does become idle, and all related data structures are |
24 |
updated accordingly. But in_service_entity still points to the queue |
25 |
in the parent entity. This inconsistency may even propagate to |
26 |
higher-level parent entities, if they happen to become idle as well, |
27 |
as a consequence of the leaf queue becoming idle. For this queue and |
28 |
parent entities, scheduling functions have an undefined behaviour, |
29 |
and, as reported, may easily lead to kernel crashes or hangs. |
30 |
|
31 |
This commit addresses this issue by simply resetting the |
32 |
in_service_entity field also when it is detected to point to an entity |
33 |
becoming idle (regardless of why the entity becomes idle). |
34 |
|
35 |
Reported-by: Laurentiu Nicola <lnicola@dend.ro> |
36 |
Signed-off-by: Paolo Valente <paolo.valente@linaro.org> |
37 |
Tested-by: Laurentiu Nicola <lnicola@dend.ro> |
38 |
--- |
39 |
block/bfq-sched.c | 4 +++- |
40 |
1 file changed, 3 insertions(+), 1 deletion(-) |
41 |
|
42 |
diff --git a/block/bfq-sched.c b/block/bfq-sched.c |
43 |
index b6eb25887262..fdf1c713d050 100644 |
44 |
--- a/block/bfq-sched.c |
45 |
+++ b/block/bfq-sched.c |
46 |
@@ -1336,8 +1336,10 @@ static bool __bfq_deactivate_entity(struct bfq_entity *entity, |
47 |
|
48 |
BUG_ON(is_in_service && entity->tree && entity->tree != &st->active); |
49 |
|
50 |
- if (is_in_service) |
51 |
+ if (is_in_service) { |
52 |
bfq_calc_finish(entity, entity->service); |
53 |
+ sd->in_service_entity = NULL; |
54 |
+ } |
55 |
|
56 |
if (entity->tree == &st->active) |
57 |
bfq_active_extract(st, entity); |
58 |
-- |
59 |
2.14.1 |
60 |
|