diff options
Diffstat (limited to 'block/blk-exec.c')
| -rw-r--r-- | block/blk-exec.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/block/blk-exec.c b/block/blk-exec.c index fb2cbd55162..f4d27b12c90 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -5,6 +5,8 @@ #include <linux/module.h> #include <linux/bio.h> #include <linux/blkdev.h> +#include <linux/blk-mq.h> +#include <linux/sched/sysctl.h> #include "blk.h" @@ -23,7 +25,6 @@ static void blk_end_sync_rq(struct request *rq, int error) struct completion *waiting = rq->end_io_data; rq->end_io_data = NULL; - __blk_put_request(rq->q, rq); /* * complete last, if this is a stack request the process (and thus @@ -43,31 +44,52 @@ static void blk_end_sync_rq(struct request *rq, int error) * Description: * Insert a fully prepared request at the back of the I/O scheduler queue * for execution. Don't wait for completion. + * + * Note: + * This function will invoke @done directly if the queue is dead. */ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, struct request *rq, int at_head, rq_end_io_fn *done) { int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + bool is_pm_resume; WARN_ON(irqs_disabled()); + + rq->rq_disk = bd_disk; + rq->end_io = done; + + /* + * don't check dying flag for MQ because the request won't + * be resued after dying flag is set + */ + if (q->mq_ops) { + blk_mq_insert_request(rq, at_head, true, false); + return; + } + + /* + * need to check this before __blk_run_queue(), because rq can + * be freed before that returns. + */ + is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME; + spin_lock_irq(q->queue_lock); - if (unlikely(blk_queue_dead(q))) { - spin_unlock_irq(q->queue_lock); + if (unlikely(blk_queue_dying(q))) { + rq->cmd_flags |= REQ_QUIET; rq->errors = -ENXIO; - if (rq->end_io) - rq->end_io(rq, rq->errors); + __blk_end_request_all(rq, rq->errors); + spin_unlock_irq(q->queue_lock); return; } - rq->rq_disk = bd_disk; - rq->end_io = done; __elv_add_request(q, rq, where); __blk_run_queue(q); /* the queue is stopped so it won't be run */ - if (rq->cmd_type == REQ_TYPE_PM_RESUME) - q->request_fn(q); + if (is_pm_resume) + __blk_run_queue_uncond(q); spin_unlock_irq(q->queue_lock); } EXPORT_SYMBOL_GPL(blk_execute_rq_nowait); @@ -91,12 +113,6 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, int err = 0; unsigned long hang_check; - /* - * we need an extra reference to the request, so we can look at - * it after io completion - */ - rq->ref_count++; - if (!rq->sense) { memset(sense, 0, sizeof(sense)); rq->sense = sense; @@ -109,13 +125,18 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, /* Prevent hang_check timer from firing at us during very long I/O */ hang_check = sysctl_hung_task_timeout_secs; if (hang_check) - while (!wait_for_completion_timeout(&wait, hang_check * (HZ/2))); + while (!wait_for_completion_io_timeout(&wait, hang_check * (HZ/2))); else - wait_for_completion(&wait); + wait_for_completion_io(&wait); if (rq->errors) err = -EIO; + if (rq->sense == sense) { + rq->sense = NULL; + rq->sense_len = 0; + } + return err; } EXPORT_SYMBOL(blk_execute_rq); |
