#include <linux/blk_types.h>
 #include <linux/atomic.h>
 #include <linux/wait.h>
+#include <linux/blk-mq.h>
 
 #include "blk-mq-debugfs.h"
 
 
 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);
 {
        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);
 }