Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0 */
2 : #ifndef RQ_QOS_H
3 : #define RQ_QOS_H
4 :
5 : #include <linux/kernel.h>
6 : #include <linux/blkdev.h>
7 : #include <linux/blk_types.h>
8 : #include <linux/atomic.h>
9 : #include <linux/wait.h>
10 :
11 : #include "blk-mq-debugfs.h"
12 :
13 : struct blk_mq_debugfs_attr;
14 :
15 : enum rq_qos_id {
16 : RQ_QOS_WBT,
17 : RQ_QOS_LATENCY,
18 : RQ_QOS_COST,
19 : };
20 :
21 : struct rq_wait {
22 : wait_queue_head_t wait;
23 : atomic_t inflight;
24 : };
25 :
26 : struct rq_qos {
27 : struct rq_qos_ops *ops;
28 : struct request_queue *q;
29 : enum rq_qos_id id;
30 : struct rq_qos *next;
31 : #ifdef CONFIG_BLK_DEBUG_FS
32 : struct dentry *debugfs_dir;
33 : #endif
34 : };
35 :
36 : struct rq_qos_ops {
37 : void (*throttle)(struct rq_qos *, struct bio *);
38 : void (*track)(struct rq_qos *, struct request *, struct bio *);
39 : void (*merge)(struct rq_qos *, struct request *, struct bio *);
40 : void (*issue)(struct rq_qos *, struct request *);
41 : void (*requeue)(struct rq_qos *, struct request *);
42 : void (*done)(struct rq_qos *, struct request *);
43 : void (*done_bio)(struct rq_qos *, struct bio *);
44 : void (*cleanup)(struct rq_qos *, struct bio *);
45 : void (*queue_depth_changed)(struct rq_qos *);
46 : void (*exit)(struct rq_qos *);
47 : const struct blk_mq_debugfs_attr *debugfs_attrs;
48 : };
49 :
50 : struct rq_depth {
51 : unsigned int max_depth;
52 :
53 : int scale_step;
54 : bool scaled_max;
55 :
56 : unsigned int queue_depth;
57 : unsigned int default_depth;
58 : };
59 :
60 0 : static inline struct rq_qos *rq_qos_id(struct request_queue *q,
61 : enum rq_qos_id id)
62 : {
63 0 : struct rq_qos *rqos;
64 0 : for (rqos = q->rq_qos; rqos; rqos = rqos->next) {
65 0 : if (rqos->id == id)
66 : break;
67 : }
68 0 : return rqos;
69 : }
70 :
71 0 : static inline struct rq_qos *wbt_rq_qos(struct request_queue *q)
72 : {
73 0 : return rq_qos_id(q, RQ_QOS_WBT);
74 : }
75 :
76 : static inline struct rq_qos *blkcg_rq_qos(struct request_queue *q)
77 : {
78 : return rq_qos_id(q, RQ_QOS_LATENCY);
79 : }
80 :
81 : static inline const char *rq_qos_id_to_name(enum rq_qos_id id)
82 : {
83 : switch (id) {
84 : case RQ_QOS_WBT:
85 : return "wbt";
86 : case RQ_QOS_LATENCY:
87 : return "latency";
88 : case RQ_QOS_COST:
89 : return "cost";
90 : }
91 : return "unknown";
92 : }
93 :
94 : static inline void rq_wait_init(struct rq_wait *rq_wait)
95 : {
96 : atomic_set(&rq_wait->inflight, 0);
97 : init_waitqueue_head(&rq_wait->wait);
98 : }
99 :
100 : static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
101 : {
102 : rqos->next = q->rq_qos;
103 : q->rq_qos = rqos;
104 :
105 : if (rqos->ops->debugfs_attrs)
106 : blk_mq_debugfs_register_rqos(rqos);
107 : }
108 :
109 : static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos)
110 : {
111 : struct rq_qos **cur;
112 :
113 : for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) {
114 : if (*cur == rqos) {
115 : *cur = rqos->next;
116 : break;
117 : }
118 : }
119 :
120 : blk_mq_debugfs_unregister_rqos(rqos);
121 : }
122 :
123 : typedef bool (acquire_inflight_cb_t)(struct rq_wait *rqw, void *private_data);
124 : typedef void (cleanup_cb_t)(struct rq_wait *rqw, void *private_data);
125 :
126 : void rq_qos_wait(struct rq_wait *rqw, void *private_data,
127 : acquire_inflight_cb_t *acquire_inflight_cb,
128 : cleanup_cb_t *cleanup_cb);
129 : bool rq_wait_inc_below(struct rq_wait *rq_wait, unsigned int limit);
130 : bool rq_depth_scale_up(struct rq_depth *rqd);
131 : bool rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle);
132 : bool rq_depth_calc_max_depth(struct rq_depth *rqd);
133 :
134 : void __rq_qos_cleanup(struct rq_qos *rqos, struct bio *bio);
135 : void __rq_qos_done(struct rq_qos *rqos, struct request *rq);
136 : void __rq_qos_issue(struct rq_qos *rqos, struct request *rq);
137 : void __rq_qos_requeue(struct rq_qos *rqos, struct request *rq);
138 : void __rq_qos_throttle(struct rq_qos *rqos, struct bio *bio);
139 : void __rq_qos_track(struct rq_qos *rqos, struct request *rq, struct bio *bio);
140 : void __rq_qos_merge(struct rq_qos *rqos, struct request *rq, struct bio *bio);
141 : void __rq_qos_done_bio(struct rq_qos *rqos, struct bio *bio);
142 : void __rq_qos_queue_depth_changed(struct rq_qos *rqos);
143 :
144 0 : static inline void rq_qos_cleanup(struct request_queue *q, struct bio *bio)
145 : {
146 0 : if (q->rq_qos)
147 0 : __rq_qos_cleanup(q->rq_qos, bio);
148 : }
149 :
150 3507 : static inline void rq_qos_done(struct request_queue *q, struct request *rq)
151 : {
152 3507 : if (q->rq_qos)
153 0 : __rq_qos_done(q->rq_qos, rq);
154 : }
155 :
156 0 : static inline void rq_qos_issue(struct request_queue *q, struct request *rq)
157 : {
158 0 : if (q->rq_qos)
159 0 : __rq_qos_issue(q->rq_qos, rq);
160 : }
161 :
162 0 : static inline void rq_qos_requeue(struct request_queue *q, struct request *rq)
163 : {
164 0 : if (q->rq_qos)
165 0 : __rq_qos_requeue(q->rq_qos, rq);
166 : }
167 :
168 8736 : static inline void rq_qos_done_bio(struct request_queue *q, struct bio *bio)
169 : {
170 8736 : if (q->rq_qos)
171 0 : __rq_qos_done_bio(q->rq_qos, bio);
172 : }
173 :
174 3252 : static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio)
175 : {
176 : /*
177 : * BIO_TRACKED lets controllers know that a bio went through the
178 : * normal rq_qos path.
179 : */
180 3252 : bio_set_flag(bio, BIO_TRACKED);
181 3252 : if (q->rq_qos)
182 0 : __rq_qos_throttle(q->rq_qos, bio);
183 3252 : }
184 :
185 3252 : static inline void rq_qos_track(struct request_queue *q, struct request *rq,
186 : struct bio *bio)
187 : {
188 3252 : if (q->rq_qos)
189 0 : __rq_qos_track(q->rq_qos, rq, bio);
190 : }
191 :
192 5485 : static inline void rq_qos_merge(struct request_queue *q, struct request *rq,
193 : struct bio *bio)
194 : {
195 5485 : if (q->rq_qos)
196 0 : __rq_qos_merge(q->rq_qos, rq, bio);
197 : }
198 :
199 0 : static inline void rq_qos_queue_depth_changed(struct request_queue *q)
200 : {
201 0 : if (q->rq_qos)
202 0 : __rq_qos_queue_depth_changed(q->rq_qos);
203 : }
204 :
205 : void rq_qos_exit(struct request_queue *);
206 :
207 : #endif
|