162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Hierarchical Budget Worst-case Fair Weighted Fair Queueing 462306a36Sopenharmony_ci * (B-WF2Q+): hierarchical scheduling algorithm by which the BFQ I/O 562306a36Sopenharmony_ci * scheduler schedules generic entities. The latter can represent 662306a36Sopenharmony_ci * either single bfq queues (associated with processes) or groups of 762306a36Sopenharmony_ci * bfq queues (associated with cgroups). 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include "bfq-iosched.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/** 1262306a36Sopenharmony_ci * bfq_gt - compare two timestamps. 1362306a36Sopenharmony_ci * @a: first ts. 1462306a36Sopenharmony_ci * @b: second ts. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Return @a > @b, dealing with wrapping correctly. 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_cistatic int bfq_gt(u64 a, u64 b) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci return (s64)(a - b) > 0; 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic struct bfq_entity *bfq_root_active_entity(struct rb_root *tree) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci struct rb_node *node = tree->rb_node; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci return rb_entry(node, struct bfq_entity, rb_node); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic unsigned int bfq_class_idx(struct bfq_entity *entity) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci return bfqq ? bfqq->ioprio_class - 1 : 3562306a36Sopenharmony_ci BFQ_DEFAULT_GRP_CLASS - 1; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciunsigned int bfq_tot_busy_queues(struct bfq_data *bfqd) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci return bfqd->busy_queues[0] + bfqd->busy_queues[1] + 4162306a36Sopenharmony_ci bfqd->busy_queues[2]; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, 4562306a36Sopenharmony_ci bool expiration); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic bool bfq_update_parent_budget(struct bfq_entity *next_in_service); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/** 5062306a36Sopenharmony_ci * bfq_update_next_in_service - update sd->next_in_service 5162306a36Sopenharmony_ci * @sd: sched_data for which to perform the update. 5262306a36Sopenharmony_ci * @new_entity: if not NULL, pointer to the entity whose activation, 5362306a36Sopenharmony_ci * requeueing or repositioning triggered the invocation of 5462306a36Sopenharmony_ci * this function. 5562306a36Sopenharmony_ci * @expiration: id true, this function is being invoked after the 5662306a36Sopenharmony_ci * expiration of the in-service entity 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * This function is called to update sd->next_in_service, which, in 5962306a36Sopenharmony_ci * its turn, may change as a consequence of the insertion or 6062306a36Sopenharmony_ci * extraction of an entity into/from one of the active trees of 6162306a36Sopenharmony_ci * sd. These insertions/extractions occur as a consequence of 6262306a36Sopenharmony_ci * activations/deactivations of entities, with some activations being 6362306a36Sopenharmony_ci * 'true' activations, and other activations being requeueings (i.e., 6462306a36Sopenharmony_ci * implementing the second, requeueing phase of the mechanism used to 6562306a36Sopenharmony_ci * reposition an entity in its active tree; see comments on 6662306a36Sopenharmony_ci * __bfq_activate_entity and __bfq_requeue_entity for details). In 6762306a36Sopenharmony_ci * both the last two activation sub-cases, new_entity points to the 6862306a36Sopenharmony_ci * just activated or requeued entity. 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * Returns true if sd->next_in_service changes in such a way that 7162306a36Sopenharmony_ci * entity->parent may become the next_in_service for its parent 7262306a36Sopenharmony_ci * entity. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistatic bool bfq_update_next_in_service(struct bfq_sched_data *sd, 7562306a36Sopenharmony_ci struct bfq_entity *new_entity, 7662306a36Sopenharmony_ci bool expiration) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci struct bfq_entity *next_in_service = sd->next_in_service; 7962306a36Sopenharmony_ci bool parent_sched_may_change = false; 8062306a36Sopenharmony_ci bool change_without_lookup = false; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* 8362306a36Sopenharmony_ci * If this update is triggered by the activation, requeueing 8462306a36Sopenharmony_ci * or repositioning of an entity that does not coincide with 8562306a36Sopenharmony_ci * sd->next_in_service, then a full lookup in the active tree 8662306a36Sopenharmony_ci * can be avoided. In fact, it is enough to check whether the 8762306a36Sopenharmony_ci * just-modified entity has the same priority as 8862306a36Sopenharmony_ci * sd->next_in_service, is eligible and has a lower virtual 8962306a36Sopenharmony_ci * finish time than sd->next_in_service. If this compound 9062306a36Sopenharmony_ci * condition holds, then the new entity becomes the new 9162306a36Sopenharmony_ci * next_in_service. Otherwise no change is needed. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci if (new_entity && new_entity != sd->next_in_service) { 9462306a36Sopenharmony_ci /* 9562306a36Sopenharmony_ci * Flag used to decide whether to replace 9662306a36Sopenharmony_ci * sd->next_in_service with new_entity. Tentatively 9762306a36Sopenharmony_ci * set to true, and left as true if 9862306a36Sopenharmony_ci * sd->next_in_service is NULL. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci change_without_lookup = true; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* 10362306a36Sopenharmony_ci * If there is already a next_in_service candidate 10462306a36Sopenharmony_ci * entity, then compare timestamps to decide whether 10562306a36Sopenharmony_ci * to replace sd->service_tree with new_entity. 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_ci if (next_in_service) { 10862306a36Sopenharmony_ci unsigned int new_entity_class_idx = 10962306a36Sopenharmony_ci bfq_class_idx(new_entity); 11062306a36Sopenharmony_ci struct bfq_service_tree *st = 11162306a36Sopenharmony_ci sd->service_tree + new_entity_class_idx; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci change_without_lookup = 11462306a36Sopenharmony_ci (new_entity_class_idx == 11562306a36Sopenharmony_ci bfq_class_idx(next_in_service) 11662306a36Sopenharmony_ci && 11762306a36Sopenharmony_ci !bfq_gt(new_entity->start, st->vtime) 11862306a36Sopenharmony_ci && 11962306a36Sopenharmony_ci bfq_gt(next_in_service->finish, 12062306a36Sopenharmony_ci new_entity->finish)); 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci if (change_without_lookup) 12462306a36Sopenharmony_ci next_in_service = new_entity; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (!change_without_lookup) /* lookup needed */ 12862306a36Sopenharmony_ci next_in_service = bfq_lookup_next_entity(sd, expiration); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci if (next_in_service) { 13162306a36Sopenharmony_ci bool new_budget_triggers_change = 13262306a36Sopenharmony_ci bfq_update_parent_budget(next_in_service); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci parent_sched_may_change = !sd->next_in_service || 13562306a36Sopenharmony_ci new_budget_triggers_change; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci sd->next_in_service = next_in_service; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return parent_sched_may_change; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* 14662306a36Sopenharmony_ci * Returns true if this budget changes may let next_in_service->parent 14762306a36Sopenharmony_ci * become the next_in_service entity for its parent entity. 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_cistatic bool bfq_update_parent_budget(struct bfq_entity *next_in_service) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci struct bfq_entity *bfqg_entity; 15262306a36Sopenharmony_ci struct bfq_group *bfqg; 15362306a36Sopenharmony_ci struct bfq_sched_data *group_sd; 15462306a36Sopenharmony_ci bool ret = false; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci group_sd = next_in_service->sched_data; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci bfqg = container_of(group_sd, struct bfq_group, sched_data); 15962306a36Sopenharmony_ci /* 16062306a36Sopenharmony_ci * bfq_group's my_entity field is not NULL only if the group 16162306a36Sopenharmony_ci * is not the root group. We must not touch the root entity 16262306a36Sopenharmony_ci * as it must never become an in-service entity. 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_ci bfqg_entity = bfqg->my_entity; 16562306a36Sopenharmony_ci if (bfqg_entity) { 16662306a36Sopenharmony_ci if (bfqg_entity->budget > next_in_service->budget) 16762306a36Sopenharmony_ci ret = true; 16862306a36Sopenharmony_ci bfqg_entity->budget = next_in_service->budget; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return ret; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* 17562306a36Sopenharmony_ci * This function tells whether entity stops being a candidate for next 17662306a36Sopenharmony_ci * service, according to the restrictive definition of the field 17762306a36Sopenharmony_ci * next_in_service. In particular, this function is invoked for an 17862306a36Sopenharmony_ci * entity that is about to be set in service. 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci * If entity is a queue, then the entity is no longer a candidate for 18162306a36Sopenharmony_ci * next service according to the that definition, because entity is 18262306a36Sopenharmony_ci * about to become the in-service queue. This function then returns 18362306a36Sopenharmony_ci * true if entity is a queue. 18462306a36Sopenharmony_ci * 18562306a36Sopenharmony_ci * In contrast, entity could still be a candidate for next service if 18662306a36Sopenharmony_ci * it is not a queue, and has more than one active child. In fact, 18762306a36Sopenharmony_ci * even if one of its children is about to be set in service, other 18862306a36Sopenharmony_ci * active children may still be the next to serve, for the parent 18962306a36Sopenharmony_ci * entity, even according to the above definition. As a consequence, a 19062306a36Sopenharmony_ci * non-queue entity is not a candidate for next-service only if it has 19162306a36Sopenharmony_ci * only one active child. And only if this condition holds, then this 19262306a36Sopenharmony_ci * function returns true for a non-queue entity. 19362306a36Sopenharmony_ci */ 19462306a36Sopenharmony_cistatic bool bfq_no_longer_next_in_service(struct bfq_entity *entity) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci struct bfq_group *bfqg; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci if (bfq_entity_to_bfqq(entity)) 19962306a36Sopenharmony_ci return true; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci bfqg = container_of(entity, struct bfq_group, entity); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* 20462306a36Sopenharmony_ci * The field active_entities does not always contain the 20562306a36Sopenharmony_ci * actual number of active children entities: it happens to 20662306a36Sopenharmony_ci * not account for the in-service entity in case the latter is 20762306a36Sopenharmony_ci * removed from its active tree (which may get done after 20862306a36Sopenharmony_ci * invoking the function bfq_no_longer_next_in_service in 20962306a36Sopenharmony_ci * bfq_get_next_queue). Fortunately, here, i.e., while 21062306a36Sopenharmony_ci * bfq_no_longer_next_in_service is not yet completed in 21162306a36Sopenharmony_ci * bfq_get_next_queue, bfq_active_extract has not yet been 21262306a36Sopenharmony_ci * invoked, and thus active_entities still coincides with the 21362306a36Sopenharmony_ci * actual number of active entities. 21462306a36Sopenharmony_ci */ 21562306a36Sopenharmony_ci if (bfqg->active_entities == 1) 21662306a36Sopenharmony_ci return true; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci return false; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic void bfq_inc_active_entities(struct bfq_entity *entity) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct bfq_sched_data *sd = entity->sched_data; 22462306a36Sopenharmony_ci struct bfq_group *bfqg = container_of(sd, struct bfq_group, sched_data); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (bfqg != bfqg->bfqd->root_group) 22762306a36Sopenharmony_ci bfqg->active_entities++; 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic void bfq_dec_active_entities(struct bfq_entity *entity) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci struct bfq_sched_data *sd = entity->sched_data; 23362306a36Sopenharmony_ci struct bfq_group *bfqg = container_of(sd, struct bfq_group, sched_data); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci if (bfqg != bfqg->bfqd->root_group) 23662306a36Sopenharmony_ci bfqg->active_entities--; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci#else /* CONFIG_BFQ_GROUP_IOSCHED */ 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic bool bfq_update_parent_budget(struct bfq_entity *next_in_service) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci return false; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic bool bfq_no_longer_next_in_service(struct bfq_entity *entity) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci return true; 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic void bfq_inc_active_entities(struct bfq_entity *entity) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic void bfq_dec_active_entities(struct bfq_entity *entity) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci#endif /* CONFIG_BFQ_GROUP_IOSCHED */ 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci/* 26262306a36Sopenharmony_ci * Shift for timestamp calculations. This actually limits the maximum 26362306a36Sopenharmony_ci * service allowed in one timestamp delta (small shift values increase it), 26462306a36Sopenharmony_ci * the maximum total weight that can be used for the queues in the system 26562306a36Sopenharmony_ci * (big shift values increase it), and the period of virtual time 26662306a36Sopenharmony_ci * wraparounds. 26762306a36Sopenharmony_ci */ 26862306a36Sopenharmony_ci#define WFQ_SERVICE_SHIFT 22 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistruct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci struct bfq_queue *bfqq = NULL; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (!entity->my_sched_data) 27562306a36Sopenharmony_ci bfqq = container_of(entity, struct bfq_queue, entity); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci return bfqq; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/** 28262306a36Sopenharmony_ci * bfq_delta - map service into the virtual time domain. 28362306a36Sopenharmony_ci * @service: amount of service. 28462306a36Sopenharmony_ci * @weight: scale factor (weight of an entity or weight sum). 28562306a36Sopenharmony_ci */ 28662306a36Sopenharmony_cistatic u64 bfq_delta(unsigned long service, unsigned long weight) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci return div64_ul((u64)service << WFQ_SERVICE_SHIFT, weight); 28962306a36Sopenharmony_ci} 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci/** 29262306a36Sopenharmony_ci * bfq_calc_finish - assign the finish time to an entity. 29362306a36Sopenharmony_ci * @entity: the entity to act upon. 29462306a36Sopenharmony_ci * @service: the service to be charged to the entity. 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_cistatic void bfq_calc_finish(struct bfq_entity *entity, unsigned long service) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci entity->finish = entity->start + 30162306a36Sopenharmony_ci bfq_delta(service, entity->weight); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (bfqq) { 30462306a36Sopenharmony_ci bfq_log_bfqq(bfqq->bfqd, bfqq, 30562306a36Sopenharmony_ci "calc_finish: serv %lu, w %d", 30662306a36Sopenharmony_ci service, entity->weight); 30762306a36Sopenharmony_ci bfq_log_bfqq(bfqq->bfqd, bfqq, 30862306a36Sopenharmony_ci "calc_finish: start %llu, finish %llu, delta %llu", 30962306a36Sopenharmony_ci entity->start, entity->finish, 31062306a36Sopenharmony_ci bfq_delta(service, entity->weight)); 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci/** 31562306a36Sopenharmony_ci * bfq_entity_of - get an entity from a node. 31662306a36Sopenharmony_ci * @node: the node field of the entity. 31762306a36Sopenharmony_ci * 31862306a36Sopenharmony_ci * Convert a node pointer to the relative entity. This is used only 31962306a36Sopenharmony_ci * to simplify the logic of some functions and not as the generic 32062306a36Sopenharmony_ci * conversion mechanism because, e.g., in the tree walking functions, 32162306a36Sopenharmony_ci * the check for a %NULL value would be redundant. 32262306a36Sopenharmony_ci */ 32362306a36Sopenharmony_cistruct bfq_entity *bfq_entity_of(struct rb_node *node) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct bfq_entity *entity = NULL; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (node) 32862306a36Sopenharmony_ci entity = rb_entry(node, struct bfq_entity, rb_node); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci return entity; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci/** 33462306a36Sopenharmony_ci * bfq_extract - remove an entity from a tree. 33562306a36Sopenharmony_ci * @root: the tree root. 33662306a36Sopenharmony_ci * @entity: the entity to remove. 33762306a36Sopenharmony_ci */ 33862306a36Sopenharmony_cistatic void bfq_extract(struct rb_root *root, struct bfq_entity *entity) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci entity->tree = NULL; 34162306a36Sopenharmony_ci rb_erase(&entity->rb_node, root); 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci/** 34562306a36Sopenharmony_ci * bfq_idle_extract - extract an entity from the idle tree. 34662306a36Sopenharmony_ci * @st: the service tree of the owning @entity. 34762306a36Sopenharmony_ci * @entity: the entity being removed. 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_cistatic void bfq_idle_extract(struct bfq_service_tree *st, 35062306a36Sopenharmony_ci struct bfq_entity *entity) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 35362306a36Sopenharmony_ci struct rb_node *next; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (entity == st->first_idle) { 35662306a36Sopenharmony_ci next = rb_next(&entity->rb_node); 35762306a36Sopenharmony_ci st->first_idle = bfq_entity_of(next); 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (entity == st->last_idle) { 36162306a36Sopenharmony_ci next = rb_prev(&entity->rb_node); 36262306a36Sopenharmony_ci st->last_idle = bfq_entity_of(next); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci bfq_extract(&st->idle, entity); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if (bfqq) 36862306a36Sopenharmony_ci list_del(&bfqq->bfqq_list); 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci/** 37262306a36Sopenharmony_ci * bfq_insert - generic tree insertion. 37362306a36Sopenharmony_ci * @root: tree root. 37462306a36Sopenharmony_ci * @entity: entity to insert. 37562306a36Sopenharmony_ci * 37662306a36Sopenharmony_ci * This is used for the idle and the active tree, since they are both 37762306a36Sopenharmony_ci * ordered by finish time. 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_cistatic void bfq_insert(struct rb_root *root, struct bfq_entity *entity) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct bfq_entity *entry; 38262306a36Sopenharmony_ci struct rb_node **node = &root->rb_node; 38362306a36Sopenharmony_ci struct rb_node *parent = NULL; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci while (*node) { 38662306a36Sopenharmony_ci parent = *node; 38762306a36Sopenharmony_ci entry = rb_entry(parent, struct bfq_entity, rb_node); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (bfq_gt(entry->finish, entity->finish)) 39062306a36Sopenharmony_ci node = &parent->rb_left; 39162306a36Sopenharmony_ci else 39262306a36Sopenharmony_ci node = &parent->rb_right; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci rb_link_node(&entity->rb_node, parent, node); 39662306a36Sopenharmony_ci rb_insert_color(&entity->rb_node, root); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci entity->tree = root; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci/** 40262306a36Sopenharmony_ci * bfq_update_min - update the min_start field of a entity. 40362306a36Sopenharmony_ci * @entity: the entity to update. 40462306a36Sopenharmony_ci * @node: one of its children. 40562306a36Sopenharmony_ci * 40662306a36Sopenharmony_ci * This function is called when @entity may store an invalid value for 40762306a36Sopenharmony_ci * min_start due to updates to the active tree. The function assumes 40862306a36Sopenharmony_ci * that the subtree rooted at @node (which may be its left or its right 40962306a36Sopenharmony_ci * child) has a valid min_start value. 41062306a36Sopenharmony_ci */ 41162306a36Sopenharmony_cistatic void bfq_update_min(struct bfq_entity *entity, struct rb_node *node) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci struct bfq_entity *child; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci if (node) { 41662306a36Sopenharmony_ci child = rb_entry(node, struct bfq_entity, rb_node); 41762306a36Sopenharmony_ci if (bfq_gt(entity->min_start, child->min_start)) 41862306a36Sopenharmony_ci entity->min_start = child->min_start; 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci/** 42362306a36Sopenharmony_ci * bfq_update_active_node - recalculate min_start. 42462306a36Sopenharmony_ci * @node: the node to update. 42562306a36Sopenharmony_ci * 42662306a36Sopenharmony_ci * @node may have changed position or one of its children may have moved, 42762306a36Sopenharmony_ci * this function updates its min_start value. The left and right subtrees 42862306a36Sopenharmony_ci * are assumed to hold a correct min_start value. 42962306a36Sopenharmony_ci */ 43062306a36Sopenharmony_cistatic void bfq_update_active_node(struct rb_node *node) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci entity->min_start = entity->start; 43562306a36Sopenharmony_ci bfq_update_min(entity, node->rb_right); 43662306a36Sopenharmony_ci bfq_update_min(entity, node->rb_left); 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci/** 44062306a36Sopenharmony_ci * bfq_update_active_tree - update min_start for the whole active tree. 44162306a36Sopenharmony_ci * @node: the starting node. 44262306a36Sopenharmony_ci * 44362306a36Sopenharmony_ci * @node must be the deepest modified node after an update. This function 44462306a36Sopenharmony_ci * updates its min_start using the values held by its children, assuming 44562306a36Sopenharmony_ci * that they did not change, and then updates all the nodes that may have 44662306a36Sopenharmony_ci * changed in the path to the root. The only nodes that may have changed 44762306a36Sopenharmony_ci * are the ones in the path or their siblings. 44862306a36Sopenharmony_ci */ 44962306a36Sopenharmony_cistatic void bfq_update_active_tree(struct rb_node *node) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct rb_node *parent; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ciup: 45462306a36Sopenharmony_ci bfq_update_active_node(node); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci parent = rb_parent(node); 45762306a36Sopenharmony_ci if (!parent) 45862306a36Sopenharmony_ci return; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci if (node == parent->rb_left && parent->rb_right) 46162306a36Sopenharmony_ci bfq_update_active_node(parent->rb_right); 46262306a36Sopenharmony_ci else if (parent->rb_left) 46362306a36Sopenharmony_ci bfq_update_active_node(parent->rb_left); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci node = parent; 46662306a36Sopenharmony_ci goto up; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/** 47062306a36Sopenharmony_ci * bfq_active_insert - insert an entity in the active tree of its 47162306a36Sopenharmony_ci * group/device. 47262306a36Sopenharmony_ci * @st: the service tree of the entity. 47362306a36Sopenharmony_ci * @entity: the entity being inserted. 47462306a36Sopenharmony_ci * 47562306a36Sopenharmony_ci * The active tree is ordered by finish time, but an extra key is kept 47662306a36Sopenharmony_ci * per each node, containing the minimum value for the start times of 47762306a36Sopenharmony_ci * its children (and the node itself), so it's possible to search for 47862306a36Sopenharmony_ci * the eligible node with the lowest finish time in logarithmic time. 47962306a36Sopenharmony_ci */ 48062306a36Sopenharmony_cistatic void bfq_active_insert(struct bfq_service_tree *st, 48162306a36Sopenharmony_ci struct bfq_entity *entity) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 48462306a36Sopenharmony_ci struct rb_node *node = &entity->rb_node; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci bfq_insert(&st->active, entity); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci if (node->rb_left) 48962306a36Sopenharmony_ci node = node->rb_left; 49062306a36Sopenharmony_ci else if (node->rb_right) 49162306a36Sopenharmony_ci node = node->rb_right; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci bfq_update_active_tree(node); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (bfqq) 49662306a36Sopenharmony_ci list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list[bfqq->actuator_idx]); 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci bfq_inc_active_entities(entity); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci/** 50262306a36Sopenharmony_ci * bfq_ioprio_to_weight - calc a weight from an ioprio. 50362306a36Sopenharmony_ci * @ioprio: the ioprio value to convert. 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_ciunsigned short bfq_ioprio_to_weight(int ioprio) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci return (IOPRIO_NR_LEVELS - ioprio) * BFQ_WEIGHT_CONVERSION_COEFF; 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci/** 51162306a36Sopenharmony_ci * bfq_weight_to_ioprio - calc an ioprio from a weight. 51262306a36Sopenharmony_ci * @weight: the weight value to convert. 51362306a36Sopenharmony_ci * 51462306a36Sopenharmony_ci * To preserve as much as possible the old only-ioprio user interface, 51562306a36Sopenharmony_ci * 0 is used as an escape ioprio value for weights (numerically) equal or 51662306a36Sopenharmony_ci * larger than IOPRIO_NR_LEVELS * BFQ_WEIGHT_CONVERSION_COEFF. 51762306a36Sopenharmony_ci */ 51862306a36Sopenharmony_cistatic unsigned short bfq_weight_to_ioprio(int weight) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci return max_t(int, 0, 52162306a36Sopenharmony_ci IOPRIO_NR_LEVELS - weight / BFQ_WEIGHT_CONVERSION_COEFF); 52262306a36Sopenharmony_ci} 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_cistatic void bfq_get_entity(struct bfq_entity *entity) 52562306a36Sopenharmony_ci{ 52662306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci if (bfqq) { 52962306a36Sopenharmony_ci bfqq->ref++; 53062306a36Sopenharmony_ci bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", 53162306a36Sopenharmony_ci bfqq, bfqq->ref); 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci} 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci/** 53662306a36Sopenharmony_ci * bfq_find_deepest - find the deepest node that an extraction can modify. 53762306a36Sopenharmony_ci * @node: the node being removed. 53862306a36Sopenharmony_ci * 53962306a36Sopenharmony_ci * Do the first step of an extraction in an rb tree, looking for the 54062306a36Sopenharmony_ci * node that will replace @node, and returning the deepest node that 54162306a36Sopenharmony_ci * the following modifications to the tree can touch. If @node is the 54262306a36Sopenharmony_ci * last node in the tree return %NULL. 54362306a36Sopenharmony_ci */ 54462306a36Sopenharmony_cistatic struct rb_node *bfq_find_deepest(struct rb_node *node) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci struct rb_node *deepest; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci if (!node->rb_right && !node->rb_left) 54962306a36Sopenharmony_ci deepest = rb_parent(node); 55062306a36Sopenharmony_ci else if (!node->rb_right) 55162306a36Sopenharmony_ci deepest = node->rb_left; 55262306a36Sopenharmony_ci else if (!node->rb_left) 55362306a36Sopenharmony_ci deepest = node->rb_right; 55462306a36Sopenharmony_ci else { 55562306a36Sopenharmony_ci deepest = rb_next(node); 55662306a36Sopenharmony_ci if (deepest->rb_right) 55762306a36Sopenharmony_ci deepest = deepest->rb_right; 55862306a36Sopenharmony_ci else if (rb_parent(deepest) != node) 55962306a36Sopenharmony_ci deepest = rb_parent(deepest); 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci return deepest; 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci/** 56662306a36Sopenharmony_ci * bfq_active_extract - remove an entity from the active tree. 56762306a36Sopenharmony_ci * @st: the service_tree containing the tree. 56862306a36Sopenharmony_ci * @entity: the entity being removed. 56962306a36Sopenharmony_ci */ 57062306a36Sopenharmony_cistatic void bfq_active_extract(struct bfq_service_tree *st, 57162306a36Sopenharmony_ci struct bfq_entity *entity) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 57462306a36Sopenharmony_ci struct rb_node *node; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci node = bfq_find_deepest(&entity->rb_node); 57762306a36Sopenharmony_ci bfq_extract(&st->active, entity); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (node) 58062306a36Sopenharmony_ci bfq_update_active_tree(node); 58162306a36Sopenharmony_ci if (bfqq) 58262306a36Sopenharmony_ci list_del(&bfqq->bfqq_list); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci bfq_dec_active_entities(entity); 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci/** 58862306a36Sopenharmony_ci * bfq_idle_insert - insert an entity into the idle tree. 58962306a36Sopenharmony_ci * @st: the service tree containing the tree. 59062306a36Sopenharmony_ci * @entity: the entity to insert. 59162306a36Sopenharmony_ci */ 59262306a36Sopenharmony_cistatic void bfq_idle_insert(struct bfq_service_tree *st, 59362306a36Sopenharmony_ci struct bfq_entity *entity) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 59662306a36Sopenharmony_ci struct bfq_entity *first_idle = st->first_idle; 59762306a36Sopenharmony_ci struct bfq_entity *last_idle = st->last_idle; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci if (!first_idle || bfq_gt(first_idle->finish, entity->finish)) 60062306a36Sopenharmony_ci st->first_idle = entity; 60162306a36Sopenharmony_ci if (!last_idle || bfq_gt(entity->finish, last_idle->finish)) 60262306a36Sopenharmony_ci st->last_idle = entity; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci bfq_insert(&st->idle, entity); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci if (bfqq) 60762306a36Sopenharmony_ci list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list); 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci/** 61162306a36Sopenharmony_ci * bfq_forget_entity - do not consider entity any longer for scheduling 61262306a36Sopenharmony_ci * @st: the service tree. 61362306a36Sopenharmony_ci * @entity: the entity being removed. 61462306a36Sopenharmony_ci * @is_in_service: true if entity is currently the in-service entity. 61562306a36Sopenharmony_ci * 61662306a36Sopenharmony_ci * Forget everything about @entity. In addition, if entity represents 61762306a36Sopenharmony_ci * a queue, and the latter is not in service, then release the service 61862306a36Sopenharmony_ci * reference to the queue (the one taken through bfq_get_entity). In 61962306a36Sopenharmony_ci * fact, in this case, there is really no more service reference to 62062306a36Sopenharmony_ci * the queue, as the latter is also outside any service tree. If, 62162306a36Sopenharmony_ci * instead, the queue is in service, then __bfq_bfqd_reset_in_service 62262306a36Sopenharmony_ci * will take care of putting the reference when the queue finally 62362306a36Sopenharmony_ci * stops being served. 62462306a36Sopenharmony_ci */ 62562306a36Sopenharmony_cistatic void bfq_forget_entity(struct bfq_service_tree *st, 62662306a36Sopenharmony_ci struct bfq_entity *entity, 62762306a36Sopenharmony_ci bool is_in_service) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci entity->on_st_or_in_serv = false; 63262306a36Sopenharmony_ci st->wsum -= entity->weight; 63362306a36Sopenharmony_ci if (bfqq && !is_in_service) 63462306a36Sopenharmony_ci bfq_put_queue(bfqq); 63562306a36Sopenharmony_ci} 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci/** 63862306a36Sopenharmony_ci * bfq_put_idle_entity - release the idle tree ref of an entity. 63962306a36Sopenharmony_ci * @st: service tree for the entity. 64062306a36Sopenharmony_ci * @entity: the entity being released. 64162306a36Sopenharmony_ci */ 64262306a36Sopenharmony_civoid bfq_put_idle_entity(struct bfq_service_tree *st, struct bfq_entity *entity) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci bfq_idle_extract(st, entity); 64562306a36Sopenharmony_ci bfq_forget_entity(st, entity, 64662306a36Sopenharmony_ci entity == entity->sched_data->in_service_entity); 64762306a36Sopenharmony_ci} 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci/** 65062306a36Sopenharmony_ci * bfq_forget_idle - update the idle tree if necessary. 65162306a36Sopenharmony_ci * @st: the service tree to act upon. 65262306a36Sopenharmony_ci * 65362306a36Sopenharmony_ci * To preserve the global O(log N) complexity we only remove one entry here; 65462306a36Sopenharmony_ci * as the idle tree will not grow indefinitely this can be done safely. 65562306a36Sopenharmony_ci */ 65662306a36Sopenharmony_cistatic void bfq_forget_idle(struct bfq_service_tree *st) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci struct bfq_entity *first_idle = st->first_idle; 65962306a36Sopenharmony_ci struct bfq_entity *last_idle = st->last_idle; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci if (RB_EMPTY_ROOT(&st->active) && last_idle && 66262306a36Sopenharmony_ci !bfq_gt(last_idle->finish, st->vtime)) { 66362306a36Sopenharmony_ci /* 66462306a36Sopenharmony_ci * Forget the whole idle tree, increasing the vtime past 66562306a36Sopenharmony_ci * the last finish time of idle entities. 66662306a36Sopenharmony_ci */ 66762306a36Sopenharmony_ci st->vtime = last_idle->finish; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci if (first_idle && !bfq_gt(first_idle->finish, st->vtime)) 67162306a36Sopenharmony_ci bfq_put_idle_entity(st, first_idle); 67262306a36Sopenharmony_ci} 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_cistruct bfq_service_tree *bfq_entity_service_tree(struct bfq_entity *entity) 67562306a36Sopenharmony_ci{ 67662306a36Sopenharmony_ci struct bfq_sched_data *sched_data = entity->sched_data; 67762306a36Sopenharmony_ci unsigned int idx = bfq_class_idx(entity); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci return sched_data->service_tree + idx; 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci/* 68362306a36Sopenharmony_ci * Update weight and priority of entity. If update_class_too is true, 68462306a36Sopenharmony_ci * then update the ioprio_class of entity too. 68562306a36Sopenharmony_ci * 68662306a36Sopenharmony_ci * The reason why the update of ioprio_class is controlled through the 68762306a36Sopenharmony_ci * last parameter is as follows. Changing the ioprio class of an 68862306a36Sopenharmony_ci * entity implies changing the destination service trees for that 68962306a36Sopenharmony_ci * entity. If such a change occurred when the entity is already on one 69062306a36Sopenharmony_ci * of the service trees for its previous class, then the state of the 69162306a36Sopenharmony_ci * entity would become more complex: none of the new possible service 69262306a36Sopenharmony_ci * trees for the entity, according to bfq_entity_service_tree(), would 69362306a36Sopenharmony_ci * match any of the possible service trees on which the entity 69462306a36Sopenharmony_ci * is. Complex operations involving these trees, such as entity 69562306a36Sopenharmony_ci * activations and deactivations, should take into account this 69662306a36Sopenharmony_ci * additional complexity. To avoid this issue, this function is 69762306a36Sopenharmony_ci * invoked with update_class_too unset in the points in the code where 69862306a36Sopenharmony_ci * entity may happen to be on some tree. 69962306a36Sopenharmony_ci */ 70062306a36Sopenharmony_cistruct bfq_service_tree * 70162306a36Sopenharmony_ci__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, 70262306a36Sopenharmony_ci struct bfq_entity *entity, 70362306a36Sopenharmony_ci bool update_class_too) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci struct bfq_service_tree *new_st = old_st; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci if (entity->prio_changed) { 70862306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 70962306a36Sopenharmony_ci unsigned int prev_weight, new_weight; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci /* Matches the smp_wmb() in bfq_group_set_weight. */ 71262306a36Sopenharmony_ci smp_rmb(); 71362306a36Sopenharmony_ci old_st->wsum -= entity->weight; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci if (entity->new_weight != entity->orig_weight) { 71662306a36Sopenharmony_ci if (entity->new_weight < BFQ_MIN_WEIGHT || 71762306a36Sopenharmony_ci entity->new_weight > BFQ_MAX_WEIGHT) { 71862306a36Sopenharmony_ci pr_crit("update_weight_prio: new_weight %d\n", 71962306a36Sopenharmony_ci entity->new_weight); 72062306a36Sopenharmony_ci if (entity->new_weight < BFQ_MIN_WEIGHT) 72162306a36Sopenharmony_ci entity->new_weight = BFQ_MIN_WEIGHT; 72262306a36Sopenharmony_ci else 72362306a36Sopenharmony_ci entity->new_weight = BFQ_MAX_WEIGHT; 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci entity->orig_weight = entity->new_weight; 72662306a36Sopenharmony_ci if (bfqq) 72762306a36Sopenharmony_ci bfqq->ioprio = 72862306a36Sopenharmony_ci bfq_weight_to_ioprio(entity->orig_weight); 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci if (bfqq && update_class_too) 73262306a36Sopenharmony_ci bfqq->ioprio_class = bfqq->new_ioprio_class; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci /* 73562306a36Sopenharmony_ci * Reset prio_changed only if the ioprio_class change 73662306a36Sopenharmony_ci * is not pending any longer. 73762306a36Sopenharmony_ci */ 73862306a36Sopenharmony_ci if (!bfqq || bfqq->ioprio_class == bfqq->new_ioprio_class) 73962306a36Sopenharmony_ci entity->prio_changed = 0; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci /* 74262306a36Sopenharmony_ci * NOTE: here we may be changing the weight too early, 74362306a36Sopenharmony_ci * this will cause unfairness. The correct approach 74462306a36Sopenharmony_ci * would have required additional complexity to defer 74562306a36Sopenharmony_ci * weight changes to the proper time instants (i.e., 74662306a36Sopenharmony_ci * when entity->finish <= old_st->vtime). 74762306a36Sopenharmony_ci */ 74862306a36Sopenharmony_ci new_st = bfq_entity_service_tree(entity); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci prev_weight = entity->weight; 75162306a36Sopenharmony_ci new_weight = entity->orig_weight * 75262306a36Sopenharmony_ci (bfqq ? bfqq->wr_coeff : 1); 75362306a36Sopenharmony_ci /* 75462306a36Sopenharmony_ci * If the weight of the entity changes, and the entity is a 75562306a36Sopenharmony_ci * queue, remove the entity from its old weight counter (if 75662306a36Sopenharmony_ci * there is a counter associated with the entity). 75762306a36Sopenharmony_ci */ 75862306a36Sopenharmony_ci if (prev_weight != new_weight && bfqq) 75962306a36Sopenharmony_ci bfq_weights_tree_remove(bfqq); 76062306a36Sopenharmony_ci entity->weight = new_weight; 76162306a36Sopenharmony_ci /* 76262306a36Sopenharmony_ci * Add the entity, if it is not a weight-raised queue, 76362306a36Sopenharmony_ci * to the counter associated with its new weight. 76462306a36Sopenharmony_ci */ 76562306a36Sopenharmony_ci if (prev_weight != new_weight && bfqq && bfqq->wr_coeff == 1) 76662306a36Sopenharmony_ci bfq_weights_tree_add(bfqq); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci new_st->wsum += entity->weight; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci if (new_st != old_st) 77162306a36Sopenharmony_ci entity->start = new_st->vtime; 77262306a36Sopenharmony_ci } 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci return new_st; 77562306a36Sopenharmony_ci} 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci/** 77862306a36Sopenharmony_ci * bfq_bfqq_served - update the scheduler status after selection for 77962306a36Sopenharmony_ci * service. 78062306a36Sopenharmony_ci * @bfqq: the queue being served. 78162306a36Sopenharmony_ci * @served: bytes to transfer. 78262306a36Sopenharmony_ci * 78362306a36Sopenharmony_ci * NOTE: this can be optimized, as the timestamps of upper level entities 78462306a36Sopenharmony_ci * are synchronized every time a new bfqq is selected for service. By now, 78562306a36Sopenharmony_ci * we keep it to better check consistency. 78662306a36Sopenharmony_ci */ 78762306a36Sopenharmony_civoid bfq_bfqq_served(struct bfq_queue *bfqq, int served) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci struct bfq_entity *entity = &bfqq->entity; 79062306a36Sopenharmony_ci struct bfq_service_tree *st; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci if (!bfqq->service_from_backlogged) 79362306a36Sopenharmony_ci bfqq->first_IO_time = jiffies; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci if (bfqq->wr_coeff > 1) 79662306a36Sopenharmony_ci bfqq->service_from_wr += served; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci bfqq->service_from_backlogged += served; 79962306a36Sopenharmony_ci for_each_entity(entity) { 80062306a36Sopenharmony_ci st = bfq_entity_service_tree(entity); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci entity->service += served; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci st->vtime += bfq_delta(served, st->wsum); 80562306a36Sopenharmony_ci bfq_forget_idle(st); 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %d secs", served); 80862306a36Sopenharmony_ci} 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci/** 81162306a36Sopenharmony_ci * bfq_bfqq_charge_time - charge an amount of service equivalent to the length 81262306a36Sopenharmony_ci * of the time interval during which bfqq has been in 81362306a36Sopenharmony_ci * service. 81462306a36Sopenharmony_ci * @bfqd: the device 81562306a36Sopenharmony_ci * @bfqq: the queue that needs a service update. 81662306a36Sopenharmony_ci * @time_ms: the amount of time during which the queue has received service 81762306a36Sopenharmony_ci * 81862306a36Sopenharmony_ci * If a queue does not consume its budget fast enough, then providing 81962306a36Sopenharmony_ci * the queue with service fairness may impair throughput, more or less 82062306a36Sopenharmony_ci * severely. For this reason, queues that consume their budget slowly 82162306a36Sopenharmony_ci * are provided with time fairness instead of service fairness. This 82262306a36Sopenharmony_ci * goal is achieved through the BFQ scheduling engine, even if such an 82362306a36Sopenharmony_ci * engine works in the service, and not in the time domain. The trick 82462306a36Sopenharmony_ci * is charging these queues with an inflated amount of service, equal 82562306a36Sopenharmony_ci * to the amount of service that they would have received during their 82662306a36Sopenharmony_ci * service slot if they had been fast, i.e., if their requests had 82762306a36Sopenharmony_ci * been dispatched at a rate equal to the estimated peak rate. 82862306a36Sopenharmony_ci * 82962306a36Sopenharmony_ci * It is worth noting that time fairness can cause important 83062306a36Sopenharmony_ci * distortions in terms of bandwidth distribution, on devices with 83162306a36Sopenharmony_ci * internal queueing. The reason is that I/O requests dispatched 83262306a36Sopenharmony_ci * during the service slot of a queue may be served after that service 83362306a36Sopenharmony_ci * slot is finished, and may have a total processing time loosely 83462306a36Sopenharmony_ci * correlated with the duration of the service slot. This is 83562306a36Sopenharmony_ci * especially true for short service slots. 83662306a36Sopenharmony_ci */ 83762306a36Sopenharmony_civoid bfq_bfqq_charge_time(struct bfq_data *bfqd, struct bfq_queue *bfqq, 83862306a36Sopenharmony_ci unsigned long time_ms) 83962306a36Sopenharmony_ci{ 84062306a36Sopenharmony_ci struct bfq_entity *entity = &bfqq->entity; 84162306a36Sopenharmony_ci unsigned long timeout_ms = jiffies_to_msecs(bfq_timeout); 84262306a36Sopenharmony_ci unsigned long bounded_time_ms = min(time_ms, timeout_ms); 84362306a36Sopenharmony_ci int serv_to_charge_for_time = 84462306a36Sopenharmony_ci (bfqd->bfq_max_budget * bounded_time_ms) / timeout_ms; 84562306a36Sopenharmony_ci int tot_serv_to_charge = max(serv_to_charge_for_time, entity->service); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci /* Increase budget to avoid inconsistencies */ 84862306a36Sopenharmony_ci if (tot_serv_to_charge > entity->budget) 84962306a36Sopenharmony_ci entity->budget = tot_serv_to_charge; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci bfq_bfqq_served(bfqq, 85262306a36Sopenharmony_ci max_t(int, 0, tot_serv_to_charge - entity->service)); 85362306a36Sopenharmony_ci} 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cistatic void bfq_update_fin_time_enqueue(struct bfq_entity *entity, 85662306a36Sopenharmony_ci struct bfq_service_tree *st, 85762306a36Sopenharmony_ci bool backshifted) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* 86262306a36Sopenharmony_ci * When this function is invoked, entity is not in any service 86362306a36Sopenharmony_ci * tree, then it is safe to invoke next function with the last 86462306a36Sopenharmony_ci * parameter set (see the comments on the function). 86562306a36Sopenharmony_ci */ 86662306a36Sopenharmony_ci st = __bfq_entity_update_weight_prio(st, entity, true); 86762306a36Sopenharmony_ci bfq_calc_finish(entity, entity->budget); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci /* 87062306a36Sopenharmony_ci * If some queues enjoy backshifting for a while, then their 87162306a36Sopenharmony_ci * (virtual) finish timestamps may happen to become lower and 87262306a36Sopenharmony_ci * lower than the system virtual time. In particular, if 87362306a36Sopenharmony_ci * these queues often happen to be idle for short time 87462306a36Sopenharmony_ci * periods, and during such time periods other queues with 87562306a36Sopenharmony_ci * higher timestamps happen to be busy, then the backshifted 87662306a36Sopenharmony_ci * timestamps of the former queues can become much lower than 87762306a36Sopenharmony_ci * the system virtual time. In fact, to serve the queues with 87862306a36Sopenharmony_ci * higher timestamps while the ones with lower timestamps are 87962306a36Sopenharmony_ci * idle, the system virtual time may be pushed-up to much 88062306a36Sopenharmony_ci * higher values than the finish timestamps of the idle 88162306a36Sopenharmony_ci * queues. As a consequence, the finish timestamps of all new 88262306a36Sopenharmony_ci * or newly activated queues may end up being much larger than 88362306a36Sopenharmony_ci * those of lucky queues with backshifted timestamps. The 88462306a36Sopenharmony_ci * latter queues may then monopolize the device for a lot of 88562306a36Sopenharmony_ci * time. This would simply break service guarantees. 88662306a36Sopenharmony_ci * 88762306a36Sopenharmony_ci * To reduce this problem, push up a little bit the 88862306a36Sopenharmony_ci * backshifted timestamps of the queue associated with this 88962306a36Sopenharmony_ci * entity (only a queue can happen to have the backshifted 89062306a36Sopenharmony_ci * flag set): just enough to let the finish timestamp of the 89162306a36Sopenharmony_ci * queue be equal to the current value of the system virtual 89262306a36Sopenharmony_ci * time. This may introduce a little unfairness among queues 89362306a36Sopenharmony_ci * with backshifted timestamps, but it does not break 89462306a36Sopenharmony_ci * worst-case fairness guarantees. 89562306a36Sopenharmony_ci * 89662306a36Sopenharmony_ci * As a special case, if bfqq is weight-raised, push up 89762306a36Sopenharmony_ci * timestamps much less, to keep very low the probability that 89862306a36Sopenharmony_ci * this push up causes the backshifted finish timestamps of 89962306a36Sopenharmony_ci * weight-raised queues to become higher than the backshifted 90062306a36Sopenharmony_ci * finish timestamps of non weight-raised queues. 90162306a36Sopenharmony_ci */ 90262306a36Sopenharmony_ci if (backshifted && bfq_gt(st->vtime, entity->finish)) { 90362306a36Sopenharmony_ci unsigned long delta = st->vtime - entity->finish; 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci if (bfqq) 90662306a36Sopenharmony_ci delta /= bfqq->wr_coeff; 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci entity->start += delta; 90962306a36Sopenharmony_ci entity->finish += delta; 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci bfq_active_insert(st, entity); 91362306a36Sopenharmony_ci} 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci/** 91662306a36Sopenharmony_ci * __bfq_activate_entity - handle activation of entity. 91762306a36Sopenharmony_ci * @entity: the entity being activated. 91862306a36Sopenharmony_ci * @non_blocking_wait_rq: true if entity was waiting for a request 91962306a36Sopenharmony_ci * 92062306a36Sopenharmony_ci * Called for a 'true' activation, i.e., if entity is not active and 92162306a36Sopenharmony_ci * one of its children receives a new request. 92262306a36Sopenharmony_ci * 92362306a36Sopenharmony_ci * Basically, this function updates the timestamps of entity and 92462306a36Sopenharmony_ci * inserts entity into its active tree, after possibly extracting it 92562306a36Sopenharmony_ci * from its idle tree. 92662306a36Sopenharmony_ci */ 92762306a36Sopenharmony_cistatic void __bfq_activate_entity(struct bfq_entity *entity, 92862306a36Sopenharmony_ci bool non_blocking_wait_rq) 92962306a36Sopenharmony_ci{ 93062306a36Sopenharmony_ci struct bfq_service_tree *st = bfq_entity_service_tree(entity); 93162306a36Sopenharmony_ci bool backshifted = false; 93262306a36Sopenharmony_ci unsigned long long min_vstart; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci /* See comments on bfq_fqq_update_budg_for_activation */ 93562306a36Sopenharmony_ci if (non_blocking_wait_rq && bfq_gt(st->vtime, entity->finish)) { 93662306a36Sopenharmony_ci backshifted = true; 93762306a36Sopenharmony_ci min_vstart = entity->finish; 93862306a36Sopenharmony_ci } else 93962306a36Sopenharmony_ci min_vstart = st->vtime; 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci if (entity->tree == &st->idle) { 94262306a36Sopenharmony_ci /* 94362306a36Sopenharmony_ci * Must be on the idle tree, bfq_idle_extract() will 94462306a36Sopenharmony_ci * check for that. 94562306a36Sopenharmony_ci */ 94662306a36Sopenharmony_ci bfq_idle_extract(st, entity); 94762306a36Sopenharmony_ci entity->start = bfq_gt(min_vstart, entity->finish) ? 94862306a36Sopenharmony_ci min_vstart : entity->finish; 94962306a36Sopenharmony_ci } else { 95062306a36Sopenharmony_ci /* 95162306a36Sopenharmony_ci * The finish time of the entity may be invalid, and 95262306a36Sopenharmony_ci * it is in the past for sure, otherwise the queue 95362306a36Sopenharmony_ci * would have been on the idle tree. 95462306a36Sopenharmony_ci */ 95562306a36Sopenharmony_ci entity->start = min_vstart; 95662306a36Sopenharmony_ci st->wsum += entity->weight; 95762306a36Sopenharmony_ci /* 95862306a36Sopenharmony_ci * entity is about to be inserted into a service tree, 95962306a36Sopenharmony_ci * and then set in service: get a reference to make 96062306a36Sopenharmony_ci * sure entity does not disappear until it is no 96162306a36Sopenharmony_ci * longer in service or scheduled for service. 96262306a36Sopenharmony_ci */ 96362306a36Sopenharmony_ci bfq_get_entity(entity); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci entity->on_st_or_in_serv = true; 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci bfq_update_fin_time_enqueue(entity, st, backshifted); 96962306a36Sopenharmony_ci} 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci/** 97262306a36Sopenharmony_ci * __bfq_requeue_entity - handle requeueing or repositioning of an entity. 97362306a36Sopenharmony_ci * @entity: the entity being requeued or repositioned. 97462306a36Sopenharmony_ci * 97562306a36Sopenharmony_ci * Requeueing is needed if this entity stops being served, which 97662306a36Sopenharmony_ci * happens if a leaf descendant entity has expired. On the other hand, 97762306a36Sopenharmony_ci * repositioning is needed if the next_inservice_entity for the child 97862306a36Sopenharmony_ci * entity has changed. See the comments inside the function for 97962306a36Sopenharmony_ci * details. 98062306a36Sopenharmony_ci * 98162306a36Sopenharmony_ci * Basically, this function: 1) removes entity from its active tree if 98262306a36Sopenharmony_ci * present there, 2) updates the timestamps of entity and 3) inserts 98362306a36Sopenharmony_ci * entity back into its active tree (in the new, right position for 98462306a36Sopenharmony_ci * the new values of the timestamps). 98562306a36Sopenharmony_ci */ 98662306a36Sopenharmony_cistatic void __bfq_requeue_entity(struct bfq_entity *entity) 98762306a36Sopenharmony_ci{ 98862306a36Sopenharmony_ci struct bfq_sched_data *sd = entity->sched_data; 98962306a36Sopenharmony_ci struct bfq_service_tree *st = bfq_entity_service_tree(entity); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci if (entity == sd->in_service_entity) { 99262306a36Sopenharmony_ci /* 99362306a36Sopenharmony_ci * We are requeueing the current in-service entity, 99462306a36Sopenharmony_ci * which may have to be done for one of the following 99562306a36Sopenharmony_ci * reasons: 99662306a36Sopenharmony_ci * - entity represents the in-service queue, and the 99762306a36Sopenharmony_ci * in-service queue is being requeued after an 99862306a36Sopenharmony_ci * expiration; 99962306a36Sopenharmony_ci * - entity represents a group, and its budget has 100062306a36Sopenharmony_ci * changed because one of its child entities has 100162306a36Sopenharmony_ci * just been either activated or requeued for some 100262306a36Sopenharmony_ci * reason; the timestamps of the entity need then to 100362306a36Sopenharmony_ci * be updated, and the entity needs to be enqueued 100462306a36Sopenharmony_ci * or repositioned accordingly. 100562306a36Sopenharmony_ci * 100662306a36Sopenharmony_ci * In particular, before requeueing, the start time of 100762306a36Sopenharmony_ci * the entity must be moved forward to account for the 100862306a36Sopenharmony_ci * service that the entity has received while in 100962306a36Sopenharmony_ci * service. This is done by the next instructions. The 101062306a36Sopenharmony_ci * finish time will then be updated according to this 101162306a36Sopenharmony_ci * new value of the start time, and to the budget of 101262306a36Sopenharmony_ci * the entity. 101362306a36Sopenharmony_ci */ 101462306a36Sopenharmony_ci bfq_calc_finish(entity, entity->service); 101562306a36Sopenharmony_ci entity->start = entity->finish; 101662306a36Sopenharmony_ci /* 101762306a36Sopenharmony_ci * In addition, if the entity had more than one child 101862306a36Sopenharmony_ci * when set in service, then it was not extracted from 101962306a36Sopenharmony_ci * the active tree. This implies that the position of 102062306a36Sopenharmony_ci * the entity in the active tree may need to be 102162306a36Sopenharmony_ci * changed now, because we have just updated the start 102262306a36Sopenharmony_ci * time of the entity, and we will update its finish 102362306a36Sopenharmony_ci * time in a moment (the requeueing is then, more 102462306a36Sopenharmony_ci * precisely, a repositioning in this case). To 102562306a36Sopenharmony_ci * implement this repositioning, we: 1) dequeue the 102662306a36Sopenharmony_ci * entity here, 2) update the finish time and requeue 102762306a36Sopenharmony_ci * the entity according to the new timestamps below. 102862306a36Sopenharmony_ci */ 102962306a36Sopenharmony_ci if (entity->tree) 103062306a36Sopenharmony_ci bfq_active_extract(st, entity); 103162306a36Sopenharmony_ci } else { /* The entity is already active, and not in service */ 103262306a36Sopenharmony_ci /* 103362306a36Sopenharmony_ci * In this case, this function gets called only if the 103462306a36Sopenharmony_ci * next_in_service entity below this entity has 103562306a36Sopenharmony_ci * changed, and this change has caused the budget of 103662306a36Sopenharmony_ci * this entity to change, which, finally implies that 103762306a36Sopenharmony_ci * the finish time of this entity must be 103862306a36Sopenharmony_ci * updated. Such an update may cause the scheduling, 103962306a36Sopenharmony_ci * i.e., the position in the active tree, of this 104062306a36Sopenharmony_ci * entity to change. We handle this change by: 1) 104162306a36Sopenharmony_ci * dequeueing the entity here, 2) updating the finish 104262306a36Sopenharmony_ci * time and requeueing the entity according to the new 104362306a36Sopenharmony_ci * timestamps below. This is the same approach as the 104462306a36Sopenharmony_ci * non-extracted-entity sub-case above. 104562306a36Sopenharmony_ci */ 104662306a36Sopenharmony_ci bfq_active_extract(st, entity); 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci bfq_update_fin_time_enqueue(entity, st, false); 105062306a36Sopenharmony_ci} 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_cistatic void __bfq_activate_requeue_entity(struct bfq_entity *entity, 105362306a36Sopenharmony_ci bool non_blocking_wait_rq) 105462306a36Sopenharmony_ci{ 105562306a36Sopenharmony_ci struct bfq_service_tree *st = bfq_entity_service_tree(entity); 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci if (entity->sched_data->in_service_entity == entity || 105862306a36Sopenharmony_ci entity->tree == &st->active) 105962306a36Sopenharmony_ci /* 106062306a36Sopenharmony_ci * in service or already queued on the active tree, 106162306a36Sopenharmony_ci * requeue or reposition 106262306a36Sopenharmony_ci */ 106362306a36Sopenharmony_ci __bfq_requeue_entity(entity); 106462306a36Sopenharmony_ci else 106562306a36Sopenharmony_ci /* 106662306a36Sopenharmony_ci * Not in service and not queued on its active tree: 106762306a36Sopenharmony_ci * the activity is idle and this is a true activation. 106862306a36Sopenharmony_ci */ 106962306a36Sopenharmony_ci __bfq_activate_entity(entity, non_blocking_wait_rq); 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci/** 107462306a36Sopenharmony_ci * bfq_activate_requeue_entity - activate or requeue an entity representing a 107562306a36Sopenharmony_ci * bfq_queue, and activate, requeue or reposition 107662306a36Sopenharmony_ci * all ancestors for which such an update becomes 107762306a36Sopenharmony_ci * necessary. 107862306a36Sopenharmony_ci * @entity: the entity to activate. 107962306a36Sopenharmony_ci * @non_blocking_wait_rq: true if this entity was waiting for a request 108062306a36Sopenharmony_ci * @requeue: true if this is a requeue, which implies that bfqq is 108162306a36Sopenharmony_ci * being expired; thus ALL its ancestors stop being served and must 108262306a36Sopenharmony_ci * therefore be requeued 108362306a36Sopenharmony_ci * @expiration: true if this function is being invoked in the expiration path 108462306a36Sopenharmony_ci * of the in-service queue 108562306a36Sopenharmony_ci */ 108662306a36Sopenharmony_cistatic void bfq_activate_requeue_entity(struct bfq_entity *entity, 108762306a36Sopenharmony_ci bool non_blocking_wait_rq, 108862306a36Sopenharmony_ci bool requeue, bool expiration) 108962306a36Sopenharmony_ci{ 109062306a36Sopenharmony_ci for_each_entity(entity) { 109162306a36Sopenharmony_ci __bfq_activate_requeue_entity(entity, non_blocking_wait_rq); 109262306a36Sopenharmony_ci if (!bfq_update_next_in_service(entity->sched_data, entity, 109362306a36Sopenharmony_ci expiration) && !requeue) 109462306a36Sopenharmony_ci break; 109562306a36Sopenharmony_ci } 109662306a36Sopenharmony_ci} 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci/** 109962306a36Sopenharmony_ci * __bfq_deactivate_entity - update sched_data and service trees for 110062306a36Sopenharmony_ci * entity, so as to represent entity as inactive 110162306a36Sopenharmony_ci * @entity: the entity being deactivated. 110262306a36Sopenharmony_ci * @ins_into_idle_tree: if false, the entity will not be put into the 110362306a36Sopenharmony_ci * idle tree. 110462306a36Sopenharmony_ci * 110562306a36Sopenharmony_ci * If necessary and allowed, puts entity into the idle tree. NOTE: 110662306a36Sopenharmony_ci * entity may be on no tree if in service. 110762306a36Sopenharmony_ci */ 110862306a36Sopenharmony_cibool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree) 110962306a36Sopenharmony_ci{ 111062306a36Sopenharmony_ci struct bfq_sched_data *sd = entity->sched_data; 111162306a36Sopenharmony_ci struct bfq_service_tree *st; 111262306a36Sopenharmony_ci bool is_in_service; 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci if (!entity->on_st_or_in_serv) /* 111562306a36Sopenharmony_ci * entity never activated, or 111662306a36Sopenharmony_ci * already inactive 111762306a36Sopenharmony_ci */ 111862306a36Sopenharmony_ci return false; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci /* 112162306a36Sopenharmony_ci * If we get here, then entity is active, which implies that 112262306a36Sopenharmony_ci * bfq_group_set_parent has already been invoked for the group 112362306a36Sopenharmony_ci * represented by entity. Therefore, the field 112462306a36Sopenharmony_ci * entity->sched_data has been set, and we can safely use it. 112562306a36Sopenharmony_ci */ 112662306a36Sopenharmony_ci st = bfq_entity_service_tree(entity); 112762306a36Sopenharmony_ci is_in_service = entity == sd->in_service_entity; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci bfq_calc_finish(entity, entity->service); 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci if (is_in_service) 113262306a36Sopenharmony_ci sd->in_service_entity = NULL; 113362306a36Sopenharmony_ci else 113462306a36Sopenharmony_ci /* 113562306a36Sopenharmony_ci * Non in-service entity: nobody will take care of 113662306a36Sopenharmony_ci * resetting its service counter on expiration. Do it 113762306a36Sopenharmony_ci * now. 113862306a36Sopenharmony_ci */ 113962306a36Sopenharmony_ci entity->service = 0; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci if (entity->tree == &st->active) 114262306a36Sopenharmony_ci bfq_active_extract(st, entity); 114362306a36Sopenharmony_ci else if (!is_in_service && entity->tree == &st->idle) 114462306a36Sopenharmony_ci bfq_idle_extract(st, entity); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci if (!ins_into_idle_tree || !bfq_gt(entity->finish, st->vtime)) 114762306a36Sopenharmony_ci bfq_forget_entity(st, entity, is_in_service); 114862306a36Sopenharmony_ci else 114962306a36Sopenharmony_ci bfq_idle_insert(st, entity); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci return true; 115262306a36Sopenharmony_ci} 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci/** 115562306a36Sopenharmony_ci * bfq_deactivate_entity - deactivate an entity representing a bfq_queue. 115662306a36Sopenharmony_ci * @entity: the entity to deactivate. 115762306a36Sopenharmony_ci * @ins_into_idle_tree: true if the entity can be put into the idle tree 115862306a36Sopenharmony_ci * @expiration: true if this function is being invoked in the expiration path 115962306a36Sopenharmony_ci * of the in-service queue 116062306a36Sopenharmony_ci */ 116162306a36Sopenharmony_cistatic void bfq_deactivate_entity(struct bfq_entity *entity, 116262306a36Sopenharmony_ci bool ins_into_idle_tree, 116362306a36Sopenharmony_ci bool expiration) 116462306a36Sopenharmony_ci{ 116562306a36Sopenharmony_ci struct bfq_sched_data *sd; 116662306a36Sopenharmony_ci struct bfq_entity *parent = NULL; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci for_each_entity_safe(entity, parent) { 116962306a36Sopenharmony_ci sd = entity->sched_data; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci if (!__bfq_deactivate_entity(entity, ins_into_idle_tree)) { 117262306a36Sopenharmony_ci /* 117362306a36Sopenharmony_ci * entity is not in any tree any more, so 117462306a36Sopenharmony_ci * this deactivation is a no-op, and there is 117562306a36Sopenharmony_ci * nothing to change for upper-level entities 117662306a36Sopenharmony_ci * (in case of expiration, this can never 117762306a36Sopenharmony_ci * happen). 117862306a36Sopenharmony_ci */ 117962306a36Sopenharmony_ci return; 118062306a36Sopenharmony_ci } 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci if (sd->next_in_service == entity) 118362306a36Sopenharmony_ci /* 118462306a36Sopenharmony_ci * entity was the next_in_service entity, 118562306a36Sopenharmony_ci * then, since entity has just been 118662306a36Sopenharmony_ci * deactivated, a new one must be found. 118762306a36Sopenharmony_ci */ 118862306a36Sopenharmony_ci bfq_update_next_in_service(sd, NULL, expiration); 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci if (sd->next_in_service || sd->in_service_entity) { 119162306a36Sopenharmony_ci /* 119262306a36Sopenharmony_ci * The parent entity is still active, because 119362306a36Sopenharmony_ci * either next_in_service or in_service_entity 119462306a36Sopenharmony_ci * is not NULL. So, no further upwards 119562306a36Sopenharmony_ci * deactivation must be performed. Yet, 119662306a36Sopenharmony_ci * next_in_service has changed. Then the 119762306a36Sopenharmony_ci * schedule does need to be updated upwards. 119862306a36Sopenharmony_ci * 119962306a36Sopenharmony_ci * NOTE If in_service_entity is not NULL, then 120062306a36Sopenharmony_ci * next_in_service may happen to be NULL, 120162306a36Sopenharmony_ci * although the parent entity is evidently 120262306a36Sopenharmony_ci * active. This happens if 1) the entity 120362306a36Sopenharmony_ci * pointed by in_service_entity is the only 120462306a36Sopenharmony_ci * active entity in the parent entity, and 2) 120562306a36Sopenharmony_ci * according to the definition of 120662306a36Sopenharmony_ci * next_in_service, the in_service_entity 120762306a36Sopenharmony_ci * cannot be considered as 120862306a36Sopenharmony_ci * next_in_service. See the comments on the 120962306a36Sopenharmony_ci * definition of next_in_service for details. 121062306a36Sopenharmony_ci */ 121162306a36Sopenharmony_ci break; 121262306a36Sopenharmony_ci } 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci /* 121562306a36Sopenharmony_ci * If we get here, then the parent is no more 121662306a36Sopenharmony_ci * backlogged and we need to propagate the 121762306a36Sopenharmony_ci * deactivation upwards. Thus let the loop go on. 121862306a36Sopenharmony_ci */ 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci /* 122162306a36Sopenharmony_ci * Also let parent be queued into the idle tree on 122262306a36Sopenharmony_ci * deactivation, to preserve service guarantees, and 122362306a36Sopenharmony_ci * assuming that who invoked this function does not 122462306a36Sopenharmony_ci * need parent entities too to be removed completely. 122562306a36Sopenharmony_ci */ 122662306a36Sopenharmony_ci ins_into_idle_tree = true; 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci /* 123062306a36Sopenharmony_ci * If the deactivation loop is fully executed, then there are 123162306a36Sopenharmony_ci * no more entities to touch and next loop is not executed at 123262306a36Sopenharmony_ci * all. Otherwise, requeue remaining entities if they are 123362306a36Sopenharmony_ci * about to stop receiving service, or reposition them if this 123462306a36Sopenharmony_ci * is not the case. 123562306a36Sopenharmony_ci */ 123662306a36Sopenharmony_ci entity = parent; 123762306a36Sopenharmony_ci for_each_entity(entity) { 123862306a36Sopenharmony_ci /* 123962306a36Sopenharmony_ci * Invoke __bfq_requeue_entity on entity, even if 124062306a36Sopenharmony_ci * already active, to requeue/reposition it in the 124162306a36Sopenharmony_ci * active tree (because sd->next_in_service has 124262306a36Sopenharmony_ci * changed) 124362306a36Sopenharmony_ci */ 124462306a36Sopenharmony_ci __bfq_requeue_entity(entity); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci sd = entity->sched_data; 124762306a36Sopenharmony_ci if (!bfq_update_next_in_service(sd, entity, expiration) && 124862306a36Sopenharmony_ci !expiration) 124962306a36Sopenharmony_ci /* 125062306a36Sopenharmony_ci * next_in_service unchanged or not causing 125162306a36Sopenharmony_ci * any change in entity->parent->sd, and no 125262306a36Sopenharmony_ci * requeueing needed for expiration: stop 125362306a36Sopenharmony_ci * here. 125462306a36Sopenharmony_ci */ 125562306a36Sopenharmony_ci break; 125662306a36Sopenharmony_ci } 125762306a36Sopenharmony_ci} 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci/** 126062306a36Sopenharmony_ci * bfq_calc_vtime_jump - compute the value to which the vtime should jump, 126162306a36Sopenharmony_ci * if needed, to have at least one entity eligible. 126262306a36Sopenharmony_ci * @st: the service tree to act upon. 126362306a36Sopenharmony_ci * 126462306a36Sopenharmony_ci * Assumes that st is not empty. 126562306a36Sopenharmony_ci */ 126662306a36Sopenharmony_cistatic u64 bfq_calc_vtime_jump(struct bfq_service_tree *st) 126762306a36Sopenharmony_ci{ 126862306a36Sopenharmony_ci struct bfq_entity *root_entity = bfq_root_active_entity(&st->active); 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci if (bfq_gt(root_entity->min_start, st->vtime)) 127162306a36Sopenharmony_ci return root_entity->min_start; 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci return st->vtime; 127462306a36Sopenharmony_ci} 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_cistatic void bfq_update_vtime(struct bfq_service_tree *st, u64 new_value) 127762306a36Sopenharmony_ci{ 127862306a36Sopenharmony_ci if (new_value > st->vtime) { 127962306a36Sopenharmony_ci st->vtime = new_value; 128062306a36Sopenharmony_ci bfq_forget_idle(st); 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci/** 128562306a36Sopenharmony_ci * bfq_first_active_entity - find the eligible entity with 128662306a36Sopenharmony_ci * the smallest finish time 128762306a36Sopenharmony_ci * @st: the service tree to select from. 128862306a36Sopenharmony_ci * @vtime: the system virtual to use as a reference for eligibility 128962306a36Sopenharmony_ci * 129062306a36Sopenharmony_ci * This function searches the first schedulable entity, starting from the 129162306a36Sopenharmony_ci * root of the tree and going on the left every time on this side there is 129262306a36Sopenharmony_ci * a subtree with at least one eligible (start <= vtime) entity. The path on 129362306a36Sopenharmony_ci * the right is followed only if a) the left subtree contains no eligible 129462306a36Sopenharmony_ci * entities and b) no eligible entity has been found yet. 129562306a36Sopenharmony_ci */ 129662306a36Sopenharmony_cistatic struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st, 129762306a36Sopenharmony_ci u64 vtime) 129862306a36Sopenharmony_ci{ 129962306a36Sopenharmony_ci struct bfq_entity *entry, *first = NULL; 130062306a36Sopenharmony_ci struct rb_node *node = st->active.rb_node; 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci while (node) { 130362306a36Sopenharmony_ci entry = rb_entry(node, struct bfq_entity, rb_node); 130462306a36Sopenharmony_cileft: 130562306a36Sopenharmony_ci if (!bfq_gt(entry->start, vtime)) 130662306a36Sopenharmony_ci first = entry; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci if (node->rb_left) { 130962306a36Sopenharmony_ci entry = rb_entry(node->rb_left, 131062306a36Sopenharmony_ci struct bfq_entity, rb_node); 131162306a36Sopenharmony_ci if (!bfq_gt(entry->min_start, vtime)) { 131262306a36Sopenharmony_ci node = node->rb_left; 131362306a36Sopenharmony_ci goto left; 131462306a36Sopenharmony_ci } 131562306a36Sopenharmony_ci } 131662306a36Sopenharmony_ci if (first) 131762306a36Sopenharmony_ci break; 131862306a36Sopenharmony_ci node = node->rb_right; 131962306a36Sopenharmony_ci } 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci return first; 132262306a36Sopenharmony_ci} 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci/** 132562306a36Sopenharmony_ci * __bfq_lookup_next_entity - return the first eligible entity in @st. 132662306a36Sopenharmony_ci * @st: the service tree. 132762306a36Sopenharmony_ci * @in_service: whether or not there is an in-service entity for the sched_data 132862306a36Sopenharmony_ci * this active tree belongs to. 132962306a36Sopenharmony_ci * 133062306a36Sopenharmony_ci * If there is no in-service entity for the sched_data st belongs to, 133162306a36Sopenharmony_ci * then return the entity that will be set in service if: 133262306a36Sopenharmony_ci * 1) the parent entity this st belongs to is set in service; 133362306a36Sopenharmony_ci * 2) no entity belonging to such parent entity undergoes a state change 133462306a36Sopenharmony_ci * that would influence the timestamps of the entity (e.g., becomes idle, 133562306a36Sopenharmony_ci * becomes backlogged, changes its budget, ...). 133662306a36Sopenharmony_ci * 133762306a36Sopenharmony_ci * In this first case, update the virtual time in @st too (see the 133862306a36Sopenharmony_ci * comments on this update inside the function). 133962306a36Sopenharmony_ci * 134062306a36Sopenharmony_ci * In contrast, if there is an in-service entity, then return the 134162306a36Sopenharmony_ci * entity that would be set in service if not only the above 134262306a36Sopenharmony_ci * conditions, but also the next one held true: the currently 134362306a36Sopenharmony_ci * in-service entity, on expiration, 134462306a36Sopenharmony_ci * 1) gets a finish time equal to the current one, or 134562306a36Sopenharmony_ci * 2) is not eligible any more, or 134662306a36Sopenharmony_ci * 3) is idle. 134762306a36Sopenharmony_ci */ 134862306a36Sopenharmony_cistatic struct bfq_entity * 134962306a36Sopenharmony_ci__bfq_lookup_next_entity(struct bfq_service_tree *st, bool in_service) 135062306a36Sopenharmony_ci{ 135162306a36Sopenharmony_ci struct bfq_entity *entity; 135262306a36Sopenharmony_ci u64 new_vtime; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci if (RB_EMPTY_ROOT(&st->active)) 135562306a36Sopenharmony_ci return NULL; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci /* 135862306a36Sopenharmony_ci * Get the value of the system virtual time for which at 135962306a36Sopenharmony_ci * least one entity is eligible. 136062306a36Sopenharmony_ci */ 136162306a36Sopenharmony_ci new_vtime = bfq_calc_vtime_jump(st); 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci /* 136462306a36Sopenharmony_ci * If there is no in-service entity for the sched_data this 136562306a36Sopenharmony_ci * active tree belongs to, then push the system virtual time 136662306a36Sopenharmony_ci * up to the value that guarantees that at least one entity is 136762306a36Sopenharmony_ci * eligible. If, instead, there is an in-service entity, then 136862306a36Sopenharmony_ci * do not make any such update, because there is already an 136962306a36Sopenharmony_ci * eligible entity, namely the in-service one (even if the 137062306a36Sopenharmony_ci * entity is not on st, because it was extracted when set in 137162306a36Sopenharmony_ci * service). 137262306a36Sopenharmony_ci */ 137362306a36Sopenharmony_ci if (!in_service) 137462306a36Sopenharmony_ci bfq_update_vtime(st, new_vtime); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci entity = bfq_first_active_entity(st, new_vtime); 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci return entity; 137962306a36Sopenharmony_ci} 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci/** 138262306a36Sopenharmony_ci * bfq_lookup_next_entity - return the first eligible entity in @sd. 138362306a36Sopenharmony_ci * @sd: the sched_data. 138462306a36Sopenharmony_ci * @expiration: true if we are on the expiration path of the in-service queue 138562306a36Sopenharmony_ci * 138662306a36Sopenharmony_ci * This function is invoked when there has been a change in the trees 138762306a36Sopenharmony_ci * for sd, and we need to know what is the new next entity to serve 138862306a36Sopenharmony_ci * after this change. 138962306a36Sopenharmony_ci */ 139062306a36Sopenharmony_cistatic struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, 139162306a36Sopenharmony_ci bool expiration) 139262306a36Sopenharmony_ci{ 139362306a36Sopenharmony_ci struct bfq_service_tree *st = sd->service_tree; 139462306a36Sopenharmony_ci struct bfq_service_tree *idle_class_st = st + (BFQ_IOPRIO_CLASSES - 1); 139562306a36Sopenharmony_ci struct bfq_entity *entity = NULL; 139662306a36Sopenharmony_ci int class_idx = 0; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci /* 139962306a36Sopenharmony_ci * Choose from idle class, if needed to guarantee a minimum 140062306a36Sopenharmony_ci * bandwidth to this class (and if there is some active entity 140162306a36Sopenharmony_ci * in idle class). This should also mitigate 140262306a36Sopenharmony_ci * priority-inversion problems in case a low priority task is 140362306a36Sopenharmony_ci * holding file system resources. 140462306a36Sopenharmony_ci */ 140562306a36Sopenharmony_ci if (time_is_before_jiffies(sd->bfq_class_idle_last_service + 140662306a36Sopenharmony_ci BFQ_CL_IDLE_TIMEOUT)) { 140762306a36Sopenharmony_ci if (!RB_EMPTY_ROOT(&idle_class_st->active)) 140862306a36Sopenharmony_ci class_idx = BFQ_IOPRIO_CLASSES - 1; 140962306a36Sopenharmony_ci /* About to be served if backlogged, or not yet backlogged */ 141062306a36Sopenharmony_ci sd->bfq_class_idle_last_service = jiffies; 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci /* 141462306a36Sopenharmony_ci * Find the next entity to serve for the highest-priority 141562306a36Sopenharmony_ci * class, unless the idle class needs to be served. 141662306a36Sopenharmony_ci */ 141762306a36Sopenharmony_ci for (; class_idx < BFQ_IOPRIO_CLASSES; class_idx++) { 141862306a36Sopenharmony_ci /* 141962306a36Sopenharmony_ci * If expiration is true, then bfq_lookup_next_entity 142062306a36Sopenharmony_ci * is being invoked as a part of the expiration path 142162306a36Sopenharmony_ci * of the in-service queue. In this case, even if 142262306a36Sopenharmony_ci * sd->in_service_entity is not NULL, 142362306a36Sopenharmony_ci * sd->in_service_entity at this point is actually not 142462306a36Sopenharmony_ci * in service any more, and, if needed, has already 142562306a36Sopenharmony_ci * been properly queued or requeued into the right 142662306a36Sopenharmony_ci * tree. The reason why sd->in_service_entity is still 142762306a36Sopenharmony_ci * not NULL here, even if expiration is true, is that 142862306a36Sopenharmony_ci * sd->in_service_entity is reset as a last step in the 142962306a36Sopenharmony_ci * expiration path. So, if expiration is true, tell 143062306a36Sopenharmony_ci * __bfq_lookup_next_entity that there is no 143162306a36Sopenharmony_ci * sd->in_service_entity. 143262306a36Sopenharmony_ci */ 143362306a36Sopenharmony_ci entity = __bfq_lookup_next_entity(st + class_idx, 143462306a36Sopenharmony_ci sd->in_service_entity && 143562306a36Sopenharmony_ci !expiration); 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci if (entity) 143862306a36Sopenharmony_ci break; 143962306a36Sopenharmony_ci } 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci return entity; 144262306a36Sopenharmony_ci} 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_cibool next_queue_may_preempt(struct bfq_data *bfqd) 144562306a36Sopenharmony_ci{ 144662306a36Sopenharmony_ci struct bfq_sched_data *sd = &bfqd->root_group->sched_data; 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci return sd->next_in_service != sd->in_service_entity; 144962306a36Sopenharmony_ci} 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci/* 145262306a36Sopenharmony_ci * Get next queue for service. 145362306a36Sopenharmony_ci */ 145462306a36Sopenharmony_cistruct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) 145562306a36Sopenharmony_ci{ 145662306a36Sopenharmony_ci struct bfq_entity *entity = NULL; 145762306a36Sopenharmony_ci struct bfq_sched_data *sd; 145862306a36Sopenharmony_ci struct bfq_queue *bfqq; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci if (bfq_tot_busy_queues(bfqd) == 0) 146162306a36Sopenharmony_ci return NULL; 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci /* 146462306a36Sopenharmony_ci * Traverse the path from the root to the leaf entity to 146562306a36Sopenharmony_ci * serve. Set in service all the entities visited along the 146662306a36Sopenharmony_ci * way. 146762306a36Sopenharmony_ci */ 146862306a36Sopenharmony_ci sd = &bfqd->root_group->sched_data; 146962306a36Sopenharmony_ci for (; sd ; sd = entity->my_sched_data) { 147062306a36Sopenharmony_ci /* 147162306a36Sopenharmony_ci * WARNING. We are about to set the in-service entity 147262306a36Sopenharmony_ci * to sd->next_in_service, i.e., to the (cached) value 147362306a36Sopenharmony_ci * returned by bfq_lookup_next_entity(sd) the last 147462306a36Sopenharmony_ci * time it was invoked, i.e., the last time when the 147562306a36Sopenharmony_ci * service order in sd changed as a consequence of the 147662306a36Sopenharmony_ci * activation or deactivation of an entity. In this 147762306a36Sopenharmony_ci * respect, if we execute bfq_lookup_next_entity(sd) 147862306a36Sopenharmony_ci * in this very moment, it may, although with low 147962306a36Sopenharmony_ci * probability, yield a different entity than that 148062306a36Sopenharmony_ci * pointed to by sd->next_in_service. This rare event 148162306a36Sopenharmony_ci * happens in case there was no CLASS_IDLE entity to 148262306a36Sopenharmony_ci * serve for sd when bfq_lookup_next_entity(sd) was 148362306a36Sopenharmony_ci * invoked for the last time, while there is now one 148462306a36Sopenharmony_ci * such entity. 148562306a36Sopenharmony_ci * 148662306a36Sopenharmony_ci * If the above event happens, then the scheduling of 148762306a36Sopenharmony_ci * such entity in CLASS_IDLE is postponed until the 148862306a36Sopenharmony_ci * service of the sd->next_in_service entity 148962306a36Sopenharmony_ci * finishes. In fact, when the latter is expired, 149062306a36Sopenharmony_ci * bfq_lookup_next_entity(sd) gets called again, 149162306a36Sopenharmony_ci * exactly to update sd->next_in_service. 149262306a36Sopenharmony_ci */ 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci /* Make next_in_service entity become in_service_entity */ 149562306a36Sopenharmony_ci entity = sd->next_in_service; 149662306a36Sopenharmony_ci sd->in_service_entity = entity; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci /* 149962306a36Sopenharmony_ci * If entity is no longer a candidate for next 150062306a36Sopenharmony_ci * service, then it must be extracted from its active 150162306a36Sopenharmony_ci * tree, so as to make sure that it won't be 150262306a36Sopenharmony_ci * considered when computing next_in_service. See the 150362306a36Sopenharmony_ci * comments on the function 150462306a36Sopenharmony_ci * bfq_no_longer_next_in_service() for details. 150562306a36Sopenharmony_ci */ 150662306a36Sopenharmony_ci if (bfq_no_longer_next_in_service(entity)) 150762306a36Sopenharmony_ci bfq_active_extract(bfq_entity_service_tree(entity), 150862306a36Sopenharmony_ci entity); 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci /* 151162306a36Sopenharmony_ci * Even if entity is not to be extracted according to 151262306a36Sopenharmony_ci * the above check, a descendant entity may get 151362306a36Sopenharmony_ci * extracted in one of the next iterations of this 151462306a36Sopenharmony_ci * loop. Such an event could cause a change in 151562306a36Sopenharmony_ci * next_in_service for the level of the descendant 151662306a36Sopenharmony_ci * entity, and thus possibly back to this level. 151762306a36Sopenharmony_ci * 151862306a36Sopenharmony_ci * However, we cannot perform the resulting needed 151962306a36Sopenharmony_ci * update of next_in_service for this level before the 152062306a36Sopenharmony_ci * end of the whole loop, because, to know which is 152162306a36Sopenharmony_ci * the correct next-to-serve candidate entity for each 152262306a36Sopenharmony_ci * level, we need first to find the leaf entity to set 152362306a36Sopenharmony_ci * in service. In fact, only after we know which is 152462306a36Sopenharmony_ci * the next-to-serve leaf entity, we can discover 152562306a36Sopenharmony_ci * whether the parent entity of the leaf entity 152662306a36Sopenharmony_ci * becomes the next-to-serve, and so on. 152762306a36Sopenharmony_ci */ 152862306a36Sopenharmony_ci } 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci bfqq = bfq_entity_to_bfqq(entity); 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci /* 153362306a36Sopenharmony_ci * We can finally update all next-to-serve entities along the 153462306a36Sopenharmony_ci * path from the leaf entity just set in service to the root. 153562306a36Sopenharmony_ci */ 153662306a36Sopenharmony_ci for_each_entity(entity) { 153762306a36Sopenharmony_ci struct bfq_sched_data *sd = entity->sched_data; 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci if (!bfq_update_next_in_service(sd, NULL, false)) 154062306a36Sopenharmony_ci break; 154162306a36Sopenharmony_ci } 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci return bfqq; 154462306a36Sopenharmony_ci} 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci/* returns true if the in-service queue gets freed */ 154762306a36Sopenharmony_cibool __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) 154862306a36Sopenharmony_ci{ 154962306a36Sopenharmony_ci struct bfq_queue *in_serv_bfqq = bfqd->in_service_queue; 155062306a36Sopenharmony_ci struct bfq_entity *in_serv_entity = &in_serv_bfqq->entity; 155162306a36Sopenharmony_ci struct bfq_entity *entity = in_serv_entity; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci bfq_clear_bfqq_wait_request(in_serv_bfqq); 155462306a36Sopenharmony_ci hrtimer_try_to_cancel(&bfqd->idle_slice_timer); 155562306a36Sopenharmony_ci bfqd->in_service_queue = NULL; 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci /* 155862306a36Sopenharmony_ci * When this function is called, all in-service entities have 155962306a36Sopenharmony_ci * been properly deactivated or requeued, so we can safely 156062306a36Sopenharmony_ci * execute the final step: reset in_service_entity along the 156162306a36Sopenharmony_ci * path from entity to the root. 156262306a36Sopenharmony_ci */ 156362306a36Sopenharmony_ci for_each_entity(entity) 156462306a36Sopenharmony_ci entity->sched_data->in_service_entity = NULL; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci /* 156762306a36Sopenharmony_ci * in_serv_entity is no longer in service, so, if it is in no 156862306a36Sopenharmony_ci * service tree either, then release the service reference to 156962306a36Sopenharmony_ci * the queue it represents (taken with bfq_get_entity). 157062306a36Sopenharmony_ci */ 157162306a36Sopenharmony_ci if (!in_serv_entity->on_st_or_in_serv) { 157262306a36Sopenharmony_ci /* 157362306a36Sopenharmony_ci * If no process is referencing in_serv_bfqq any 157462306a36Sopenharmony_ci * longer, then the service reference may be the only 157562306a36Sopenharmony_ci * reference to the queue. If this is the case, then 157662306a36Sopenharmony_ci * bfqq gets freed here. 157762306a36Sopenharmony_ci */ 157862306a36Sopenharmony_ci int ref = in_serv_bfqq->ref; 157962306a36Sopenharmony_ci bfq_put_queue(in_serv_bfqq); 158062306a36Sopenharmony_ci if (ref == 1) 158162306a36Sopenharmony_ci return true; 158262306a36Sopenharmony_ci } 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci return false; 158562306a36Sopenharmony_ci} 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_civoid bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, 158862306a36Sopenharmony_ci bool ins_into_idle_tree, bool expiration) 158962306a36Sopenharmony_ci{ 159062306a36Sopenharmony_ci struct bfq_entity *entity = &bfqq->entity; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci bfq_deactivate_entity(entity, ins_into_idle_tree, expiration); 159362306a36Sopenharmony_ci} 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_civoid bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) 159662306a36Sopenharmony_ci{ 159762306a36Sopenharmony_ci struct bfq_entity *entity = &bfqq->entity; 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci bfq_activate_requeue_entity(entity, bfq_bfqq_non_blocking_wait_rq(bfqq), 160062306a36Sopenharmony_ci false, false); 160162306a36Sopenharmony_ci bfq_clear_bfqq_non_blocking_wait_rq(bfqq); 160262306a36Sopenharmony_ci} 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_civoid bfq_requeue_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, 160562306a36Sopenharmony_ci bool expiration) 160662306a36Sopenharmony_ci{ 160762306a36Sopenharmony_ci struct bfq_entity *entity = &bfqq->entity; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci bfq_activate_requeue_entity(entity, false, 161062306a36Sopenharmony_ci bfqq == bfqd->in_service_queue, expiration); 161162306a36Sopenharmony_ci} 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_civoid bfq_add_bfqq_in_groups_with_pending_reqs(struct bfq_queue *bfqq) 161462306a36Sopenharmony_ci{ 161562306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 161662306a36Sopenharmony_ci struct bfq_entity *entity = &bfqq->entity; 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci if (!entity->in_groups_with_pending_reqs) { 161962306a36Sopenharmony_ci entity->in_groups_with_pending_reqs = true; 162062306a36Sopenharmony_ci if (!(bfqq_group(bfqq)->num_queues_with_pending_reqs++)) 162162306a36Sopenharmony_ci bfqq->bfqd->num_groups_with_pending_reqs++; 162262306a36Sopenharmony_ci } 162362306a36Sopenharmony_ci#endif 162462306a36Sopenharmony_ci} 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_civoid bfq_del_bfqq_in_groups_with_pending_reqs(struct bfq_queue *bfqq) 162762306a36Sopenharmony_ci{ 162862306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 162962306a36Sopenharmony_ci struct bfq_entity *entity = &bfqq->entity; 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci if (entity->in_groups_with_pending_reqs) { 163262306a36Sopenharmony_ci entity->in_groups_with_pending_reqs = false; 163362306a36Sopenharmony_ci if (!(--bfqq_group(bfqq)->num_queues_with_pending_reqs)) 163462306a36Sopenharmony_ci bfqq->bfqd->num_groups_with_pending_reqs--; 163562306a36Sopenharmony_ci } 163662306a36Sopenharmony_ci#endif 163762306a36Sopenharmony_ci} 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci/* 164062306a36Sopenharmony_ci * Called when the bfqq no longer has requests pending, remove it from 164162306a36Sopenharmony_ci * the service tree. As a special case, it can be invoked during an 164262306a36Sopenharmony_ci * expiration. 164362306a36Sopenharmony_ci */ 164462306a36Sopenharmony_civoid bfq_del_bfqq_busy(struct bfq_queue *bfqq, bool expiration) 164562306a36Sopenharmony_ci{ 164662306a36Sopenharmony_ci struct bfq_data *bfqd = bfqq->bfqd; 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci bfq_log_bfqq(bfqd, bfqq, "del from busy"); 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci bfq_clear_bfqq_busy(bfqq); 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci bfqd->busy_queues[bfqq->ioprio_class - 1]--; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci if (bfqq->wr_coeff > 1) 165562306a36Sopenharmony_ci bfqd->wr_busy_queues--; 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci bfqg_stats_update_dequeue(bfqq_group(bfqq)); 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci bfq_deactivate_bfqq(bfqd, bfqq, true, expiration); 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci if (!bfqq->dispatched) { 166262306a36Sopenharmony_ci bfq_del_bfqq_in_groups_with_pending_reqs(bfqq); 166362306a36Sopenharmony_ci /* 166462306a36Sopenharmony_ci * Next function is invoked last, because it causes bfqq to be 166562306a36Sopenharmony_ci * freed. DO NOT use bfqq after the next function invocation. 166662306a36Sopenharmony_ci */ 166762306a36Sopenharmony_ci bfq_weights_tree_remove(bfqq); 166862306a36Sopenharmony_ci } 166962306a36Sopenharmony_ci} 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci/* 167262306a36Sopenharmony_ci * Called when an inactive queue receives a new request. 167362306a36Sopenharmony_ci */ 167462306a36Sopenharmony_civoid bfq_add_bfqq_busy(struct bfq_queue *bfqq) 167562306a36Sopenharmony_ci{ 167662306a36Sopenharmony_ci struct bfq_data *bfqd = bfqq->bfqd; 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci bfq_log_bfqq(bfqd, bfqq, "add to busy"); 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci bfq_activate_bfqq(bfqd, bfqq); 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci bfq_mark_bfqq_busy(bfqq); 168362306a36Sopenharmony_ci bfqd->busy_queues[bfqq->ioprio_class - 1]++; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci if (!bfqq->dispatched) { 168662306a36Sopenharmony_ci bfq_add_bfqq_in_groups_with_pending_reqs(bfqq); 168762306a36Sopenharmony_ci if (bfqq->wr_coeff == 1) 168862306a36Sopenharmony_ci bfq_weights_tree_add(bfqq); 168962306a36Sopenharmony_ci } 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci if (bfqq->wr_coeff > 1) 169262306a36Sopenharmony_ci bfqd->wr_busy_queues++; 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci /* Move bfqq to the head of the woken list of its waker */ 169562306a36Sopenharmony_ci if (!hlist_unhashed(&bfqq->woken_list_node) && 169662306a36Sopenharmony_ci &bfqq->woken_list_node != bfqq->waker_bfqq->woken_list.first) { 169762306a36Sopenharmony_ci hlist_del_init(&bfqq->woken_list_node); 169862306a36Sopenharmony_ci hlist_add_head(&bfqq->woken_list_node, 169962306a36Sopenharmony_ci &bfqq->waker_bfqq->woken_list); 170062306a36Sopenharmony_ci } 170162306a36Sopenharmony_ci} 1702