hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/block/blk-rq-qos.h
....@@ -1,3 +1,4 @@
1
+/* SPDX-License-Identifier: GPL-2.0 */
12 #ifndef RQ_QOS_H
23 #define RQ_QOS_H
34
....@@ -6,10 +7,17 @@
67 #include <linux/blk_types.h>
78 #include <linux/atomic.h>
89 #include <linux/wait.h>
10
+#include <linux/blk-mq.h>
11
+
12
+#include "blk-mq-debugfs.h"
13
+
14
+struct blk_mq_debugfs_attr;
915
1016 enum rq_qos_id {
1117 RQ_QOS_WBT,
12
- RQ_QOS_CGROUP,
18
+ RQ_QOS_LATENCY,
19
+ RQ_QOS_COST,
20
+ RQ_QOS_IOPRIO,
1321 };
1422
1523 struct rq_wait {
....@@ -22,17 +30,23 @@
2230 struct request_queue *q;
2331 enum rq_qos_id id;
2432 struct rq_qos *next;
33
+#ifdef CONFIG_BLK_DEBUG_FS
34
+ struct dentry *debugfs_dir;
35
+#endif
2536 };
2637
2738 struct rq_qos_ops {
28
- void (*throttle)(struct rq_qos *, struct bio *, spinlock_t *);
39
+ void (*throttle)(struct rq_qos *, struct bio *);
2940 void (*track)(struct rq_qos *, struct request *, struct bio *);
41
+ void (*merge)(struct rq_qos *, struct request *, struct bio *);
3042 void (*issue)(struct rq_qos *, struct request *);
3143 void (*requeue)(struct rq_qos *, struct request *);
3244 void (*done)(struct rq_qos *, struct request *);
3345 void (*done_bio)(struct rq_qos *, struct bio *);
3446 void (*cleanup)(struct rq_qos *, struct bio *);
47
+ void (*queue_depth_changed)(struct rq_qos *);
3548 void (*exit)(struct rq_qos *);
49
+ const struct blk_mq_debugfs_attr *debugfs_attrs;
3650 };
3751
3852 struct rq_depth {
....@@ -63,7 +77,7 @@
6377
6478 static inline struct rq_qos *blkcg_rq_qos(struct request_queue *q)
6579 {
66
- return rq_qos_id(q, RQ_QOS_CGROUP);
80
+ return rq_qos_id(q, RQ_QOS_LATENCY);
6781 }
6882
6983 static inline void rq_wait_init(struct rq_wait *rq_wait)
....@@ -74,33 +88,132 @@
7488
7589 static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
7690 {
91
+ /*
92
+ * No IO can be in-flight when adding rqos, so freeze queue, which
93
+ * is fine since we only support rq_qos for blk-mq queue.
94
+ *
95
+ * Reuse ->queue_lock for protecting against other concurrent
96
+ * rq_qos adding/deleting
97
+ */
98
+ blk_mq_freeze_queue(q);
99
+
100
+ spin_lock_irq(&q->queue_lock);
77101 rqos->next = q->rq_qos;
78102 q->rq_qos = rqos;
103
+ spin_unlock_irq(&q->queue_lock);
104
+
105
+ blk_mq_unfreeze_queue(q);
106
+
107
+ if (rqos->ops->debugfs_attrs)
108
+ blk_mq_debugfs_register_rqos(rqos);
79109 }
80110
81111 static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos)
82112 {
83113 struct rq_qos **cur;
84114
115
+ /*
116
+ * See comment in rq_qos_add() about freezing queue & using
117
+ * ->queue_lock.
118
+ */
119
+ blk_mq_freeze_queue(q);
120
+
121
+ spin_lock_irq(&q->queue_lock);
85122 for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) {
86123 if (*cur == rqos) {
87124 *cur = rqos->next;
88125 break;
89126 }
90127 }
128
+ spin_unlock_irq(&q->queue_lock);
129
+
130
+ blk_mq_unfreeze_queue(q);
131
+
132
+ blk_mq_debugfs_unregister_rqos(rqos);
91133 }
92134
135
+typedef bool (acquire_inflight_cb_t)(struct rq_wait *rqw, void *private_data);
136
+typedef void (cleanup_cb_t)(struct rq_wait *rqw, void *private_data);
137
+
138
+void rq_qos_wait(struct rq_wait *rqw, void *private_data,
139
+ acquire_inflight_cb_t *acquire_inflight_cb,
140
+ cleanup_cb_t *cleanup_cb);
93141 bool rq_wait_inc_below(struct rq_wait *rq_wait, unsigned int limit);
94142 bool rq_depth_scale_up(struct rq_depth *rqd);
95143 bool rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle);
96144 bool rq_depth_calc_max_depth(struct rq_depth *rqd);
97145
98
-void rq_qos_cleanup(struct request_queue *, struct bio *);
99
-void rq_qos_done(struct request_queue *, struct request *);
100
-void rq_qos_issue(struct request_queue *, struct request *);
101
-void rq_qos_requeue(struct request_queue *, struct request *);
102
-void rq_qos_done_bio(struct request_queue *q, struct bio *bio);
103
-void rq_qos_throttle(struct request_queue *, struct bio *, spinlock_t *);
104
-void rq_qos_track(struct request_queue *q, struct request *, struct bio *);
146
+void __rq_qos_cleanup(struct rq_qos *rqos, struct bio *bio);
147
+void __rq_qos_done(struct rq_qos *rqos, struct request *rq);
148
+void __rq_qos_issue(struct rq_qos *rqos, struct request *rq);
149
+void __rq_qos_requeue(struct rq_qos *rqos, struct request *rq);
150
+void __rq_qos_throttle(struct rq_qos *rqos, struct bio *bio);
151
+void __rq_qos_track(struct rq_qos *rqos, struct request *rq, struct bio *bio);
152
+void __rq_qos_merge(struct rq_qos *rqos, struct request *rq, struct bio *bio);
153
+void __rq_qos_done_bio(struct rq_qos *rqos, struct bio *bio);
154
+void __rq_qos_queue_depth_changed(struct rq_qos *rqos);
155
+
156
+static inline void rq_qos_cleanup(struct request_queue *q, struct bio *bio)
157
+{
158
+ if (q->rq_qos)
159
+ __rq_qos_cleanup(q->rq_qos, bio);
160
+}
161
+
162
+static inline void rq_qos_done(struct request_queue *q, struct request *rq)
163
+{
164
+ if (q->rq_qos)
165
+ __rq_qos_done(q->rq_qos, rq);
166
+}
167
+
168
+static inline void rq_qos_issue(struct request_queue *q, struct request *rq)
169
+{
170
+ if (q->rq_qos)
171
+ __rq_qos_issue(q->rq_qos, rq);
172
+}
173
+
174
+static inline void rq_qos_requeue(struct request_queue *q, struct request *rq)
175
+{
176
+ if (q->rq_qos)
177
+ __rq_qos_requeue(q->rq_qos, rq);
178
+}
179
+
180
+static inline void rq_qos_done_bio(struct request_queue *q, struct bio *bio)
181
+{
182
+ if (q->rq_qos)
183
+ __rq_qos_done_bio(q->rq_qos, bio);
184
+}
185
+
186
+static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio)
187
+{
188
+ /*
189
+ * BIO_TRACKED lets controllers know that a bio went through the
190
+ * normal rq_qos path.
191
+ */
192
+ bio_set_flag(bio, BIO_TRACKED);
193
+ if (q->rq_qos)
194
+ __rq_qos_throttle(q->rq_qos, bio);
195
+}
196
+
197
+static inline void rq_qos_track(struct request_queue *q, struct request *rq,
198
+ struct bio *bio)
199
+{
200
+ if (q->rq_qos)
201
+ __rq_qos_track(q->rq_qos, rq, bio);
202
+}
203
+
204
+static inline void rq_qos_merge(struct request_queue *q, struct request *rq,
205
+ struct bio *bio)
206
+{
207
+ if (q->rq_qos)
208
+ __rq_qos_merge(q->rq_qos, rq, bio);
209
+}
210
+
211
+static inline void rq_qos_queue_depth_changed(struct request_queue *q)
212
+{
213
+ if (q->rq_qos)
214
+ __rq_qos_queue_depth_changed(q->rq_qos);
215
+}
216
+
105217 void rq_qos_exit(struct request_queue *);
218
+
106219 #endif