diff options
| -rw-r--r-- | block/bfq-iosched.h | 22 | ||||
| -rw-r--r-- | block/bfq-wf2q.c | 142 |
2 files changed, 95 insertions, 69 deletions
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h index 63e771ab56d8..859f0a8c97c8 100644 --- a/block/bfq-iosched.h +++ b/block/bfq-iosched.h | |||
| @@ -71,17 +71,29 @@ struct bfq_service_tree { | |||
| 71 | * | 71 | * |
| 72 | * bfq_sched_data is the basic scheduler queue. It supports three | 72 | * bfq_sched_data is the basic scheduler queue. It supports three |
| 73 | * ioprio_classes, and can be used either as a toplevel queue or as an | 73 | * ioprio_classes, and can be used either as a toplevel queue or as an |
| 74 | * intermediate queue on a hierarchical setup. @next_in_service | 74 | * intermediate queue in a hierarchical setup. |
| 75 | * points to the active entity of the sched_data service trees that | ||
| 76 | * will be scheduled next. It is used to reduce the number of steps | ||
| 77 | * needed for each hierarchical-schedule update. | ||
| 78 | * | 75 | * |
| 79 | * The supported ioprio_classes are the same as in CFQ, in descending | 76 | * The supported ioprio_classes are the same as in CFQ, in descending |
| 80 | * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. | 77 | * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. |
| 81 | * Requests from higher priority queues are served before all the | 78 | * Requests from higher priority queues are served before all the |
| 82 | * requests from lower priority queues; among requests of the same | 79 | * requests from lower priority queues; among requests of the same |
| 83 | * queue requests are served according to B-WF2Q+. | 80 | * queue requests are served according to B-WF2Q+. |
| 84 | * All the fields are protected by the queue lock of the containing bfqd. | 81 | * |
| 82 | * The schedule is implemented by the service trees, plus the field | ||
| 83 | * @next_in_service, which points to the entity on the active trees | ||
| 84 | * that will be served next, if 1) no changes in the schedule occurs | ||
| 85 | * before the current in-service entity is expired, 2) the in-service | ||
| 86 | * queue becomes idle when it expires, and 3) if the entity pointed by | ||
| 87 | * in_service_entity is not a queue, then the in-service child entity | ||
| 88 | * of the entity pointed by in_service_entity becomes idle on | ||
| 89 | * expiration. This peculiar definition allows for the following | ||
| 90 | * optimization, not yet exploited: while a given entity is still in | ||
| 91 | * service, we already know which is the best candidate for next | ||
| 92 | * service among the other active entitities in the same parent | ||
| 93 | * entity. We can then quickly compare the timestamps of the | ||
| 94 | * in-service entity with those of such best candidate. | ||
| 95 | * | ||
| 96 | * All fields are protected by the lock of the containing bfqd. | ||
| 85 | */ | 97 | */ |
| 86 | struct bfq_sched_data { | 98 | struct bfq_sched_data { |
| 87 | /* entity in service */ | 99 | /* entity in service */ |
diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c index 881bbe5e1827..911aa7431dbe 100644 --- a/block/bfq-wf2q.c +++ b/block/bfq-wf2q.c | |||
| @@ -188,21 +188,23 @@ static bool bfq_update_parent_budget(struct bfq_entity *next_in_service) | |||
| 188 | 188 | ||
| 189 | /* | 189 | /* |
| 190 | * This function tells whether entity stops being a candidate for next | 190 | * This function tells whether entity stops being a candidate for next |
| 191 | * service, according to the following logic. | 191 | * service, according to the restrictive definition of the field |
| 192 | * next_in_service. In particular, this function is invoked for an | ||
| 193 | * entity that is about to be set in service. | ||
| 192 | * | 194 | * |
| 193 | * This function is invoked for an entity that is about to be set in | 195 | * If entity is a queue, then the entity is no longer a candidate for |
| 194 | * service. If such an entity is a queue, then the entity is no longer | 196 | * next service according to the that definition, because entity is |
| 195 | * a candidate for next service (i.e, a candidate entity to serve | 197 | * about to become the in-service queue. This function then returns |
| 196 | * after the in-service entity is expired). The function then returns | 198 | * true if entity is a queue. |
| 197 | * true. | ||
| 198 | * | 199 | * |
| 199 | * In contrast, the entity could stil be a candidate for next service | 200 | * In contrast, entity could still be a candidate for next service if |
| 200 | * if it is not a queue, and has more than one child. In fact, even if | 201 | * it is not a queue, and has more than one active child. In fact, |
| 201 | * one of its children is about to be set in service, other children | 202 | * even if one of its children is about to be set in service, other |
| 202 | * may still be the next to serve. As a consequence, a non-queue | 203 | * active children may still be the next to serve, for the parent |
| 203 | * entity is not a candidate for next-service only if it has only one | 204 | * entity, even according to the above definition. As a consequence, a |
| 204 | * child. And only if this condition holds, then the function returns | 205 | * non-queue entity is not a candidate for next-service only if it has |
| 205 | * true for a non-queue entity. | 206 | * only one active child. And only if this condition holds, then this |
| 207 | * function returns true for a non-queue entity. | ||
| 206 | */ | 208 | */ |
| 207 | static bool bfq_no_longer_next_in_service(struct bfq_entity *entity) | 209 | static bool bfq_no_longer_next_in_service(struct bfq_entity *entity) |
| 208 | { | 210 | { |
| @@ -213,6 +215,18 @@ static bool bfq_no_longer_next_in_service(struct bfq_entity *entity) | |||
| 213 | 215 | ||
| 214 | bfqg = container_of(entity, struct bfq_group, entity); | 216 | bfqg = container_of(entity, struct bfq_group, entity); |
| 215 | 217 | ||
| 218 | /* | ||
| 219 | * The field active_entities does not always contain the | ||
| 220 | * actual number of active children entities: it happens to | ||
| 221 | * not account for the in-service entity in case the latter is | ||
| 222 | * removed from its active tree (which may get done after | ||
| 223 | * invoking the function bfq_no_longer_next_in_service in | ||
| 224 | * bfq_get_next_queue). Fortunately, here, i.e., while | ||
| 225 | * bfq_no_longer_next_in_service is not yet completed in | ||
| 226 | * bfq_get_next_queue, bfq_active_extract has not yet been | ||
| 227 | * invoked, and thus active_entities still coincides with the | ||
| 228 | * actual number of active entities. | ||
| 229 | */ | ||
| 216 | if (bfqg->active_entities == 1) | 230 | if (bfqg->active_entities == 1) |
| 217 | return true; | 231 | return true; |
| 218 | 232 | ||
| @@ -954,7 +968,7 @@ static void bfq_update_fin_time_enqueue(struct bfq_entity *entity, | |||
| 954 | * one of its children receives a new request. | 968 | * one of its children receives a new request. |
| 955 | * | 969 | * |
| 956 | * Basically, this function updates the timestamps of entity and | 970 | * Basically, this function updates the timestamps of entity and |
| 957 | * inserts entity into its active tree, ater possible extracting it | 971 | * inserts entity into its active tree, ater possibly extracting it |
| 958 | * from its idle tree. | 972 | * from its idle tree. |
| 959 | */ | 973 | */ |
| 960 | static void __bfq_activate_entity(struct bfq_entity *entity, | 974 | static void __bfq_activate_entity(struct bfq_entity *entity, |
| @@ -1048,7 +1062,7 @@ static void __bfq_requeue_entity(struct bfq_entity *entity) | |||
| 1048 | entity->start = entity->finish; | 1062 | entity->start = entity->finish; |
| 1049 | /* | 1063 | /* |
| 1050 | * In addition, if the entity had more than one child | 1064 | * In addition, if the entity had more than one child |
| 1051 | * when set in service, then was not extracted from | 1065 | * when set in service, then it was not extracted from |
| 1052 | * the active tree. This implies that the position of | 1066 | * the active tree. This implies that the position of |
| 1053 | * the entity in the active tree may need to be | 1067 | * the entity in the active tree may need to be |
| 1054 | * changed now, because we have just updated the start | 1068 | * changed now, because we have just updated the start |
| @@ -1056,9 +1070,8 @@ static void __bfq_requeue_entity(struct bfq_entity *entity) | |||
| 1056 | * time in a moment (the requeueing is then, more | 1070 | * time in a moment (the requeueing is then, more |
| 1057 | * precisely, a repositioning in this case). To | 1071 | * precisely, a repositioning in this case). To |
| 1058 | * implement this repositioning, we: 1) dequeue the | 1072 | * implement this repositioning, we: 1) dequeue the |
| 1059 | * entity here, 2) update the finish time and | 1073 | * entity here, 2) update the finish time and requeue |
| 1060 | * requeue the entity according to the new | 1074 | * the entity according to the new timestamps below. |
| 1061 | * timestamps below. | ||
| 1062 | */ | 1075 | */ |
| 1063 | if (entity->tree) | 1076 | if (entity->tree) |
| 1064 | bfq_active_extract(st, entity); | 1077 | bfq_active_extract(st, entity); |
| @@ -1105,9 +1118,10 @@ static void __bfq_activate_requeue_entity(struct bfq_entity *entity, | |||
| 1105 | 1118 | ||
| 1106 | 1119 | ||
| 1107 | /** | 1120 | /** |
| 1108 | * bfq_activate_entity - activate or requeue an entity representing a bfq_queue, | 1121 | * bfq_activate_requeue_entity - activate or requeue an entity representing a |
| 1109 | * and activate, requeue or reposition all ancestors | 1122 | * bfq_queue, and activate, requeue or reposition |
| 1110 | * for which such an update becomes necessary. | 1123 | * all ancestors for which such an update becomes |
| 1124 | * necessary. | ||
| 1111 | * @entity: the entity to activate. | 1125 | * @entity: the entity to activate. |
| 1112 | * @non_blocking_wait_rq: true if this entity was waiting for a request | 1126 | * @non_blocking_wait_rq: true if this entity was waiting for a request |
| 1113 | * @requeue: true if this is a requeue, which implies that bfqq is | 1127 | * @requeue: true if this is a requeue, which implies that bfqq is |
| @@ -1135,9 +1149,9 @@ static void bfq_activate_requeue_entity(struct bfq_entity *entity, | |||
| 1135 | * @ins_into_idle_tree: if false, the entity will not be put into the | 1149 | * @ins_into_idle_tree: if false, the entity will not be put into the |
| 1136 | * idle tree. | 1150 | * idle tree. |
| 1137 | * | 1151 | * |
| 1138 | * Deactivates an entity, independently from its previous state. Must | 1152 | * Deactivates an entity, independently of its previous state. Must |
| 1139 | * be invoked only if entity is on a service tree. Extracts the entity | 1153 | * be invoked only if entity is on a service tree. Extracts the entity |
| 1140 | * from that tree, and if necessary and allowed, puts it on the idle | 1154 | * from that tree, and if necessary and allowed, puts it into the idle |
| 1141 | * tree. | 1155 | * tree. |
| 1142 | */ | 1156 | */ |
| 1143 | bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree) | 1157 | bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree) |
| @@ -1179,7 +1193,7 @@ bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree) | |||
| 1179 | /** | 1193 | /** |
| 1180 | * bfq_deactivate_entity - deactivate an entity representing a bfq_queue. | 1194 | * bfq_deactivate_entity - deactivate an entity representing a bfq_queue. |
| 1181 | * @entity: the entity to deactivate. | 1195 | * @entity: the entity to deactivate. |
| 1182 | * @ins_into_idle_tree: true if the entity can be put on the idle tree | 1196 | * @ins_into_idle_tree: true if the entity can be put into the idle tree |
| 1183 | */ | 1197 | */ |
| 1184 | static void bfq_deactivate_entity(struct bfq_entity *entity, | 1198 | static void bfq_deactivate_entity(struct bfq_entity *entity, |
| 1185 | bool ins_into_idle_tree, | 1199 | bool ins_into_idle_tree, |
| @@ -1210,16 +1224,29 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, | |||
| 1210 | */ | 1224 | */ |
| 1211 | bfq_update_next_in_service(sd, NULL); | 1225 | bfq_update_next_in_service(sd, NULL); |
| 1212 | 1226 | ||
| 1213 | if (sd->next_in_service) | 1227 | if (sd->next_in_service || sd->in_service_entity) { |
| 1214 | /* | 1228 | /* |
| 1215 | * The parent entity is still backlogged, | 1229 | * The parent entity is still active, because |
| 1216 | * because next_in_service is not NULL. So, no | 1230 | * either next_in_service or in_service_entity |
| 1217 | * further upwards deactivation must be | 1231 | * is not NULL. So, no further upwards |
| 1218 | * performed. Yet, next_in_service has | 1232 | * deactivation must be performed. Yet, |
| 1219 | * changed. Then the schedule does need to be | 1233 | * next_in_service has changed. Then the |
| 1220 | * updated upwards. | 1234 | * schedule does need to be updated upwards. |
| 1235 | * | ||
| 1236 | * NOTE If in_service_entity is not NULL, then | ||
| 1237 | * next_in_service may happen to be NULL, | ||
| 1238 | * although the parent entity is evidently | ||
| 1239 | * active. This happens if 1) the entity | ||
| 1240 | * pointed by in_service_entity is the only | ||
| 1241 | * active entity in the parent entity, and 2) | ||
| 1242 | * according to the definition of | ||
| 1243 | * next_in_service, the in_service_entity | ||
