]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - block/blk-mq.c
blk-mq: fix race between timeout and freeing request
[mirror_ubuntu-bionic-kernel.git] / block / blk-mq.c
index f53779692c772a1cc06ec341f9fab307b2ceef91..f2d67b4047a04d7015c3c2af16871972c3b5a720 100644 (file)
@@ -559,23 +559,9 @@ void blk_mq_abort_requeue_list(struct request_queue *q)
 }
 EXPORT_SYMBOL(blk_mq_abort_requeue_list);
 
-static inline bool is_flush_request(struct request *rq,
-               struct blk_flush_queue *fq, unsigned int tag)
-{
-       return ((rq->cmd_flags & REQ_FLUSH_SEQ) &&
-                       fq->flush_rq->tag == tag);
-}
-
 struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag)
 {
-       struct request *rq = tags->rqs[tag];
-       /* mq_ctx of flush rq is always cloned from the corresponding req */
-       struct blk_flush_queue *fq = blk_get_flush_queue(rq->q, rq->mq_ctx);
-
-       if (!is_flush_request(rq, fq, tag))
-               return rq;
-
-       return fq->flush_rq;
+       return tags->rqs[tag];
 }
 EXPORT_SYMBOL(blk_mq_tag_to_rq);
 
@@ -1199,7 +1185,7 @@ static struct request *blk_mq_map_request(struct request_queue *q,
        struct blk_mq_alloc_data alloc_data;
 
        if (unlikely(blk_mq_queue_enter(q, GFP_KERNEL))) {
-               bio_endio(bio, -EIO);
+               bio_io_error(bio);
                return NULL;
        }
 
@@ -1283,10 +1269,12 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
        blk_queue_bounce(q, &bio);
 
        if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
-               bio_endio(bio, -EIO);
+               bio_io_error(bio);
                return;
        }
 
+       blk_queue_split(q, &bio, q->bio_split);
+
        if (!is_flush_fua && !blk_queue_nomerges(q) &&
            blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq))
                return;
@@ -1368,10 +1356,12 @@ static void blk_sq_make_request(struct request_queue *q, struct bio *bio)
        blk_queue_bounce(q, &bio);
 
        if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
-               bio_endio(bio, -EIO);
+               bio_io_error(bio);
                return;
        }
 
+       blk_queue_split(q, &bio, q->bio_split);
+
        if (!is_flush_fua && !blk_queue_nomerges(q) &&
            blk_attempt_plug_merge(q, bio, &request_count, NULL))
                return;
@@ -1998,7 +1988,7 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
                goto err_hctxs;
 
        setup_timer(&q->timeout, blk_mq_rq_timer, (unsigned long) q);
-       blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30000);
+       blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);
 
        q->nr_queues = nr_cpu_ids;
        q->nr_hw_queues = set->nr_hw_queues;