162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Header file for the BFQ I/O scheduler: data structures and 462306a36Sopenharmony_ci * prototypes of interface functions among BFQ components. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef _BFQ_H 762306a36Sopenharmony_ci#define _BFQ_H 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/blktrace_api.h> 1062306a36Sopenharmony_ci#include <linux/hrtimer.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "blk-cgroup-rwstat.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define BFQ_IOPRIO_CLASSES 3 1562306a36Sopenharmony_ci#define BFQ_CL_IDLE_TIMEOUT (HZ/5) 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define BFQ_MIN_WEIGHT 1 1862306a36Sopenharmony_ci#define BFQ_MAX_WEIGHT 1000 1962306a36Sopenharmony_ci#define BFQ_WEIGHT_CONVERSION_COEFF 10 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define BFQ_DEFAULT_QUEUE_IOPRIO 4 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define BFQ_DEFAULT_GRP_IOPRIO 0 2462306a36Sopenharmony_ci#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define MAX_BFQQ_NAME_LENGTH 16 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* 2962306a36Sopenharmony_ci * Soft real-time applications are extremely more latency sensitive 3062306a36Sopenharmony_ci * than interactive ones. Over-raise the weight of the former to 3162306a36Sopenharmony_ci * privilege them against the latter. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci#define BFQ_SOFTRT_WEIGHT_FACTOR 100 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * Maximum number of actuators supported. This constant is used simply 3762306a36Sopenharmony_ci * to define the size of the static array that will contain 3862306a36Sopenharmony_ci * per-actuator data. The current value is hopefully a good upper 3962306a36Sopenharmony_ci * bound to the possible number of actuators of any actual drive. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci#define BFQ_MAX_ACTUATORS 8 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistruct bfq_entity; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/** 4662306a36Sopenharmony_ci * struct bfq_service_tree - per ioprio_class service tree. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * Each service tree represents a B-WF2Q+ scheduler on its own. Each 4962306a36Sopenharmony_ci * ioprio_class has its own independent scheduler, and so its own 5062306a36Sopenharmony_ci * bfq_service_tree. All the fields are protected by the queue lock 5162306a36Sopenharmony_ci * of the containing bfqd. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_cistruct bfq_service_tree { 5462306a36Sopenharmony_ci /* tree for active entities (i.e., those backlogged) */ 5562306a36Sopenharmony_ci struct rb_root active; 5662306a36Sopenharmony_ci /* tree for idle entities (i.e., not backlogged, with V < F_i)*/ 5762306a36Sopenharmony_ci struct rb_root idle; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* idle entity with minimum F_i */ 6062306a36Sopenharmony_ci struct bfq_entity *first_idle; 6162306a36Sopenharmony_ci /* idle entity with maximum F_i */ 6262306a36Sopenharmony_ci struct bfq_entity *last_idle; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* scheduler virtual time */ 6562306a36Sopenharmony_ci u64 vtime; 6662306a36Sopenharmony_ci /* scheduler weight sum; active and idle entities contribute to it */ 6762306a36Sopenharmony_ci unsigned long wsum; 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/** 7162306a36Sopenharmony_ci * struct bfq_sched_data - multi-class scheduler. 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * bfq_sched_data is the basic scheduler queue. It supports three 7462306a36Sopenharmony_ci * ioprio_classes, and can be used either as a toplevel queue or as an 7562306a36Sopenharmony_ci * intermediate queue in a hierarchical setup. 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * The supported ioprio_classes are the same as in CFQ, in descending 7862306a36Sopenharmony_ci * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. 7962306a36Sopenharmony_ci * Requests from higher priority queues are served before all the 8062306a36Sopenharmony_ci * requests from lower priority queues; among requests of the same 8162306a36Sopenharmony_ci * queue requests are served according to B-WF2Q+. 8262306a36Sopenharmony_ci * 8362306a36Sopenharmony_ci * The schedule is implemented by the service trees, plus the field 8462306a36Sopenharmony_ci * @next_in_service, which points to the entity on the active trees 8562306a36Sopenharmony_ci * that will be served next, if 1) no changes in the schedule occurs 8662306a36Sopenharmony_ci * before the current in-service entity is expired, 2) the in-service 8762306a36Sopenharmony_ci * queue becomes idle when it expires, and 3) if the entity pointed by 8862306a36Sopenharmony_ci * in_service_entity is not a queue, then the in-service child entity 8962306a36Sopenharmony_ci * of the entity pointed by in_service_entity becomes idle on 9062306a36Sopenharmony_ci * expiration. This peculiar definition allows for the following 9162306a36Sopenharmony_ci * optimization, not yet exploited: while a given entity is still in 9262306a36Sopenharmony_ci * service, we already know which is the best candidate for next 9362306a36Sopenharmony_ci * service among the other active entities in the same parent 9462306a36Sopenharmony_ci * entity. We can then quickly compare the timestamps of the 9562306a36Sopenharmony_ci * in-service entity with those of such best candidate. 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * All fields are protected by the lock of the containing bfqd. 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_cistruct bfq_sched_data { 10062306a36Sopenharmony_ci /* entity in service */ 10162306a36Sopenharmony_ci struct bfq_entity *in_service_entity; 10262306a36Sopenharmony_ci /* head-of-line entity (see comments above) */ 10362306a36Sopenharmony_ci struct bfq_entity *next_in_service; 10462306a36Sopenharmony_ci /* array of service trees, one per ioprio_class */ 10562306a36Sopenharmony_ci struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; 10662306a36Sopenharmony_ci /* last time CLASS_IDLE was served */ 10762306a36Sopenharmony_ci unsigned long bfq_class_idle_last_service; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci}; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/** 11262306a36Sopenharmony_ci * struct bfq_weight_counter - counter of the number of all active queues 11362306a36Sopenharmony_ci * with a given weight. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_cistruct bfq_weight_counter { 11662306a36Sopenharmony_ci unsigned int weight; /* weight of the queues this counter refers to */ 11762306a36Sopenharmony_ci unsigned int num_active; /* nr of active queues with this weight */ 11862306a36Sopenharmony_ci /* 11962306a36Sopenharmony_ci * Weights tree member (see bfq_data's @queue_weights_tree) 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci struct rb_node weights_node; 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/** 12562306a36Sopenharmony_ci * struct bfq_entity - schedulable entity. 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * A bfq_entity is used to represent either a bfq_queue (leaf node in the 12862306a36Sopenharmony_ci * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each 12962306a36Sopenharmony_ci * entity belongs to the sched_data of the parent group in the cgroup 13062306a36Sopenharmony_ci * hierarchy. Non-leaf entities have also their own sched_data, stored 13162306a36Sopenharmony_ci * in @my_sched_data. 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci * Each entity stores independently its priority values; this would 13462306a36Sopenharmony_ci * allow different weights on different devices, but this 13562306a36Sopenharmony_ci * functionality is not exported to userspace by now. Priorities and 13662306a36Sopenharmony_ci * weights are updated lazily, first storing the new values into the 13762306a36Sopenharmony_ci * new_* fields, then setting the @prio_changed flag. As soon as 13862306a36Sopenharmony_ci * there is a transition in the entity state that allows the priority 13962306a36Sopenharmony_ci * update to take place the effective and the requested priority 14062306a36Sopenharmony_ci * values are synchronized. 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * Unless cgroups are used, the weight value is calculated from the 14362306a36Sopenharmony_ci * ioprio to export the same interface as CFQ. When dealing with 14462306a36Sopenharmony_ci * "well-behaved" queues (i.e., queues that do not spend too much 14562306a36Sopenharmony_ci * time to consume their budget and have true sequential behavior, and 14662306a36Sopenharmony_ci * when there are no external factors breaking anticipation) the 14762306a36Sopenharmony_ci * relative weights at each level of the cgroups hierarchy should be 14862306a36Sopenharmony_ci * guaranteed. All the fields are protected by the queue lock of the 14962306a36Sopenharmony_ci * containing bfqd. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_cistruct bfq_entity { 15262306a36Sopenharmony_ci /* service_tree member */ 15362306a36Sopenharmony_ci struct rb_node rb_node; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* 15662306a36Sopenharmony_ci * Flag, true if the entity is on a tree (either the active or 15762306a36Sopenharmony_ci * the idle one of its service_tree) or is in service. 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_ci bool on_st_or_in_serv; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* B-WF2Q+ start and finish timestamps [sectors/weight] */ 16262306a36Sopenharmony_ci u64 start, finish; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* tree the entity is enqueued into; %NULL if not on a tree */ 16562306a36Sopenharmony_ci struct rb_root *tree; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* 16862306a36Sopenharmony_ci * minimum start time of the (active) subtree rooted at this 16962306a36Sopenharmony_ci * entity; used for O(log N) lookups into active trees 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_ci u64 min_start; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* amount of service received during the last service slot */ 17462306a36Sopenharmony_ci int service; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci /* budget, used also to calculate F_i: F_i = S_i + @budget / @weight */ 17762306a36Sopenharmony_ci int budget; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* Number of requests allocated in the subtree of this entity */ 18062306a36Sopenharmony_ci int allocated; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* device weight, if non-zero, it overrides the default weight of 18362306a36Sopenharmony_ci * bfq_group_data */ 18462306a36Sopenharmony_ci int dev_weight; 18562306a36Sopenharmony_ci /* weight of the queue */ 18662306a36Sopenharmony_ci int weight; 18762306a36Sopenharmony_ci /* next weight if a change is in progress */ 18862306a36Sopenharmony_ci int new_weight; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* original weight, used to implement weight boosting */ 19162306a36Sopenharmony_ci int orig_weight; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* parent entity, for hierarchical scheduling */ 19462306a36Sopenharmony_ci struct bfq_entity *parent; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci /* 19762306a36Sopenharmony_ci * For non-leaf nodes in the hierarchy, the associated 19862306a36Sopenharmony_ci * scheduler queue, %NULL on leaf nodes. 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_ci struct bfq_sched_data *my_sched_data; 20162306a36Sopenharmony_ci /* the scheduler queue this entity belongs to */ 20262306a36Sopenharmony_ci struct bfq_sched_data *sched_data; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* flag, set to request a weight, ioprio or ioprio_class change */ 20562306a36Sopenharmony_ci int prio_changed; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 20862306a36Sopenharmony_ci /* flag, set if the entity is counted in groups_with_pending_reqs */ 20962306a36Sopenharmony_ci bool in_groups_with_pending_reqs; 21062306a36Sopenharmony_ci#endif 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* last child queue of entity created (for non-leaf entities) */ 21362306a36Sopenharmony_ci struct bfq_queue *last_bfqq_created; 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistruct bfq_group; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/** 21962306a36Sopenharmony_ci * struct bfq_ttime - per process thinktime stats. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_cistruct bfq_ttime { 22262306a36Sopenharmony_ci /* completion time of the last request */ 22362306a36Sopenharmony_ci u64 last_end_request; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* total process thinktime */ 22662306a36Sopenharmony_ci u64 ttime_total; 22762306a36Sopenharmony_ci /* number of thinktime samples */ 22862306a36Sopenharmony_ci unsigned long ttime_samples; 22962306a36Sopenharmony_ci /* average process thinktime */ 23062306a36Sopenharmony_ci u64 ttime_mean; 23162306a36Sopenharmony_ci}; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/** 23462306a36Sopenharmony_ci * struct bfq_queue - leaf schedulable entity. 23562306a36Sopenharmony_ci * 23662306a36Sopenharmony_ci * A bfq_queue is a leaf request queue; it can be associated with an 23762306a36Sopenharmony_ci * io_context or more, if it is async or shared between cooperating 23862306a36Sopenharmony_ci * processes. Besides, it contains I/O requests for only one actuator 23962306a36Sopenharmony_ci * (an io_context is associated with a different bfq_queue for each 24062306a36Sopenharmony_ci * actuator it generates I/O for). @cgroup holds a reference to the 24162306a36Sopenharmony_ci * cgroup, to be sure that it does not disappear while a bfqq still 24262306a36Sopenharmony_ci * references it (mostly to avoid races between request issuing and 24362306a36Sopenharmony_ci * task migration followed by cgroup destruction). All the fields are 24462306a36Sopenharmony_ci * protected by the queue lock of the containing bfqd. 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_cistruct bfq_queue { 24762306a36Sopenharmony_ci /* reference counter */ 24862306a36Sopenharmony_ci int ref; 24962306a36Sopenharmony_ci /* counter of references from other queues for delayed stable merge */ 25062306a36Sopenharmony_ci int stable_ref; 25162306a36Sopenharmony_ci /* parent bfq_data */ 25262306a36Sopenharmony_ci struct bfq_data *bfqd; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* current ioprio and ioprio class */ 25562306a36Sopenharmony_ci unsigned short ioprio, ioprio_class; 25662306a36Sopenharmony_ci /* next ioprio and ioprio class if a change is in progress */ 25762306a36Sopenharmony_ci unsigned short new_ioprio, new_ioprio_class; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* last total-service-time sample, see bfq_update_inject_limit() */ 26062306a36Sopenharmony_ci u64 last_serv_time_ns; 26162306a36Sopenharmony_ci /* limit for request injection */ 26262306a36Sopenharmony_ci unsigned int inject_limit; 26362306a36Sopenharmony_ci /* last time the inject limit has been decreased, in jiffies */ 26462306a36Sopenharmony_ci unsigned long decrease_time_jif; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* 26762306a36Sopenharmony_ci * Shared bfq_queue if queue is cooperating with one or more 26862306a36Sopenharmony_ci * other queues. 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_ci struct bfq_queue *new_bfqq; 27162306a36Sopenharmony_ci /* request-position tree member (see bfq_group's @rq_pos_tree) */ 27262306a36Sopenharmony_ci struct rb_node pos_node; 27362306a36Sopenharmony_ci /* request-position tree root (see bfq_group's @rq_pos_tree) */ 27462306a36Sopenharmony_ci struct rb_root *pos_root; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* sorted list of pending requests */ 27762306a36Sopenharmony_ci struct rb_root sort_list; 27862306a36Sopenharmony_ci /* if fifo isn't expired, next request to serve */ 27962306a36Sopenharmony_ci struct request *next_rq; 28062306a36Sopenharmony_ci /* number of sync and async requests queued */ 28162306a36Sopenharmony_ci int queued[2]; 28262306a36Sopenharmony_ci /* number of pending metadata requests */ 28362306a36Sopenharmony_ci int meta_pending; 28462306a36Sopenharmony_ci /* fifo list of requests in sort_list */ 28562306a36Sopenharmony_ci struct list_head fifo; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci /* entity representing this queue in the scheduler */ 28862306a36Sopenharmony_ci struct bfq_entity entity; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* pointer to the weight counter associated with this entity */ 29162306a36Sopenharmony_ci struct bfq_weight_counter *weight_counter; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* maximum budget allowed from the feedback mechanism */ 29462306a36Sopenharmony_ci int max_budget; 29562306a36Sopenharmony_ci /* budget expiration (in jiffies) */ 29662306a36Sopenharmony_ci unsigned long budget_timeout; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* number of requests on the dispatch list or inside driver */ 29962306a36Sopenharmony_ci int dispatched; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* status flags */ 30262306a36Sopenharmony_ci unsigned long flags; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* node for active/idle bfqq list inside parent bfqd */ 30562306a36Sopenharmony_ci struct list_head bfqq_list; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* associated @bfq_ttime struct */ 30862306a36Sopenharmony_ci struct bfq_ttime ttime; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* when bfqq started to do I/O within the last observation window */ 31162306a36Sopenharmony_ci u64 io_start_time; 31262306a36Sopenharmony_ci /* how long bfqq has remained empty during the last observ. window */ 31362306a36Sopenharmony_ci u64 tot_idle_time; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* bit vector: a 1 for each seeky requests in history */ 31662306a36Sopenharmony_ci u32 seek_history; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci /* node for the device's burst list */ 31962306a36Sopenharmony_ci struct hlist_node burst_list_node; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* position of the last request enqueued */ 32262306a36Sopenharmony_ci sector_t last_request_pos; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* Number of consecutive pairs of request completion and 32562306a36Sopenharmony_ci * arrival, such that the queue becomes idle after the 32662306a36Sopenharmony_ci * completion, but the next request arrives within an idle 32762306a36Sopenharmony_ci * time slice; used only if the queue's IO_bound flag has been 32862306a36Sopenharmony_ci * cleared. 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_ci unsigned int requests_within_timer; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci /* pid of the process owning the queue, used for logging purposes */ 33362306a36Sopenharmony_ci pid_t pid; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* 33662306a36Sopenharmony_ci * Pointer to the bfq_io_cq owning the bfq_queue, set to %NULL 33762306a36Sopenharmony_ci * if the queue is shared. 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_ci struct bfq_io_cq *bic; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* current maximum weight-raising time for this queue */ 34262306a36Sopenharmony_ci unsigned long wr_cur_max_time; 34362306a36Sopenharmony_ci /* 34462306a36Sopenharmony_ci * Minimum time instant such that, only if a new request is 34562306a36Sopenharmony_ci * enqueued after this time instant in an idle @bfq_queue with 34662306a36Sopenharmony_ci * no outstanding requests, then the task associated with the 34762306a36Sopenharmony_ci * queue it is deemed as soft real-time (see the comments on 34862306a36Sopenharmony_ci * the function bfq_bfqq_softrt_next_start()) 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_ci unsigned long soft_rt_next_start; 35162306a36Sopenharmony_ci /* 35262306a36Sopenharmony_ci * Start time of the current weight-raising period if 35362306a36Sopenharmony_ci * the @bfq-queue is being weight-raised, otherwise 35462306a36Sopenharmony_ci * finish time of the last weight-raising period. 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_ci unsigned long last_wr_start_finish; 35762306a36Sopenharmony_ci /* factor by which the weight of this queue is multiplied */ 35862306a36Sopenharmony_ci unsigned int wr_coeff; 35962306a36Sopenharmony_ci /* 36062306a36Sopenharmony_ci * Time of the last transition of the @bfq_queue from idle to 36162306a36Sopenharmony_ci * backlogged. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ci unsigned long last_idle_bklogged; 36462306a36Sopenharmony_ci /* 36562306a36Sopenharmony_ci * Cumulative service received from the @bfq_queue since the 36662306a36Sopenharmony_ci * last transition from idle to backlogged. 36762306a36Sopenharmony_ci */ 36862306a36Sopenharmony_ci unsigned long service_from_backlogged; 36962306a36Sopenharmony_ci /* 37062306a36Sopenharmony_ci * Cumulative service received from the @bfq_queue since its 37162306a36Sopenharmony_ci * last transition to weight-raised state. 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_ci unsigned long service_from_wr; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* 37662306a36Sopenharmony_ci * Value of wr start time when switching to soft rt 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_ci unsigned long wr_start_at_switch_to_srt; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci unsigned long split_time; /* time of last split */ 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci unsigned long first_IO_time; /* time of first I/O for this queue */ 38362306a36Sopenharmony_ci unsigned long creation_time; /* when this queue is created */ 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* 38662306a36Sopenharmony_ci * Pointer to the waker queue for this queue, i.e., to the 38762306a36Sopenharmony_ci * queue Q such that this queue happens to get new I/O right 38862306a36Sopenharmony_ci * after some I/O request of Q is completed. For details, see 38962306a36Sopenharmony_ci * the comments on the choice of the queue for injection in 39062306a36Sopenharmony_ci * bfq_select_queue(). 39162306a36Sopenharmony_ci */ 39262306a36Sopenharmony_ci struct bfq_queue *waker_bfqq; 39362306a36Sopenharmony_ci /* pointer to the curr. tentative waker queue, see bfq_check_waker() */ 39462306a36Sopenharmony_ci struct bfq_queue *tentative_waker_bfqq; 39562306a36Sopenharmony_ci /* number of times the same tentative waker has been detected */ 39662306a36Sopenharmony_ci unsigned int num_waker_detections; 39762306a36Sopenharmony_ci /* time when we started considering this waker */ 39862306a36Sopenharmony_ci u64 waker_detection_started; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci /* node for woken_list, see below */ 40162306a36Sopenharmony_ci struct hlist_node woken_list_node; 40262306a36Sopenharmony_ci /* 40362306a36Sopenharmony_ci * Head of the list of the woken queues for this queue, i.e., 40462306a36Sopenharmony_ci * of the list of the queues for which this queue is a waker 40562306a36Sopenharmony_ci * queue. This list is used to reset the waker_bfqq pointer in 40662306a36Sopenharmony_ci * the woken queues when this queue exits. 40762306a36Sopenharmony_ci */ 40862306a36Sopenharmony_ci struct hlist_head woken_list; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /* index of the actuator this queue is associated with */ 41162306a36Sopenharmony_ci unsigned int actuator_idx; 41262306a36Sopenharmony_ci}; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci/** 41562306a36Sopenharmony_ci* struct bfq_data - bfqq data unique and persistent for associated bfq_io_cq 41662306a36Sopenharmony_ci*/ 41762306a36Sopenharmony_cistruct bfq_iocq_bfqq_data { 41862306a36Sopenharmony_ci /* 41962306a36Sopenharmony_ci * Snapshot of the has_short_time flag before merging; taken 42062306a36Sopenharmony_ci * to remember its values while the queue is merged, so as to 42162306a36Sopenharmony_ci * be able to restore it in case of split. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_ci bool saved_has_short_ttime; 42462306a36Sopenharmony_ci /* 42562306a36Sopenharmony_ci * Same purpose as the previous two fields for the I/O bound 42662306a36Sopenharmony_ci * classification of a queue. 42762306a36Sopenharmony_ci */ 42862306a36Sopenharmony_ci bool saved_IO_bound; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci u64 saved_io_start_time; 43162306a36Sopenharmony_ci u64 saved_tot_idle_time; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci /* 43462306a36Sopenharmony_ci * Same purpose as the previous fields for the values of the 43562306a36Sopenharmony_ci * field keeping the queue's belonging to a large burst 43662306a36Sopenharmony_ci */ 43762306a36Sopenharmony_ci bool saved_in_large_burst; 43862306a36Sopenharmony_ci /* 43962306a36Sopenharmony_ci * True if the queue belonged to a burst list before its merge 44062306a36Sopenharmony_ci * with another cooperating queue. 44162306a36Sopenharmony_ci */ 44262306a36Sopenharmony_ci bool was_in_burst_list; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci /* 44562306a36Sopenharmony_ci * Save the weight when a merge occurs, to be able 44662306a36Sopenharmony_ci * to restore it in case of split. If the weight is not 44762306a36Sopenharmony_ci * correctly resumed when the queue is recycled, 44862306a36Sopenharmony_ci * then the weight of the recycled queue could differ 44962306a36Sopenharmony_ci * from the weight of the original queue. 45062306a36Sopenharmony_ci */ 45162306a36Sopenharmony_ci unsigned int saved_weight; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci /* 45462306a36Sopenharmony_ci * Similar to previous fields: save wr information. 45562306a36Sopenharmony_ci */ 45662306a36Sopenharmony_ci unsigned long saved_wr_coeff; 45762306a36Sopenharmony_ci unsigned long saved_last_wr_start_finish; 45862306a36Sopenharmony_ci unsigned long saved_service_from_wr; 45962306a36Sopenharmony_ci unsigned long saved_wr_start_at_switch_to_srt; 46062306a36Sopenharmony_ci unsigned int saved_wr_cur_max_time; 46162306a36Sopenharmony_ci struct bfq_ttime saved_ttime; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* Save also injection state */ 46462306a36Sopenharmony_ci u64 saved_last_serv_time_ns; 46562306a36Sopenharmony_ci unsigned int saved_inject_limit; 46662306a36Sopenharmony_ci unsigned long saved_decrease_time_jif; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci /* candidate queue for a stable merge (due to close creation time) */ 46962306a36Sopenharmony_ci struct bfq_queue *stable_merge_bfqq; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci bool stably_merged; /* non splittable if true */ 47262306a36Sopenharmony_ci}; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci/** 47562306a36Sopenharmony_ci * struct bfq_io_cq - per (request_queue, io_context) structure. 47662306a36Sopenharmony_ci */ 47762306a36Sopenharmony_cistruct bfq_io_cq { 47862306a36Sopenharmony_ci /* associated io_cq structure */ 47962306a36Sopenharmony_ci struct io_cq icq; /* must be the first member */ 48062306a36Sopenharmony_ci /* 48162306a36Sopenharmony_ci * Matrix of associated process queues: first row for async 48262306a36Sopenharmony_ci * queues, second row sync queues. Each row contains one 48362306a36Sopenharmony_ci * column for each actuator. An I/O request generated by the 48462306a36Sopenharmony_ci * process is inserted into the queue pointed by bfqq[i][j] if 48562306a36Sopenharmony_ci * the request is to be served by the j-th actuator of the 48662306a36Sopenharmony_ci * drive, where i==0 or i==1, depending on whether the request 48762306a36Sopenharmony_ci * is async or sync. So there is a distinct queue for each 48862306a36Sopenharmony_ci * actuator. 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ci struct bfq_queue *bfqq[2][BFQ_MAX_ACTUATORS]; 49162306a36Sopenharmony_ci /* per (request_queue, blkcg) ioprio */ 49262306a36Sopenharmony_ci int ioprio; 49362306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 49462306a36Sopenharmony_ci uint64_t blkcg_serial_nr; /* the current blkcg serial */ 49562306a36Sopenharmony_ci#endif 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* 49862306a36Sopenharmony_ci * Persistent data for associated synchronous process queues 49962306a36Sopenharmony_ci * (one queue per actuator, see field bfqq above). In 50062306a36Sopenharmony_ci * particular, each of these queues may undergo a merge. 50162306a36Sopenharmony_ci */ 50262306a36Sopenharmony_ci struct bfq_iocq_bfqq_data bfqq_data[BFQ_MAX_ACTUATORS]; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci unsigned int requests; /* Number of requests this process has in flight */ 50562306a36Sopenharmony_ci}; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci/** 50862306a36Sopenharmony_ci * struct bfq_data - per-device data structure. 50962306a36Sopenharmony_ci * 51062306a36Sopenharmony_ci * All the fields are protected by @lock. 51162306a36Sopenharmony_ci */ 51262306a36Sopenharmony_cistruct bfq_data { 51362306a36Sopenharmony_ci /* device request queue */ 51462306a36Sopenharmony_ci struct request_queue *queue; 51562306a36Sopenharmony_ci /* dispatch queue */ 51662306a36Sopenharmony_ci struct list_head dispatch; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* root bfq_group for the device */ 51962306a36Sopenharmony_ci struct bfq_group *root_group; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci /* 52262306a36Sopenharmony_ci * rbtree of weight counters of @bfq_queues, sorted by 52362306a36Sopenharmony_ci * weight. Used to keep track of whether all @bfq_queues have 52462306a36Sopenharmony_ci * the same weight. The tree contains one counter for each 52562306a36Sopenharmony_ci * distinct weight associated to some active and not 52662306a36Sopenharmony_ci * weight-raised @bfq_queue (see the comments to the functions 52762306a36Sopenharmony_ci * bfq_weights_tree_[add|remove] for further details). 52862306a36Sopenharmony_ci */ 52962306a36Sopenharmony_ci struct rb_root_cached queue_weights_tree; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 53262306a36Sopenharmony_ci /* 53362306a36Sopenharmony_ci * Number of groups with at least one process that 53462306a36Sopenharmony_ci * has at least one request waiting for completion. Note that 53562306a36Sopenharmony_ci * this accounts for also requests already dispatched, but not 53662306a36Sopenharmony_ci * yet completed. Therefore this number of groups may differ 53762306a36Sopenharmony_ci * (be larger) than the number of active groups, as a group is 53862306a36Sopenharmony_ci * considered active only if its corresponding entity has 53962306a36Sopenharmony_ci * queues with at least one request queued. This 54062306a36Sopenharmony_ci * number is used to decide whether a scenario is symmetric. 54162306a36Sopenharmony_ci * For a detailed explanation see comments on the computation 54262306a36Sopenharmony_ci * of the variable asymmetric_scenario in the function 54362306a36Sopenharmony_ci * bfq_better_to_idle(). 54462306a36Sopenharmony_ci * 54562306a36Sopenharmony_ci * However, it is hard to compute this number exactly, for 54662306a36Sopenharmony_ci * groups with multiple processes. Consider a group 54762306a36Sopenharmony_ci * that is inactive, i.e., that has no process with 54862306a36Sopenharmony_ci * pending I/O inside BFQ queues. Then suppose that 54962306a36Sopenharmony_ci * num_groups_with_pending_reqs is still accounting for this 55062306a36Sopenharmony_ci * group, because the group has processes with some 55162306a36Sopenharmony_ci * I/O request still in flight. num_groups_with_pending_reqs 55262306a36Sopenharmony_ci * should be decremented when the in-flight request of the 55362306a36Sopenharmony_ci * last process is finally completed (assuming that 55462306a36Sopenharmony_ci * nothing else has changed for the group in the meantime, in 55562306a36Sopenharmony_ci * terms of composition of the group and active/inactive state of child 55662306a36Sopenharmony_ci * groups and processes). To accomplish this, an additional 55762306a36Sopenharmony_ci * pending-request counter must be added to entities, and must 55862306a36Sopenharmony_ci * be updated correctly. To avoid this additional field and operations, 55962306a36Sopenharmony_ci * we resort to the following tradeoff between simplicity and 56062306a36Sopenharmony_ci * accuracy: for an inactive group that is still counted in 56162306a36Sopenharmony_ci * num_groups_with_pending_reqs, we decrement 56262306a36Sopenharmony_ci * num_groups_with_pending_reqs when the first 56362306a36Sopenharmony_ci * process of the group remains with no request waiting for 56462306a36Sopenharmony_ci * completion. 56562306a36Sopenharmony_ci * 56662306a36Sopenharmony_ci * Even this simpler decrement strategy requires a little 56762306a36Sopenharmony_ci * carefulness: to avoid multiple decrements, we flag a group, 56862306a36Sopenharmony_ci * more precisely an entity representing a group, as still 56962306a36Sopenharmony_ci * counted in num_groups_with_pending_reqs when it becomes 57062306a36Sopenharmony_ci * inactive. Then, when the first queue of the 57162306a36Sopenharmony_ci * entity remains with no request waiting for completion, 57262306a36Sopenharmony_ci * num_groups_with_pending_reqs is decremented, and this flag 57362306a36Sopenharmony_ci * is reset. After this flag is reset for the entity, 57462306a36Sopenharmony_ci * num_groups_with_pending_reqs won't be decremented any 57562306a36Sopenharmony_ci * longer in case a new queue of the entity remains 57662306a36Sopenharmony_ci * with no request waiting for completion. 57762306a36Sopenharmony_ci */ 57862306a36Sopenharmony_ci unsigned int num_groups_with_pending_reqs; 57962306a36Sopenharmony_ci#endif 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci /* 58262306a36Sopenharmony_ci * Per-class (RT, BE, IDLE) number of bfq_queues containing 58362306a36Sopenharmony_ci * requests (including the queue in service, even if it is 58462306a36Sopenharmony_ci * idling). 58562306a36Sopenharmony_ci */ 58662306a36Sopenharmony_ci unsigned int busy_queues[3]; 58762306a36Sopenharmony_ci /* number of weight-raised busy @bfq_queues */ 58862306a36Sopenharmony_ci int wr_busy_queues; 58962306a36Sopenharmony_ci /* number of queued requests */ 59062306a36Sopenharmony_ci int queued; 59162306a36Sopenharmony_ci /* number of requests dispatched and waiting for completion */ 59262306a36Sopenharmony_ci int tot_rq_in_driver; 59362306a36Sopenharmony_ci /* 59462306a36Sopenharmony_ci * number of requests dispatched and waiting for completion 59562306a36Sopenharmony_ci * for each actuator 59662306a36Sopenharmony_ci */ 59762306a36Sopenharmony_ci int rq_in_driver[BFQ_MAX_ACTUATORS]; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* true if the device is non rotational and performs queueing */ 60062306a36Sopenharmony_ci bool nonrot_with_queueing; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci /* 60362306a36Sopenharmony_ci * Maximum number of requests in driver in the last 60462306a36Sopenharmony_ci * @hw_tag_samples completed requests. 60562306a36Sopenharmony_ci */ 60662306a36Sopenharmony_ci int max_rq_in_driver; 60762306a36Sopenharmony_ci /* number of samples used to calculate hw_tag */ 60862306a36Sopenharmony_ci int hw_tag_samples; 60962306a36Sopenharmony_ci /* flag set to one if the driver is showing a queueing behavior */ 61062306a36Sopenharmony_ci int hw_tag; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci /* number of budgets assigned */ 61362306a36Sopenharmony_ci int budgets_assigned; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci /* 61662306a36Sopenharmony_ci * Timer set when idling (waiting) for the next request from 61762306a36Sopenharmony_ci * the queue in service. 61862306a36Sopenharmony_ci */ 61962306a36Sopenharmony_ci struct hrtimer idle_slice_timer; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci /* bfq_queue in service */ 62262306a36Sopenharmony_ci struct bfq_queue *in_service_queue; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci /* on-disk position of the last served request */ 62562306a36Sopenharmony_ci sector_t last_position; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* position of the last served request for the in-service queue */ 62862306a36Sopenharmony_ci sector_t in_serv_last_pos; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci /* time of last request completion (ns) */ 63162306a36Sopenharmony_ci u64 last_completion; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci /* bfqq owning the last completed rq */ 63462306a36Sopenharmony_ci struct bfq_queue *last_completed_rq_bfqq; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* last bfqq created, among those in the root group */ 63762306a36Sopenharmony_ci struct bfq_queue *last_bfqq_created; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci /* time of last transition from empty to non-empty (ns) */ 64062306a36Sopenharmony_ci u64 last_empty_occupied_ns; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci /* 64362306a36Sopenharmony_ci * Flag set to activate the sampling of the total service time 64462306a36Sopenharmony_ci * of a just-arrived first I/O request (see 64562306a36Sopenharmony_ci * bfq_update_inject_limit()). This will cause the setting of 64662306a36Sopenharmony_ci * waited_rq when the request is finally dispatched. 64762306a36Sopenharmony_ci */ 64862306a36Sopenharmony_ci bool wait_dispatch; 64962306a36Sopenharmony_ci /* 65062306a36Sopenharmony_ci * If set, then bfq_update_inject_limit() is invoked when 65162306a36Sopenharmony_ci * waited_rq is eventually completed. 65262306a36Sopenharmony_ci */ 65362306a36Sopenharmony_ci struct request *waited_rq; 65462306a36Sopenharmony_ci /* 65562306a36Sopenharmony_ci * True if some request has been injected during the last service hole. 65662306a36Sopenharmony_ci */ 65762306a36Sopenharmony_ci bool rqs_injected; 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci /* time of first rq dispatch in current observation interval (ns) */ 66062306a36Sopenharmony_ci u64 first_dispatch; 66162306a36Sopenharmony_ci /* time of last rq dispatch in current observation interval (ns) */ 66262306a36Sopenharmony_ci u64 last_dispatch; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /* beginning of the last budget */ 66562306a36Sopenharmony_ci ktime_t last_budget_start; 66662306a36Sopenharmony_ci /* beginning of the last idle slice */ 66762306a36Sopenharmony_ci ktime_t last_idling_start; 66862306a36Sopenharmony_ci unsigned long last_idling_start_jiffies; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /* number of samples in current observation interval */ 67162306a36Sopenharmony_ci int peak_rate_samples; 67262306a36Sopenharmony_ci /* num of samples of seq dispatches in current observation interval */ 67362306a36Sopenharmony_ci u32 sequential_samples; 67462306a36Sopenharmony_ci /* total num of sectors transferred in current observation interval */ 67562306a36Sopenharmony_ci u64 tot_sectors_dispatched; 67662306a36Sopenharmony_ci /* max rq size seen during current observation interval (sectors) */ 67762306a36Sopenharmony_ci u32 last_rq_max_size; 67862306a36Sopenharmony_ci /* time elapsed from first dispatch in current observ. interval (us) */ 67962306a36Sopenharmony_ci u64 delta_from_first; 68062306a36Sopenharmony_ci /* 68162306a36Sopenharmony_ci * Current estimate of the device peak rate, measured in 68262306a36Sopenharmony_ci * [(sectors/usec) / 2^BFQ_RATE_SHIFT]. The left-shift by 68362306a36Sopenharmony_ci * BFQ_RATE_SHIFT is performed to increase precision in 68462306a36Sopenharmony_ci * fixed-point calculations. 68562306a36Sopenharmony_ci */ 68662306a36Sopenharmony_ci u32 peak_rate; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* maximum budget allotted to a bfq_queue before rescheduling */ 68962306a36Sopenharmony_ci int bfq_max_budget; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci /* 69262306a36Sopenharmony_ci * List of all the bfq_queues active for a specific actuator 69362306a36Sopenharmony_ci * on the device. Keeping active queues separate on a 69462306a36Sopenharmony_ci * per-actuator basis helps implementing per-actuator 69562306a36Sopenharmony_ci * injection more efficiently. 69662306a36Sopenharmony_ci */ 69762306a36Sopenharmony_ci struct list_head active_list[BFQ_MAX_ACTUATORS]; 69862306a36Sopenharmony_ci /* list of all the bfq_queues idle on the device */ 69962306a36Sopenharmony_ci struct list_head idle_list; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /* 70262306a36Sopenharmony_ci * Timeout for async/sync requests; when it fires, requests 70362306a36Sopenharmony_ci * are served in fifo order. 70462306a36Sopenharmony_ci */ 70562306a36Sopenharmony_ci u64 bfq_fifo_expire[2]; 70662306a36Sopenharmony_ci /* weight of backward seeks wrt forward ones */ 70762306a36Sopenharmony_ci unsigned int bfq_back_penalty; 70862306a36Sopenharmony_ci /* maximum allowed backward seek */ 70962306a36Sopenharmony_ci unsigned int bfq_back_max; 71062306a36Sopenharmony_ci /* maximum idling time */ 71162306a36Sopenharmony_ci u32 bfq_slice_idle; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci /* user-configured max budget value (0 for auto-tuning) */ 71462306a36Sopenharmony_ci int bfq_user_max_budget; 71562306a36Sopenharmony_ci /* 71662306a36Sopenharmony_ci * Timeout for bfq_queues to consume their budget; used to 71762306a36Sopenharmony_ci * prevent seeky queues from imposing long latencies to 71862306a36Sopenharmony_ci * sequential or quasi-sequential ones (this also implies that 71962306a36Sopenharmony_ci * seeky queues cannot receive guarantees in the service 72062306a36Sopenharmony_ci * domain; after a timeout they are charged for the time they 72162306a36Sopenharmony_ci * have been in service, to preserve fairness among them, but 72262306a36Sopenharmony_ci * without service-domain guarantees). 72362306a36Sopenharmony_ci */ 72462306a36Sopenharmony_ci unsigned int bfq_timeout; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci /* 72762306a36Sopenharmony_ci * Force device idling whenever needed to provide accurate 72862306a36Sopenharmony_ci * service guarantees, without caring about throughput 72962306a36Sopenharmony_ci * issues. CAVEAT: this may even increase latencies, in case 73062306a36Sopenharmony_ci * of useless idling for processes that did stop doing I/O. 73162306a36Sopenharmony_ci */ 73262306a36Sopenharmony_ci bool strict_guarantees; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci /* 73562306a36Sopenharmony_ci * Last time at which a queue entered the current burst of 73662306a36Sopenharmony_ci * queues being activated shortly after each other; for more 73762306a36Sopenharmony_ci * details about this and the following parameters related to 73862306a36Sopenharmony_ci * a burst of activations, see the comments on the function 73962306a36Sopenharmony_ci * bfq_handle_burst. 74062306a36Sopenharmony_ci */ 74162306a36Sopenharmony_ci unsigned long last_ins_in_burst; 74262306a36Sopenharmony_ci /* 74362306a36Sopenharmony_ci * Reference time interval used to decide whether a queue has 74462306a36Sopenharmony_ci * been activated shortly after @last_ins_in_burst. 74562306a36Sopenharmony_ci */ 74662306a36Sopenharmony_ci unsigned long bfq_burst_interval; 74762306a36Sopenharmony_ci /* number of queues in the current burst of queue activations */ 74862306a36Sopenharmony_ci int burst_size; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci /* common parent entity for the queues in the burst */ 75162306a36Sopenharmony_ci struct bfq_entity *burst_parent_entity; 75262306a36Sopenharmony_ci /* Maximum burst size above which the current queue-activation 75362306a36Sopenharmony_ci * burst is deemed as 'large'. 75462306a36Sopenharmony_ci */ 75562306a36Sopenharmony_ci unsigned long bfq_large_burst_thresh; 75662306a36Sopenharmony_ci /* true if a large queue-activation burst is in progress */ 75762306a36Sopenharmony_ci bool large_burst; 75862306a36Sopenharmony_ci /* 75962306a36Sopenharmony_ci * Head of the burst list (as for the above fields, more 76062306a36Sopenharmony_ci * details in the comments on the function bfq_handle_burst). 76162306a36Sopenharmony_ci */ 76262306a36Sopenharmony_ci struct hlist_head burst_list; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci /* if set to true, low-latency heuristics are enabled */ 76562306a36Sopenharmony_ci bool low_latency; 76662306a36Sopenharmony_ci /* 76762306a36Sopenharmony_ci * Maximum factor by which the weight of a weight-raised queue 76862306a36Sopenharmony_ci * is multiplied. 76962306a36Sopenharmony_ci */ 77062306a36Sopenharmony_ci unsigned int bfq_wr_coeff; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci /* Maximum weight-raising duration for soft real-time processes */ 77362306a36Sopenharmony_ci unsigned int bfq_wr_rt_max_time; 77462306a36Sopenharmony_ci /* 77562306a36Sopenharmony_ci * Minimum idle period after which weight-raising may be 77662306a36Sopenharmony_ci * reactivated for a queue (in jiffies). 77762306a36Sopenharmony_ci */ 77862306a36Sopenharmony_ci unsigned int bfq_wr_min_idle_time; 77962306a36Sopenharmony_ci /* 78062306a36Sopenharmony_ci * Minimum period between request arrivals after which 78162306a36Sopenharmony_ci * weight-raising may be reactivated for an already busy async 78262306a36Sopenharmony_ci * queue (in jiffies). 78362306a36Sopenharmony_ci */ 78462306a36Sopenharmony_ci unsigned long bfq_wr_min_inter_arr_async; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci /* Max service-rate for a soft real-time queue, in sectors/sec */ 78762306a36Sopenharmony_ci unsigned int bfq_wr_max_softrt_rate; 78862306a36Sopenharmony_ci /* 78962306a36Sopenharmony_ci * Cached value of the product ref_rate*ref_wr_duration, used 79062306a36Sopenharmony_ci * for computing the maximum duration of weight raising 79162306a36Sopenharmony_ci * automatically. 79262306a36Sopenharmony_ci */ 79362306a36Sopenharmony_ci u64 rate_dur_prod; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci /* fallback dummy bfqq for extreme OOM conditions */ 79662306a36Sopenharmony_ci struct bfq_queue oom_bfqq; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci spinlock_t lock; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci /* 80162306a36Sopenharmony_ci * bic associated with the task issuing current bio for 80262306a36Sopenharmony_ci * merging. This and the next field are used as a support to 80362306a36Sopenharmony_ci * be able to perform the bic lookup, needed by bio-merge 80462306a36Sopenharmony_ci * functions, before the scheduler lock is taken, and thus 80562306a36Sopenharmony_ci * avoid taking the request-queue lock while the scheduler 80662306a36Sopenharmony_ci * lock is being held. 80762306a36Sopenharmony_ci */ 80862306a36Sopenharmony_ci struct bfq_io_cq *bio_bic; 80962306a36Sopenharmony_ci /* bfqq associated with the task issuing current bio for merging */ 81062306a36Sopenharmony_ci struct bfq_queue *bio_bfqq; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* 81362306a36Sopenharmony_ci * Depth limits used in bfq_limit_depth (see comments on the 81462306a36Sopenharmony_ci * function) 81562306a36Sopenharmony_ci */ 81662306a36Sopenharmony_ci unsigned int word_depths[2][2]; 81762306a36Sopenharmony_ci unsigned int full_depth_shift; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci /* 82062306a36Sopenharmony_ci * Number of independent actuators. This is equal to 1 in 82162306a36Sopenharmony_ci * case of single-actuator drives. 82262306a36Sopenharmony_ci */ 82362306a36Sopenharmony_ci unsigned int num_actuators; 82462306a36Sopenharmony_ci /* 82562306a36Sopenharmony_ci * Disk independent access ranges for each actuator 82662306a36Sopenharmony_ci * in this device. 82762306a36Sopenharmony_ci */ 82862306a36Sopenharmony_ci sector_t sector[BFQ_MAX_ACTUATORS]; 82962306a36Sopenharmony_ci sector_t nr_sectors[BFQ_MAX_ACTUATORS]; 83062306a36Sopenharmony_ci struct blk_independent_access_range ia_ranges[BFQ_MAX_ACTUATORS]; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci /* 83362306a36Sopenharmony_ci * If the number of I/O requests queued in the device for a 83462306a36Sopenharmony_ci * given actuator is below next threshold, then the actuator 83562306a36Sopenharmony_ci * is deemed as underutilized. If this condition is found to 83662306a36Sopenharmony_ci * hold for some actuator upon a dispatch, but (i) the 83762306a36Sopenharmony_ci * in-service queue does not contain I/O for that actuator, 83862306a36Sopenharmony_ci * while (ii) some other queue does contain I/O for that 83962306a36Sopenharmony_ci * actuator, then the head I/O request of the latter queue is 84062306a36Sopenharmony_ci * returned (injected), instead of the head request of the 84162306a36Sopenharmony_ci * currently in-service queue. 84262306a36Sopenharmony_ci * 84362306a36Sopenharmony_ci * We set the threshold, empirically, to the minimum possible 84462306a36Sopenharmony_ci * value for which an actuator is fully utilized, or close to 84562306a36Sopenharmony_ci * be fully utilized. By doing so, injected I/O 'steals' as 84662306a36Sopenharmony_ci * few drive-queue slots as possibile to the in-service 84762306a36Sopenharmony_ci * queue. This reduces as much as possible the probability 84862306a36Sopenharmony_ci * that the service of I/O from the in-service bfq_queue gets 84962306a36Sopenharmony_ci * delayed because of slot exhaustion, i.e., because all the 85062306a36Sopenharmony_ci * slots of the drive queue are filled with I/O injected from 85162306a36Sopenharmony_ci * other queues (NCQ provides for 32 slots). 85262306a36Sopenharmony_ci */ 85362306a36Sopenharmony_ci unsigned int actuator_load_threshold; 85462306a36Sopenharmony_ci}; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_cienum bfqq_state_flags { 85762306a36Sopenharmony_ci BFQQF_just_created = 0, /* queue just allocated */ 85862306a36Sopenharmony_ci BFQQF_busy, /* has requests or is in service */ 85962306a36Sopenharmony_ci BFQQF_wait_request, /* waiting for a request */ 86062306a36Sopenharmony_ci BFQQF_non_blocking_wait_rq, /* 86162306a36Sopenharmony_ci * waiting for a request 86262306a36Sopenharmony_ci * without idling the device 86362306a36Sopenharmony_ci */ 86462306a36Sopenharmony_ci BFQQF_fifo_expire, /* FIFO checked in this slice */ 86562306a36Sopenharmony_ci BFQQF_has_short_ttime, /* queue has a short think time */ 86662306a36Sopenharmony_ci BFQQF_sync, /* synchronous queue */ 86762306a36Sopenharmony_ci BFQQF_IO_bound, /* 86862306a36Sopenharmony_ci * bfqq has timed-out at least once 86962306a36Sopenharmony_ci * having consumed at most 2/10 of 87062306a36Sopenharmony_ci * its budget 87162306a36Sopenharmony_ci */ 87262306a36Sopenharmony_ci BFQQF_in_large_burst, /* 87362306a36Sopenharmony_ci * bfqq activated in a large burst, 87462306a36Sopenharmony_ci * see comments to bfq_handle_burst. 87562306a36Sopenharmony_ci */ 87662306a36Sopenharmony_ci BFQQF_softrt_update, /* 87762306a36Sopenharmony_ci * may need softrt-next-start 87862306a36Sopenharmony_ci * update 87962306a36Sopenharmony_ci */ 88062306a36Sopenharmony_ci BFQQF_coop, /* bfqq is shared */ 88162306a36Sopenharmony_ci BFQQF_split_coop, /* shared bfqq will be split */ 88262306a36Sopenharmony_ci}; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci#define BFQ_BFQQ_FNS(name) \ 88562306a36Sopenharmony_civoid bfq_mark_bfqq_##name(struct bfq_queue *bfqq); \ 88662306a36Sopenharmony_civoid bfq_clear_bfqq_##name(struct bfq_queue *bfqq); \ 88762306a36Sopenharmony_ciint bfq_bfqq_##name(const struct bfq_queue *bfqq); 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ciBFQ_BFQQ_FNS(just_created); 89062306a36Sopenharmony_ciBFQ_BFQQ_FNS(busy); 89162306a36Sopenharmony_ciBFQ_BFQQ_FNS(wait_request); 89262306a36Sopenharmony_ciBFQ_BFQQ_FNS(non_blocking_wait_rq); 89362306a36Sopenharmony_ciBFQ_BFQQ_FNS(fifo_expire); 89462306a36Sopenharmony_ciBFQ_BFQQ_FNS(has_short_ttime); 89562306a36Sopenharmony_ciBFQ_BFQQ_FNS(sync); 89662306a36Sopenharmony_ciBFQ_BFQQ_FNS(IO_bound); 89762306a36Sopenharmony_ciBFQ_BFQQ_FNS(in_large_burst); 89862306a36Sopenharmony_ciBFQ_BFQQ_FNS(coop); 89962306a36Sopenharmony_ciBFQ_BFQQ_FNS(split_coop); 90062306a36Sopenharmony_ciBFQ_BFQQ_FNS(softrt_update); 90162306a36Sopenharmony_ci#undef BFQ_BFQQ_FNS 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci/* Expiration reasons. */ 90462306a36Sopenharmony_cienum bfqq_expiration { 90562306a36Sopenharmony_ci BFQQE_TOO_IDLE = 0, /* 90662306a36Sopenharmony_ci * queue has been idling for 90762306a36Sopenharmony_ci * too long 90862306a36Sopenharmony_ci */ 90962306a36Sopenharmony_ci BFQQE_BUDGET_TIMEOUT, /* budget took too long to be used */ 91062306a36Sopenharmony_ci BFQQE_BUDGET_EXHAUSTED, /* budget consumed */ 91162306a36Sopenharmony_ci BFQQE_NO_MORE_REQUESTS, /* the queue has no more requests */ 91262306a36Sopenharmony_ci BFQQE_PREEMPTED /* preemption in progress */ 91362306a36Sopenharmony_ci}; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_cistruct bfq_stat { 91662306a36Sopenharmony_ci struct percpu_counter cpu_cnt; 91762306a36Sopenharmony_ci atomic64_t aux_cnt; 91862306a36Sopenharmony_ci}; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_cistruct bfqg_stats { 92162306a36Sopenharmony_ci /* basic stats */ 92262306a36Sopenharmony_ci struct blkg_rwstat bytes; 92362306a36Sopenharmony_ci struct blkg_rwstat ios; 92462306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG 92562306a36Sopenharmony_ci /* number of ios merged */ 92662306a36Sopenharmony_ci struct blkg_rwstat merged; 92762306a36Sopenharmony_ci /* total time spent on device in ns, may not be accurate w/ queueing */ 92862306a36Sopenharmony_ci struct blkg_rwstat service_time; 92962306a36Sopenharmony_ci /* total time spent waiting in scheduler queue in ns */ 93062306a36Sopenharmony_ci struct blkg_rwstat wait_time; 93162306a36Sopenharmony_ci /* number of IOs queued up */ 93262306a36Sopenharmony_ci struct blkg_rwstat queued; 93362306a36Sopenharmony_ci /* total disk time and nr sectors dispatched by this group */ 93462306a36Sopenharmony_ci struct bfq_stat time; 93562306a36Sopenharmony_ci /* sum of number of ios queued across all samples */ 93662306a36Sopenharmony_ci struct bfq_stat avg_queue_size_sum; 93762306a36Sopenharmony_ci /* count of samples taken for average */ 93862306a36Sopenharmony_ci struct bfq_stat avg_queue_size_samples; 93962306a36Sopenharmony_ci /* how many times this group has been removed from service tree */ 94062306a36Sopenharmony_ci struct bfq_stat dequeue; 94162306a36Sopenharmony_ci /* total time spent waiting for it to be assigned a timeslice. */ 94262306a36Sopenharmony_ci struct bfq_stat group_wait_time; 94362306a36Sopenharmony_ci /* time spent idling for this blkcg_gq */ 94462306a36Sopenharmony_ci struct bfq_stat idle_time; 94562306a36Sopenharmony_ci /* total time with empty current active q with other requests queued */ 94662306a36Sopenharmony_ci struct bfq_stat empty_time; 94762306a36Sopenharmony_ci /* fields after this shouldn't be cleared on stat reset */ 94862306a36Sopenharmony_ci u64 start_group_wait_time; 94962306a36Sopenharmony_ci u64 start_idle_time; 95062306a36Sopenharmony_ci u64 start_empty_time; 95162306a36Sopenharmony_ci uint16_t flags; 95262306a36Sopenharmony_ci#endif /* CONFIG_BFQ_CGROUP_DEBUG */ 95362306a36Sopenharmony_ci}; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci/* 95862306a36Sopenharmony_ci * struct bfq_group_data - per-blkcg storage for the blkio subsystem. 95962306a36Sopenharmony_ci * 96062306a36Sopenharmony_ci * @ps: @blkcg_policy_storage that this structure inherits 96162306a36Sopenharmony_ci * @weight: weight of the bfq_group 96262306a36Sopenharmony_ci */ 96362306a36Sopenharmony_cistruct bfq_group_data { 96462306a36Sopenharmony_ci /* must be the first member */ 96562306a36Sopenharmony_ci struct blkcg_policy_data pd; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci unsigned int weight; 96862306a36Sopenharmony_ci}; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci/** 97162306a36Sopenharmony_ci * struct bfq_group - per (device, cgroup) data structure. 97262306a36Sopenharmony_ci * @entity: schedulable entity to insert into the parent group sched_data. 97362306a36Sopenharmony_ci * @sched_data: own sched_data, to contain child entities (they may be 97462306a36Sopenharmony_ci * both bfq_queues and bfq_groups). 97562306a36Sopenharmony_ci * @bfqd: the bfq_data for the device this group acts upon. 97662306a36Sopenharmony_ci * @async_bfqq: array of async queues for all the tasks belonging to 97762306a36Sopenharmony_ci * the group, one queue per ioprio value per ioprio_class, 97862306a36Sopenharmony_ci * except for the idle class that has only one queue. 97962306a36Sopenharmony_ci * @async_idle_bfqq: async queue for the idle class (ioprio is ignored). 98062306a36Sopenharmony_ci * @my_entity: pointer to @entity, %NULL for the toplevel group; used 98162306a36Sopenharmony_ci * to avoid too many special cases during group creation/ 98262306a36Sopenharmony_ci * migration. 98362306a36Sopenharmony_ci * @stats: stats for this bfqg. 98462306a36Sopenharmony_ci * @active_entities: number of active entities belonging to the group; 98562306a36Sopenharmony_ci * unused for the root group. Used to know whether there 98662306a36Sopenharmony_ci * are groups with more than one active @bfq_entity 98762306a36Sopenharmony_ci * (see the comments to the function 98862306a36Sopenharmony_ci * bfq_bfqq_may_idle()). 98962306a36Sopenharmony_ci * @rq_pos_tree: rbtree sorted by next_request position, used when 99062306a36Sopenharmony_ci * determining if two or more queues have interleaving 99162306a36Sopenharmony_ci * requests (see bfq_find_close_cooperator()). 99262306a36Sopenharmony_ci * 99362306a36Sopenharmony_ci * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup 99462306a36Sopenharmony_ci * there is a set of bfq_groups, each one collecting the lower-level 99562306a36Sopenharmony_ci * entities belonging to the group that are acting on the same device. 99662306a36Sopenharmony_ci * 99762306a36Sopenharmony_ci * Locking works as follows: 99862306a36Sopenharmony_ci * o @bfqd is protected by the queue lock, RCU is used to access it 99962306a36Sopenharmony_ci * from the readers. 100062306a36Sopenharmony_ci * o All the other fields are protected by the @bfqd queue lock. 100162306a36Sopenharmony_ci */ 100262306a36Sopenharmony_cistruct bfq_group { 100362306a36Sopenharmony_ci /* must be the first member */ 100462306a36Sopenharmony_ci struct blkg_policy_data pd; 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci /* cached path for this blkg (see comments in bfq_bic_update_cgroup) */ 100762306a36Sopenharmony_ci char blkg_path[128]; 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci /* reference counter (see comments in bfq_bic_update_cgroup) */ 101062306a36Sopenharmony_ci refcount_t ref; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci struct bfq_entity entity; 101362306a36Sopenharmony_ci struct bfq_sched_data sched_data; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci struct bfq_data *bfqd; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci struct bfq_queue *async_bfqq[2][IOPRIO_NR_LEVELS][BFQ_MAX_ACTUATORS]; 101862306a36Sopenharmony_ci struct bfq_queue *async_idle_bfqq[BFQ_MAX_ACTUATORS]; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci struct bfq_entity *my_entity; 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci int active_entities; 102362306a36Sopenharmony_ci int num_queues_with_pending_reqs; 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci struct rb_root rq_pos_tree; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci struct bfqg_stats stats; 102862306a36Sopenharmony_ci}; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci#else 103162306a36Sopenharmony_cistruct bfq_group { 103262306a36Sopenharmony_ci struct bfq_entity entity; 103362306a36Sopenharmony_ci struct bfq_sched_data sched_data; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci struct bfq_queue *async_bfqq[2][IOPRIO_NR_LEVELS][BFQ_MAX_ACTUATORS]; 103662306a36Sopenharmony_ci struct bfq_queue *async_idle_bfqq[BFQ_MAX_ACTUATORS]; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci struct rb_root rq_pos_tree; 103962306a36Sopenharmony_ci}; 104062306a36Sopenharmony_ci#endif 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci/* --------------- main algorithm interface ----------------- */ 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \ 104562306a36Sopenharmony_ci { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 }) 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ciextern const int bfq_timeout; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_cistruct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync, 105062306a36Sopenharmony_ci unsigned int actuator_idx); 105162306a36Sopenharmony_civoid bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync, 105262306a36Sopenharmony_ci unsigned int actuator_idx); 105362306a36Sopenharmony_cistruct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic); 105462306a36Sopenharmony_civoid bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq); 105562306a36Sopenharmony_civoid bfq_weights_tree_add(struct bfq_queue *bfqq); 105662306a36Sopenharmony_civoid bfq_weights_tree_remove(struct bfq_queue *bfqq); 105762306a36Sopenharmony_civoid bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq, 105862306a36Sopenharmony_ci bool compensate, enum bfqq_expiration reason); 105962306a36Sopenharmony_civoid bfq_put_queue(struct bfq_queue *bfqq); 106062306a36Sopenharmony_civoid bfq_put_cooperator(struct bfq_queue *bfqq); 106162306a36Sopenharmony_civoid bfq_end_wr_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); 106262306a36Sopenharmony_civoid bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq); 106362306a36Sopenharmony_civoid bfq_schedule_dispatch(struct bfq_data *bfqd); 106462306a36Sopenharmony_civoid bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci/* ------------ end of main algorithm interface -------------- */ 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci/* ---------------- cgroups-support interface ---------------- */ 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_civoid bfqg_stats_update_legacy_io(struct request_queue *q, struct request *rq); 107162306a36Sopenharmony_civoid bfqg_stats_update_io_remove(struct bfq_group *bfqg, blk_opf_t opf); 107262306a36Sopenharmony_civoid bfqg_stats_update_io_merged(struct bfq_group *bfqg, blk_opf_t opf); 107362306a36Sopenharmony_civoid bfqg_stats_update_completion(struct bfq_group *bfqg, u64 start_time_ns, 107462306a36Sopenharmony_ci u64 io_start_time_ns, blk_opf_t opf); 107562306a36Sopenharmony_civoid bfqg_stats_update_dequeue(struct bfq_group *bfqg); 107662306a36Sopenharmony_civoid bfqg_stats_set_start_idle_time(struct bfq_group *bfqg); 107762306a36Sopenharmony_civoid bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, 107862306a36Sopenharmony_ci struct bfq_group *bfqg); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG 108162306a36Sopenharmony_civoid bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq, 108262306a36Sopenharmony_ci blk_opf_t opf); 108362306a36Sopenharmony_civoid bfqg_stats_set_start_empty_time(struct bfq_group *bfqg); 108462306a36Sopenharmony_civoid bfqg_stats_update_idle_time(struct bfq_group *bfqg); 108562306a36Sopenharmony_civoid bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg); 108662306a36Sopenharmony_ci#endif 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_civoid bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg); 108962306a36Sopenharmony_civoid bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio); 109062306a36Sopenharmony_civoid bfq_end_wr_async(struct bfq_data *bfqd); 109162306a36Sopenharmony_cistruct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio); 109262306a36Sopenharmony_cistruct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg); 109362306a36Sopenharmony_cistruct bfq_group *bfqq_group(struct bfq_queue *bfqq); 109462306a36Sopenharmony_cistruct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node); 109562306a36Sopenharmony_civoid bfqg_and_blkg_put(struct bfq_group *bfqg); 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 109862306a36Sopenharmony_ciextern struct cftype bfq_blkcg_legacy_files[]; 109962306a36Sopenharmony_ciextern struct cftype bfq_blkg_files[]; 110062306a36Sopenharmony_ciextern struct blkcg_policy blkcg_policy_bfq; 110162306a36Sopenharmony_ci#endif 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci/* ------------- end of cgroups-support interface ------------- */ 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci/* - interface of the internal hierarchical B-WF2Q+ scheduler - */ 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 110862306a36Sopenharmony_ci/* both next loops stop at one of the child entities of the root group */ 110962306a36Sopenharmony_ci#define for_each_entity(entity) \ 111062306a36Sopenharmony_ci for (; entity ; entity = entity->parent) 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci/* 111362306a36Sopenharmony_ci * For each iteration, compute parent in advance, so as to be safe if 111462306a36Sopenharmony_ci * entity is deallocated during the iteration. Such a deallocation may 111562306a36Sopenharmony_ci * happen as a consequence of a bfq_put_queue that frees the bfq_queue 111662306a36Sopenharmony_ci * containing entity. 111762306a36Sopenharmony_ci */ 111862306a36Sopenharmony_ci#define for_each_entity_safe(entity, parent) \ 111962306a36Sopenharmony_ci for (; entity && ({ parent = entity->parent; 1; }); entity = parent) 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci#else /* CONFIG_BFQ_GROUP_IOSCHED */ 112262306a36Sopenharmony_ci/* 112362306a36Sopenharmony_ci * Next two macros are fake loops when cgroups support is not 112462306a36Sopenharmony_ci * enabled. I fact, in such a case, there is only one level to go up 112562306a36Sopenharmony_ci * (to reach the root group). 112662306a36Sopenharmony_ci */ 112762306a36Sopenharmony_ci#define for_each_entity(entity) \ 112862306a36Sopenharmony_ci for (; entity ; entity = NULL) 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci#define for_each_entity_safe(entity, parent) \ 113162306a36Sopenharmony_ci for (parent = NULL; entity ; entity = parent) 113262306a36Sopenharmony_ci#endif /* CONFIG_BFQ_GROUP_IOSCHED */ 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_cistruct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity); 113562306a36Sopenharmony_ciunsigned int bfq_tot_busy_queues(struct bfq_data *bfqd); 113662306a36Sopenharmony_cistruct bfq_service_tree *bfq_entity_service_tree(struct bfq_entity *entity); 113762306a36Sopenharmony_cistruct bfq_entity *bfq_entity_of(struct rb_node *node); 113862306a36Sopenharmony_ciunsigned short bfq_ioprio_to_weight(int ioprio); 113962306a36Sopenharmony_civoid bfq_put_idle_entity(struct bfq_service_tree *st, 114062306a36Sopenharmony_ci struct bfq_entity *entity); 114162306a36Sopenharmony_cistruct bfq_service_tree * 114262306a36Sopenharmony_ci__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, 114362306a36Sopenharmony_ci struct bfq_entity *entity, 114462306a36Sopenharmony_ci bool update_class_too); 114562306a36Sopenharmony_civoid bfq_bfqq_served(struct bfq_queue *bfqq, int served); 114662306a36Sopenharmony_civoid bfq_bfqq_charge_time(struct bfq_data *bfqd, struct bfq_queue *bfqq, 114762306a36Sopenharmony_ci unsigned long time_ms); 114862306a36Sopenharmony_cibool __bfq_deactivate_entity(struct bfq_entity *entity, 114962306a36Sopenharmony_ci bool ins_into_idle_tree); 115062306a36Sopenharmony_cibool next_queue_may_preempt(struct bfq_data *bfqd); 115162306a36Sopenharmony_cistruct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd); 115262306a36Sopenharmony_cibool __bfq_bfqd_reset_in_service(struct bfq_data *bfqd); 115362306a36Sopenharmony_civoid bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, 115462306a36Sopenharmony_ci bool ins_into_idle_tree, bool expiration); 115562306a36Sopenharmony_civoid bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq); 115662306a36Sopenharmony_civoid bfq_requeue_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, 115762306a36Sopenharmony_ci bool expiration); 115862306a36Sopenharmony_civoid bfq_del_bfqq_busy(struct bfq_queue *bfqq, bool expiration); 115962306a36Sopenharmony_civoid bfq_add_bfqq_busy(struct bfq_queue *bfqq); 116062306a36Sopenharmony_civoid bfq_add_bfqq_in_groups_with_pending_reqs(struct bfq_queue *bfqq); 116162306a36Sopenharmony_civoid bfq_del_bfqq_in_groups_with_pending_reqs(struct bfq_queue *bfqq); 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci/* --------------- end of interface of B-WF2Q+ ---------------- */ 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci/* Logging facilities. */ 116662306a36Sopenharmony_cistatic inline void bfq_bfqq_name(struct bfq_queue *bfqq, char *str, int len) 116762306a36Sopenharmony_ci{ 116862306a36Sopenharmony_ci char type = bfq_bfqq_sync(bfqq) ? 'S' : 'A'; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci if (bfqq->pid != -1) 117162306a36Sopenharmony_ci snprintf(str, len, "bfq%d%c", bfqq->pid, type); 117262306a36Sopenharmony_ci else 117362306a36Sopenharmony_ci snprintf(str, len, "bfqSHARED-%c", type); 117462306a36Sopenharmony_ci} 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED 117762306a36Sopenharmony_cistruct bfq_group *bfqq_group(struct bfq_queue *bfqq); 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) do { \ 118062306a36Sopenharmony_ci char pid_str[MAX_BFQQ_NAME_LENGTH]; \ 118162306a36Sopenharmony_ci if (likely(!blk_trace_note_message_enabled((bfqd)->queue))) \ 118262306a36Sopenharmony_ci break; \ 118362306a36Sopenharmony_ci bfq_bfqq_name((bfqq), pid_str, MAX_BFQQ_NAME_LENGTH); \ 118462306a36Sopenharmony_ci blk_add_cgroup_trace_msg((bfqd)->queue, \ 118562306a36Sopenharmony_ci &bfqg_to_blkg(bfqq_group(bfqq))->blkcg->css, \ 118662306a36Sopenharmony_ci "%s " fmt, pid_str, ##args); \ 118762306a36Sopenharmony_ci} while (0) 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci#define bfq_log_bfqg(bfqd, bfqg, fmt, args...) do { \ 119062306a36Sopenharmony_ci blk_add_cgroup_trace_msg((bfqd)->queue, \ 119162306a36Sopenharmony_ci &bfqg_to_blkg(bfqg)->blkcg->css, fmt, ##args); \ 119262306a36Sopenharmony_ci} while (0) 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci#else /* CONFIG_BFQ_GROUP_IOSCHED */ 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) do { \ 119762306a36Sopenharmony_ci char pid_str[MAX_BFQQ_NAME_LENGTH]; \ 119862306a36Sopenharmony_ci if (likely(!blk_trace_note_message_enabled((bfqd)->queue))) \ 119962306a36Sopenharmony_ci break; \ 120062306a36Sopenharmony_ci bfq_bfqq_name((bfqq), pid_str, MAX_BFQQ_NAME_LENGTH); \ 120162306a36Sopenharmony_ci blk_add_trace_msg((bfqd)->queue, "%s " fmt, pid_str, ##args); \ 120262306a36Sopenharmony_ci} while (0) 120362306a36Sopenharmony_ci#define bfq_log_bfqg(bfqd, bfqg, fmt, args...) do {} while (0) 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci#endif /* CONFIG_BFQ_GROUP_IOSCHED */ 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci#define bfq_log(bfqd, fmt, args...) \ 120862306a36Sopenharmony_ci blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args) 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci#endif /* _BFQ_H */ 1211