Merge tag 'block-5.14-2021-08-07' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / block / blk-rq-qos.h
index 2bc43e9..f000f83 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/blk_types.h>
 #include <linux/atomic.h>
 #include <linux/wait.h>
+#include <linux/blk-mq.h>
 
 #include "blk-mq-debugfs.h"
 
@@ -16,6 +17,7 @@ enum rq_qos_id {
        RQ_QOS_WBT,
        RQ_QOS_LATENCY,
        RQ_QOS_COST,
+       RQ_QOS_IOPRIO,
 };
 
 struct rq_wait {
@@ -78,19 +80,6 @@ static inline struct rq_qos *blkcg_rq_qos(struct request_queue *q)
        return rq_qos_id(q, RQ_QOS_LATENCY);
 }
 
-static inline const char *rq_qos_id_to_name(enum rq_qos_id id)
-{
-       switch (id) {
-       case RQ_QOS_WBT:
-               return "wbt";
-       case RQ_QOS_LATENCY:
-               return "latency";
-       case RQ_QOS_COST:
-               return "cost";
-       }
-       return "unknown";
-}
-
 static inline void rq_wait_init(struct rq_wait *rq_wait)
 {
        atomic_set(&rq_wait->inflight, 0);
@@ -99,8 +88,21 @@ static inline void rq_wait_init(struct rq_wait *rq_wait)
 
 static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
 {
+       /*
+        * No IO can be in-flight when adding rqos, so freeze queue, which
+        * is fine since we only support rq_qos for blk-mq queue.
+        *
+        * Reuse ->queue_lock for protecting against other concurrent
+        * rq_qos adding/deleting
+        */
+       blk_mq_freeze_queue(q);
+
+       spin_lock_irq(&q->queue_lock);
        rqos->next = q->rq_qos;
        q->rq_qos = rqos;
+       spin_unlock_irq(&q->queue_lock);
+
+       blk_mq_unfreeze_queue(q);
 
        if (rqos->ops->debugfs_attrs)
                blk_mq_debugfs_register_rqos(rqos);
@@ -110,12 +112,22 @@ static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos)
 {
        struct rq_qos **cur;
 
+       /*
+        * See comment in rq_qos_add() about freezing queue & using
+        * ->queue_lock.
+        */
+       blk_mq_freeze_queue(q);
+
+       spin_lock_irq(&q->queue_lock);
        for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) {
                if (*cur == rqos) {
                        *cur = rqos->next;
                        break;
                }
        }
+       spin_unlock_irq(&q->queue_lock);
+
+       blk_mq_unfreeze_queue(q);
 
        blk_mq_debugfs_unregister_rqos(rqos);
 }