Merge tag 'platform-drivers-x86-v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / block / blk-flush.c
index fd5cee9..7942ca6 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/blkdev.h>
 #include <linux/gfp.h>
 #include <linux/blk-mq.h>
-#include <linux/lockdep.h>
 
 #include "blk.h"
 #include "blk-mq.h"
@@ -139,7 +138,7 @@ static void blk_flush_queue_rq(struct request *rq, bool add_front)
 
 static void blk_account_io_flush(struct request *rq)
 {
-       struct hd_struct *part = &rq->rq_disk->part0;
+       struct block_device *part = rq->rq_disk->part0;
 
        part_stat_lock();
        part_stat_inc(part, ios[STAT_FLUSH]);
@@ -433,23 +432,18 @@ void blk_insert_flush(struct request *rq)
 /**
  * blkdev_issue_flush - queue a flush
  * @bdev:      blockdev to issue flush for
- * @gfp_mask:  memory allocation flags (for bio_alloc)
  *
  * Description:
  *    Issue a flush for the block device in question.
  */
-int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask)
+int blkdev_issue_flush(struct block_device *bdev)
 {
-       struct bio *bio;
-       int ret = 0;
+       struct bio bio;
 
-       bio = bio_alloc(gfp_mask, 0);
-       bio_set_dev(bio, bdev);
-       bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
-
-       ret = submit_bio_wait(bio);
-       bio_put(bio);
-       return ret;
+       bio_init(&bio, NULL, 0);
+       bio_set_dev(&bio, bdev);
+       bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+       return submit_bio_wait(&bio);
 }
 EXPORT_SYMBOL(blkdev_issue_flush);
 
@@ -474,9 +468,6 @@ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
        INIT_LIST_HEAD(&fq->flush_queue[1]);
        INIT_LIST_HEAD(&fq->flush_data_in_flight);
 
-       lockdep_register_key(&fq->key);
-       lockdep_set_class(&fq->mq_flush_lock, &fq->key);
-
        return fq;
 
  fail_rq:
@@ -491,7 +482,31 @@ void blk_free_flush_queue(struct blk_flush_queue *fq)
        if (!fq)
                return;
 
-       lockdep_unregister_key(&fq->key);
        kfree(fq->flush_rq);
        kfree(fq);
 }
+
+/*
+ * Allow driver to set its own lock class to fq->mq_flush_lock for
+ * avoiding lockdep complaint.
+ *
+ * flush_end_io() may be called recursively from some driver, such as
+ * nvme-loop, so lockdep may complain 'possible recursive locking' because
+ * all 'struct blk_flush_queue' instance share same mq_flush_lock lock class
+ * key. We need to assign different lock class for these driver's
+ * fq->mq_flush_lock for avoiding the lockdep warning.
+ *
+ * Use dynamically allocated lock class key for each 'blk_flush_queue'
+ * instance is over-kill, and more worse it introduces horrible boot delay
+ * issue because synchronize_rcu() is implied in lockdep_unregister_key which
+ * is called for each hctx release. SCSI probing may synchronously create and
+ * destroy lots of MQ request_queues for non-existent devices, and some robot
+ * test kernel always enable lockdep option. It is observed that more than half
+ * an hour is taken during SCSI MQ probe with per-fq lock class.
+ */
+void blk_mq_hctx_set_fq_lock_class(struct blk_mq_hw_ctx *hctx,
+               struct lock_class_key *key)
+{
+       lockdep_set_class(&hctx->fq->mq_flush_lock, key);
+}
+EXPORT_SYMBOL_GPL(blk_mq_hctx_set_fq_lock_class);