Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/block/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 131 kB image not shown  

Quelle  blk-mq.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Block multiqueue core code
 *
 * Copyright (C) 2013-2014 Jens Axboe
 * Copyright (C) 2013-2014 Christoph Hellwig
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/backing-dev.h>
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/blk-integrity.h>
#include <linux/kmemleak.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <linux/llist.h>
#include <linux/cpu.h>
#include <linux/cache.h>
#include <linux/sched/topology.h>
#include <linux/sched/signal.h>
#include <linux/delay.h>
#include <linux/crash_dump.h>
#include <linux/prefetch.h>
#include <linux/blk-crypto.h>
#include <linux/part_stat.h>
#include <linux/sched/isolation.h>

#include <trace/events/block.h>

#include <linux/t10-pi.h>
#include "blk.h"
#include "blk-mq.h"
#include "blk-mq-debugfs.h"
#include "blk-pm.h"
#include "blk-stat.h"
#include "blk-mq-sched.h"
#include "blk-rq-qos.h"

static DEFINE_PER_CPU(struct llist_head, blk_cpu_done);
static DEFINE_PER_CPU(call_single_data_t, blk_cpu_csd);
static DEFINE_MUTEX(blk_mq_cpuhp_lock);

static void blk_mq_insert_request(struct request *rq, blk_insert_t flags);
static void blk_mq_request_bypass_insert(struct request *rq,
  blk_insert_t flags);
static void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
  struct list_head *list);
static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
    struct io_comp_batch *iob, unsigned int flags);

/*
 * Check if any of the ctx, dispatch list or elevator
 * have pending work in this hardware queue.
 */

static bool blk_mq_hctx_has_pending(struct blk_mq_hw_ctx *hctx)
{
 return !list_empty_careful(&hctx->dispatch) ||
  sbitmap_any_bit_set(&hctx->ctx_map) ||
   blk_mq_sched_has_work(hctx);
}

/*
 * Mark this ctx as having pending work in this hardware queue
 */

static void blk_mq_hctx_mark_pending(struct blk_mq_hw_ctx *hctx,
         struct blk_mq_ctx *ctx)
{
 const int bit = ctx->index_hw[hctx->type];

 if (!sbitmap_test_bit(&hctx->ctx_map, bit))
  sbitmap_set_bit(&hctx->ctx_map, bit);
}

static void blk_mq_hctx_clear_pending(struct blk_mq_hw_ctx *hctx,
          struct blk_mq_ctx *ctx)
{
 const int bit = ctx->index_hw[hctx->type];

 sbitmap_clear_bit(&hctx->ctx_map, bit);
}

struct mq_inflight {
 struct block_device *part;
 unsigned int inflight[2];
};

static bool blk_mq_check_in_driver(struct request *rq, void *priv)
{
 struct mq_inflight *mi = priv;

 if (rq->rq_flags & RQF_IO_STAT &&
     (!bdev_is_partition(mi->part) || rq->part == mi->part) &&
     blk_mq_rq_state(rq) == MQ_RQ_IN_FLIGHT)
  mi->inflight[rq_data_dir(rq)]++;

 return true;
}

void blk_mq_in_driver_rw(struct block_device *part, unsigned int inflight[2])
{
 struct mq_inflight mi = { .part = part };

 blk_mq_queue_tag_busy_iter(bdev_get_queue(part), blk_mq_check_in_driver,
       &mi);
 inflight[READ] = mi.inflight[READ];
 inflight[WRITE] = mi.inflight[WRITE];
}

#ifdef CONFIG_LOCKDEP
static bool blk_freeze_set_owner(struct request_queue *q,
     struct task_struct *owner)
{
 if (!owner)
  return false;

 if (!q->mq_freeze_depth) {
  q->mq_freeze_owner = owner;
  q->mq_freeze_owner_depth = 1;
  q->mq_freeze_disk_dead = !q->disk ||
   test_bit(GD_DEAD, &q->disk->state) ||
   !blk_queue_registered(q);
  q->mq_freeze_queue_dying = blk_queue_dying(q);
  return true;
 }

 if (owner == q->mq_freeze_owner)
  q->mq_freeze_owner_depth += 1;
 return false;
}

/* verify the last unfreeze in owner context */
static bool blk_unfreeze_check_owner(struct request_queue *q)
{
 if (q->mq_freeze_owner != current)
  return false;
 if (--q->mq_freeze_owner_depth == 0) {
  q->mq_freeze_owner = NULL;
  return true;
 }
 return false;
}

#else

static bool blk_freeze_set_owner(struct request_queue *q,
     struct task_struct *owner)
{
 return false;
}

static bool blk_unfreeze_check_owner(struct request_queue *q)
{
 return false;
}
#endif

bool __blk_freeze_queue_start(struct request_queue *q,
         struct task_struct *owner)
{
 bool freeze;

 mutex_lock(&q->mq_freeze_lock);
 freeze = blk_freeze_set_owner(q, owner);
 if (++q->mq_freeze_depth == 1) {
  percpu_ref_kill(&q->q_usage_counter);
  mutex_unlock(&q->mq_freeze_lock);
  if (queue_is_mq(q))
   blk_mq_run_hw_queues(q, false);
 } else {
  mutex_unlock(&q->mq_freeze_lock);
 }

 return freeze;
}

void blk_freeze_queue_start(struct request_queue *q)
{
 if (__blk_freeze_queue_start(q, current))
  blk_freeze_acquire_lock(q);
}
EXPORT_SYMBOL_GPL(blk_freeze_queue_start);

void blk_mq_freeze_queue_wait(struct request_queue *q)
{
 wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->q_usage_counter));
}
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue_wait);

int blk_mq_freeze_queue_wait_timeout(struct request_queue *q,
         unsigned long timeout)
{
 return wait_event_timeout(q->mq_freeze_wq,
     percpu_ref_is_zero(&q->q_usage_counter),
     timeout);
}
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue_wait_timeout);

void blk_mq_freeze_queue_nomemsave(struct request_queue *q)
{
 blk_freeze_queue_start(q);
 blk_mq_freeze_queue_wait(q);
}
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue_nomemsave);

bool __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic)
{
 bool unfreeze;

 mutex_lock(&q->mq_freeze_lock);
 if (force_atomic)
  q->q_usage_counter.data->force_atomic = true;
 q->mq_freeze_depth--;
 WARN_ON_ONCE(q->mq_freeze_depth < 0);
 if (!q->mq_freeze_depth) {
  percpu_ref_resurrect(&q->q_usage_counter);
  wake_up_all(&q->mq_freeze_wq);
 }
 unfreeze = blk_unfreeze_check_owner(q);
 mutex_unlock(&q->mq_freeze_lock);

 return unfreeze;
}

void blk_mq_unfreeze_queue_nomemrestore(struct request_queue *q)
{
 if (__blk_mq_unfreeze_queue(q, false))
  blk_unfreeze_release_lock(q);
}
EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue_nomemrestore);

/*
 * non_owner variant of blk_freeze_queue_start
 *
 * Unlike blk_freeze_queue_start, the queue doesn't need to be unfrozen
 * by the same task.  This is fragile and should not be used if at all
 * possible.
 */

void blk_freeze_queue_start_non_owner(struct request_queue *q)
{
 __blk_freeze_queue_start(q, NULL);
}
EXPORT_SYMBOL_GPL(blk_freeze_queue_start_non_owner);

/* non_owner variant of blk_mq_unfreeze_queue */
void blk_mq_unfreeze_queue_non_owner(struct request_queue *q)
{
 __blk_mq_unfreeze_queue(q, false);
}
EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue_non_owner);

/*
 * FIXME: replace the scsi_internal_device_*block_nowait() calls in the
 * mpt3sas driver such that this function can be removed.
 */

void blk_mq_quiesce_queue_nowait(struct request_queue *q)
{
 unsigned long flags;

 spin_lock_irqsave(&q->queue_lock, flags);
 if (!q->quiesce_depth++)
  blk_queue_flag_set(QUEUE_FLAG_QUIESCED, q);
 spin_unlock_irqrestore(&q->queue_lock, flags);
}
EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_nowait);

/**
 * blk_mq_wait_quiesce_done() - wait until in-progress quiesce is done
 * @set: tag_set to wait on
 *
 * Note: it is driver's responsibility for making sure that quiesce has
 * been started on or more of the request_queues of the tag_set.  This
 * function only waits for the quiesce on those request_queues that had
 * the quiesce flag set using blk_mq_quiesce_queue_nowait.
 */

void blk_mq_wait_quiesce_done(struct blk_mq_tag_set *set)
{
 if (set->flags & BLK_MQ_F_BLOCKING)
  synchronize_srcu(set->srcu);
 else
  synchronize_rcu();
}
EXPORT_SYMBOL_GPL(blk_mq_wait_quiesce_done);

/**
 * blk_mq_quiesce_queue() - wait until all ongoing dispatches have finished
 * @q: request queue.
 *
 * Note: this function does not prevent that the struct request end_io()
 * callback function is invoked. Once this function is returned, we make
 * sure no dispatch can happen until the queue is unquiesced via
 * blk_mq_unquiesce_queue().
 */

void blk_mq_quiesce_queue(struct request_queue *q)
{
 blk_mq_quiesce_queue_nowait(q);
 /* nothing to wait for non-mq queues */
 if (queue_is_mq(q))
  blk_mq_wait_quiesce_done(q->tag_set);
}
EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue);

/*
 * blk_mq_unquiesce_queue() - counterpart of blk_mq_quiesce_queue()
 * @q: request queue.
 *
 * This function recovers queue into the state before quiescing
 * which is done by blk_mq_quiesce_queue.
 */

void blk_mq_unquiesce_queue(struct request_queue *q)
{
 unsigned long flags;
 bool run_queue = false;

 spin_lock_irqsave(&q->queue_lock, flags);
 if (WARN_ON_ONCE(q->quiesce_depth <= 0)) {
  ;
 } else if (!--q->quiesce_depth) {
  blk_queue_flag_clear(QUEUE_FLAG_QUIESCED, q);
  run_queue = true;
 }
 spin_unlock_irqrestore(&q->queue_lock, flags);

 /* dispatch requests which are inserted during quiescing */
 if (run_queue)
  blk_mq_run_hw_queues(q, true);
}
EXPORT_SYMBOL_GPL(blk_mq_unquiesce_queue);

void blk_mq_quiesce_tagset(struct blk_mq_tag_set *set)
{
 struct request_queue *q;

 mutex_lock(&set->tag_list_lock);
 list_for_each_entry(q, &set->tag_list, tag_set_list) {
  if (!blk_queue_skip_tagset_quiesce(q))
   blk_mq_quiesce_queue_nowait(q);
 }
 mutex_unlock(&set->tag_list_lock);

 blk_mq_wait_quiesce_done(set);
}
EXPORT_SYMBOL_GPL(blk_mq_quiesce_tagset);

void blk_mq_unquiesce_tagset(struct blk_mq_tag_set *set)
{
 struct request_queue *q;

 mutex_lock(&set->tag_list_lock);
 list_for_each_entry(q, &set->tag_list, tag_set_list) {
  if (!blk_queue_skip_tagset_quiesce(q))
   blk_mq_unquiesce_queue(q);
 }
 mutex_unlock(&set->tag_list_lock);
}
EXPORT_SYMBOL_GPL(blk_mq_unquiesce_tagset);

void blk_mq_wake_waiters(struct request_queue *q)
{
 struct blk_mq_hw_ctx *hctx;
 unsigned long i;

 queue_for_each_hw_ctx(q, hctx, i)
  if (blk_mq_hw_queue_mapped(hctx))
   blk_mq_tag_wakeup_all(hctx->tags, true);
}

void blk_rq_init(struct request_queue *q, struct request *rq)
{
 memset(rq, 0, sizeof(*rq));

 INIT_LIST_HEAD(&rq->queuelist);
 rq->q = q;
 rq->__sector = (sector_t) -1;
 INIT_HLIST_NODE(&rq->hash);
 RB_CLEAR_NODE(&rq->rb_node);
 rq->tag = BLK_MQ_NO_TAG;
 rq->internal_tag = BLK_MQ_NO_TAG;
 rq->start_time_ns = blk_time_get_ns();
 blk_crypto_rq_set_defaults(rq);
}
EXPORT_SYMBOL(blk_rq_init);

/* Set start and alloc time when the allocated request is actually used */
static inline void blk_mq_rq_time_init(struct request *rq, u64 alloc_time_ns)
{
#ifdef CONFIG_BLK_RQ_ALLOC_TIME
 if (blk_queue_rq_alloc_time(rq->q))
  rq->alloc_time_ns = alloc_time_ns;
 else
  rq->alloc_time_ns = 0;
#endif
}

static inline void blk_mq_bio_issue_init(struct bio *bio)
{
#ifdef CONFIG_BLK_CGROUP
 bio->issue_time_ns = blk_time_get_ns();
#endif
}

static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
  struct blk_mq_tags *tags, unsigned int tag)
{
 struct blk_mq_ctx *ctx = data->ctx;
 struct blk_mq_hw_ctx *hctx = data->hctx;
 struct request_queue *q = data->q;
 struct request *rq = tags->static_rqs[tag];

 rq->q = q;
 rq->mq_ctx = ctx;
 rq->mq_hctx = hctx;
 rq->cmd_flags = data->cmd_flags;

 if (data->flags & BLK_MQ_REQ_PM)
  data->rq_flags |= RQF_PM;
 rq->rq_flags = data->rq_flags;

 if (data->rq_flags & RQF_SCHED_TAGS) {
  rq->tag = BLK_MQ_NO_TAG;
  rq->internal_tag = tag;
 } else {
  rq->tag = tag;
  rq->internal_tag = BLK_MQ_NO_TAG;
 }
 rq->timeout = 0;

 rq->part = NULL;
 rq->io_start_time_ns = 0;
 rq->stats_sectors = 0;
 rq->nr_phys_segments = 0;
 rq->nr_integrity_segments = 0;
 rq->end_io = NULL;
 rq->end_io_data = NULL;

 blk_crypto_rq_set_defaults(rq);
 INIT_LIST_HEAD(&rq->queuelist);
 /* tag was already set */
 WRITE_ONCE(rq->deadline, 0);
 req_ref_set(rq, 1);

 if (rq->rq_flags & RQF_USE_SCHED) {
  struct elevator_queue *e = data->q->elevator;

  INIT_HLIST_NODE(&rq->hash);
  RB_CLEAR_NODE(&rq->rb_node);

  if (e->type->ops.prepare_request)
   e->type->ops.prepare_request(rq);
 }

 return rq;
}

static inline struct request *
__blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data)
{
 unsigned int tag, tag_offset;
 struct blk_mq_tags *tags;
 struct request *rq;
 unsigned long tag_mask;
 int i, nr = 0;

 tag_mask = blk_mq_get_tags(data, data->nr_tags, &tag_offset);
 if (unlikely(!tag_mask))
  return NULL;

 tags = blk_mq_tags_from_data(data);
 for (i = 0; tag_mask; i++) {
  if (!(tag_mask & (1UL << i)))
   continue;
  tag = tag_offset + i;
  prefetch(tags->static_rqs[tag]);
  tag_mask &= ~(1UL << i);
  rq = blk_mq_rq_ctx_init(data, tags, tag);
  rq_list_add_head(data->cached_rqs, rq);
  nr++;
 }
 if (!(data->rq_flags & RQF_SCHED_TAGS))
  blk_mq_add_active_requests(data->hctx, nr);
 /* caller already holds a reference, add for remainder */
 percpu_ref_get_many(&data->q->q_usage_counter, nr - 1);
 data->nr_tags -= nr;

 return rq_list_pop(data->cached_rqs);
}

static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
{
 struct request_queue *q = data->q;
 u64 alloc_time_ns = 0;
 struct request *rq;
 unsigned int tag;

 /* alloc_time includes depth and tag waits */
 if (blk_queue_rq_alloc_time(q))
  alloc_time_ns = blk_time_get_ns();

 if (data->cmd_flags & REQ_NOWAIT)
  data->flags |= BLK_MQ_REQ_NOWAIT;

retry:
 data->ctx = blk_mq_get_ctx(q);
 data->hctx = blk_mq_map_queue(data->cmd_flags, data->ctx);

 if (q->elevator) {
  /*
 * All requests use scheduler tags when an I/O scheduler is
 * enabled for the queue.
 */

  data->rq_flags |= RQF_SCHED_TAGS;

  /*
 * Flush/passthrough requests are special and go directly to the
 * dispatch list.
 */

  if ((data->cmd_flags & REQ_OP_MASK) != REQ_OP_FLUSH &&
      !blk_op_is_passthrough(data->cmd_flags)) {
   struct elevator_mq_ops *ops = &q->elevator->type->ops;

   WARN_ON_ONCE(data->flags & BLK_MQ_REQ_RESERVED);

   data->rq_flags |= RQF_USE_SCHED;
   if (ops->limit_depth)
    ops->limit_depth(data->cmd_flags, data);
  }
 } else {
  blk_mq_tag_busy(data->hctx);
 }

 if (data->flags & BLK_MQ_REQ_RESERVED)
  data->rq_flags |= RQF_RESV;

 /*
 * Try batched alloc if we want more than 1 tag.
 */

 if (data->nr_tags > 1) {
  rq = __blk_mq_alloc_requests_batch(data);
  if (rq) {
   blk_mq_rq_time_init(rq, alloc_time_ns);
   return rq;
  }
  data->nr_tags = 1;
 }

 /*
 * Waiting allocations only fail because of an inactive hctx.  In that
 * case just retry the hctx assignment and tag allocation as CPU hotplug
 * should have migrated us to an online CPU by now.
 */

 tag = blk_mq_get_tag(data);
 if (tag == BLK_MQ_NO_TAG) {
  if (data->flags & BLK_MQ_REQ_NOWAIT)
   return NULL;
  /*
 * Give up the CPU and sleep for a random short time to
 * ensure that thread using a realtime scheduling class
 * are migrated off the CPU, and thus off the hctx that
 * is going away.
 */

  msleep(3);
  goto retry;
 }

 if (!(data->rq_flags & RQF_SCHED_TAGS))
  blk_mq_inc_active_requests(data->hctx);
 rq = blk_mq_rq_ctx_init(data, blk_mq_tags_from_data(data), tag);
 blk_mq_rq_time_init(rq, alloc_time_ns);
 return rq;
}

static struct request *blk_mq_rq_cache_fill(struct request_queue *q,
         struct blk_plug *plug,
         blk_opf_t opf,
         blk_mq_req_flags_t flags)
{
 struct blk_mq_alloc_data data = {
  .q  = q,
  .flags  = flags,
  .shallow_depth = 0,
  .cmd_flags = opf,
  .rq_flags = 0,
  .nr_tags = plug->nr_ios,
  .cached_rqs = &plug->cached_rqs,
  .ctx  = NULL,
  .hctx  = NULL
 };
 struct request *rq;

 if (blk_queue_enter(q, flags))
  return NULL;

 plug->nr_ios = 1;

 rq = __blk_mq_alloc_requests(&data);
 if (unlikely(!rq))
  blk_queue_exit(q);
 return rq;
}

static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
         blk_opf_t opf,
         blk_mq_req_flags_t flags)
{
 struct blk_plug *plug = current->plug;
 struct request *rq;

 if (!plug)
  return NULL;

 if (rq_list_empty(&plug->cached_rqs)) {
  if (plug->nr_ios == 1)
   return NULL;
  rq = blk_mq_rq_cache_fill(q, plug, opf, flags);
  if (!rq)
   return NULL;
 } else {
  rq = rq_list_peek(&plug->cached_rqs);
  if (!rq || rq->q != q)
   return NULL;

  if (blk_mq_get_hctx_type(opf) != rq->mq_hctx->type)
   return NULL;
  if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
   return NULL;

  rq_list_pop(&plug->cached_rqs);
  blk_mq_rq_time_init(rq, blk_time_get_ns());
 }

 rq->cmd_flags = opf;
 INIT_LIST_HEAD(&rq->queuelist);
 return rq;
}

struct request *blk_mq_alloc_request(struct request_queue *q, blk_opf_t opf,
  blk_mq_req_flags_t flags)
{
 struct request *rq;

 rq = blk_mq_alloc_cached_request(q, opf, flags);
 if (!rq) {
  struct blk_mq_alloc_data data = {
   .q  = q,
   .flags  = flags,
   .shallow_depth = 0,
   .cmd_flags = opf,
   .rq_flags = 0,
   .nr_tags = 1,
   .cached_rqs = NULL,
   .ctx  = NULL,
   .hctx  = NULL
  };
  int ret;

  ret = blk_queue_enter(q, flags);
  if (ret)
   return ERR_PTR(ret);

  rq = __blk_mq_alloc_requests(&data);
  if (!rq)
   goto out_queue_exit;
 }
 rq->__data_len = 0;
 rq->__sector = (sector_t) -1;
 rq->bio = rq->biotail = NULL;
 return rq;
out_queue_exit:
 blk_queue_exit(q);
 return ERR_PTR(-EWOULDBLOCK);
}
EXPORT_SYMBOL(blk_mq_alloc_request);

struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
 blk_opf_t opf, blk_mq_req_flags_t flags, unsigned int hctx_idx)
{
 struct blk_mq_alloc_data data = {
  .q  = q,
  .flags  = flags,
  .shallow_depth = 0,
  .cmd_flags = opf,
  .rq_flags = 0,
  .nr_tags = 1,
  .cached_rqs = NULL,
  .ctx  = NULL,
  .hctx  = NULL
 };
 u64 alloc_time_ns = 0;
 struct request *rq;
 unsigned int cpu;
 unsigned int tag;
 int ret;

 /* alloc_time includes depth and tag waits */
 if (blk_queue_rq_alloc_time(q))
  alloc_time_ns = blk_time_get_ns();

 /*
 * If the tag allocator sleeps we could get an allocation for a
 * different hardware context.  No need to complicate the low level
 * allocator for this for the rare use case of a command tied to
 * a specific queue.
 */

 if (WARN_ON_ONCE(!(flags & BLK_MQ_REQ_NOWAIT)) ||
     WARN_ON_ONCE(!(flags & BLK_MQ_REQ_RESERVED)))
  return ERR_PTR(-EINVAL);

 if (hctx_idx >= q->nr_hw_queues)
  return ERR_PTR(-EIO);

 ret = blk_queue_enter(q, flags);
 if (ret)
  return ERR_PTR(ret);

 /*
 * Check if the hardware context is actually mapped to anything.
 * If not tell the caller that it should skip this queue.
 */

 ret = -EXDEV;
 data.hctx = xa_load(&q->hctx_table, hctx_idx);
 if (!blk_mq_hw_queue_mapped(data.hctx))
  goto out_queue_exit;
 cpu = cpumask_first_and(data.hctx->cpumask, cpu_online_mask);
 if (cpu >= nr_cpu_ids)
  goto out_queue_exit;
 data.ctx = __blk_mq_get_ctx(q, cpu);

 if (q->elevator)
  data.rq_flags |= RQF_SCHED_TAGS;
 else
  blk_mq_tag_busy(data.hctx);

 if (flags & BLK_MQ_REQ_RESERVED)
  data.rq_flags |= RQF_RESV;

 ret = -EWOULDBLOCK;
 tag = blk_mq_get_tag(&data);
 if (tag == BLK_MQ_NO_TAG)
  goto out_queue_exit;
 if (!(data.rq_flags & RQF_SCHED_TAGS))
  blk_mq_inc_active_requests(data.hctx);
 rq = blk_mq_rq_ctx_init(&data, blk_mq_tags_from_data(&data), tag);
 blk_mq_rq_time_init(rq, alloc_time_ns);
 rq->__data_len = 0;
 rq->__sector = (sector_t) -1;
 rq->bio = rq->biotail = NULL;
 return rq;

out_queue_exit:
 blk_queue_exit(q);
 return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(blk_mq_alloc_request_hctx);

static void blk_mq_finish_request(struct request *rq)
{
 struct request_queue *q = rq->q;

 blk_zone_finish_request(rq);

 if (rq->rq_flags & RQF_USE_SCHED) {
  q->elevator->type->ops.finish_request(rq);
  /*
 * For postflush request that may need to be
 * completed twice, we should clear this flag
 * to avoid double finish_request() on the rq.
 */

  rq->rq_flags &= ~RQF_USE_SCHED;
 }
}

static void __blk_mq_free_request(struct request *rq)
{
 struct request_queue *q = rq->q;
 struct blk_mq_ctx *ctx = rq->mq_ctx;
 struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
 const int sched_tag = rq->internal_tag;

 blk_crypto_free_request(rq);
 blk_pm_mark_last_busy(rq);
 rq->mq_hctx = NULL;

 if (rq->tag != BLK_MQ_NO_TAG) {
  blk_mq_dec_active_requests(hctx);
  blk_mq_put_tag(hctx->tags, ctx, rq->tag);
 }
 if (sched_tag != BLK_MQ_NO_TAG)
  blk_mq_put_tag(hctx->sched_tags, ctx, sched_tag);
 blk_mq_sched_restart(hctx);
 blk_queue_exit(q);
}

void blk_mq_free_request(struct request *rq)
{
 struct request_queue *q = rq->q;

 blk_mq_finish_request(rq);

 if (unlikely(laptop_mode && !blk_rq_is_passthrough(rq)))
  laptop_io_completion(q->disk->bdi);

 rq_qos_done(q, rq);

 WRITE_ONCE(rq->state, MQ_RQ_IDLE);
 if (req_ref_put_and_test(rq))
  __blk_mq_free_request(rq);
}
EXPORT_SYMBOL_GPL(blk_mq_free_request);

void blk_mq_free_plug_rqs(struct blk_plug *plug)
{
 struct request *rq;

 while ((rq = rq_list_pop(&plug->cached_rqs)) != NULL)
  blk_mq_free_request(rq);
}

void blk_dump_rq_flags(struct request *rq, char *msg)
{
 printk(KERN_INFO "%s: dev %s: flags=%llx\n", msg,
  rq->q->disk ? rq->q->disk->disk_name : "?",
  (__force unsigned long long) rq->cmd_flags);

 printk(KERN_INFO " sector %llu, nr/cnr %u/%u\n",
        (unsigned long long)blk_rq_pos(rq),
        blk_rq_sectors(rq), blk_rq_cur_sectors(rq));
 printk(KERN_INFO " bio %p, biotail %p, len %u\n",
        rq->bio, rq->biotail, blk_rq_bytes(rq));
}
EXPORT_SYMBOL(blk_dump_rq_flags);

static void blk_account_io_completion(struct request *req, unsigned int bytes)
{
 if (req->rq_flags & RQF_IO_STAT) {
  const int sgrp = op_stat_group(req_op(req));

  part_stat_lock();
  part_stat_add(req->part, sectors[sgrp], bytes >> 9);
  part_stat_unlock();
 }
}

static void blk_print_req_error(struct request *req, blk_status_t status)
{
 printk_ratelimited(KERN_ERR
  "%s error, dev %s, sector %llu op 0x%x:(%s) flags 0x%x "
  "phys_seg %u prio class %u\n",
  blk_status_to_str(status),
  req->q->disk ? req->q->disk->disk_name : "?",
  blk_rq_pos(req), (__force u32)req_op(req),
  blk_op_str(req_op(req)),
  (__force u32)(req->cmd_flags & ~REQ_OP_MASK),
  req->nr_phys_segments,
  IOPRIO_PRIO_CLASS(req_get_ioprio(req)));
}

/*
 * Fully end IO on a request. Does not support partial completions, or
 * errors.
 */

static void blk_complete_request(struct request *req)
{
 const bool is_flush = (req->rq_flags & RQF_FLUSH_SEQ) != 0;
 int total_bytes = blk_rq_bytes(req);
 struct bio *bio = req->bio;

 trace_block_rq_complete(req, BLK_STS_OK, total_bytes);

 if (!bio)
  return;

 if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ)
  blk_integrity_complete(req, total_bytes);

 /*
 * Upper layers may call blk_crypto_evict_key() anytime after the last
 * bio_endio().  Therefore, the keyslot must be released before that.
 */

 blk_crypto_rq_put_keyslot(req);

 blk_account_io_completion(req, total_bytes);

 do {
  struct bio *next = bio->bi_next;

  /* Completion has already been traced */
  bio_clear_flag(bio, BIO_TRACE_COMPLETION);

  if (blk_req_bio_is_zone_append(req, bio))
   blk_zone_append_update_request_bio(req, bio);

  if (!is_flush)
   bio_endio(bio);
  bio = next;
 } while (bio);

 /*
 * Reset counters so that the request stacking driver
 * can find how many bytes remain in the request
 * later.
 */

 if (!req->end_io) {
  req->bio = NULL;
  req->__data_len = 0;
 }
}

/**
 * blk_update_request - Complete multiple bytes without completing the request
 * @req:      the request being processed
 * @error:    block status code
 * @nr_bytes: number of bytes to complete for @req
 *
 * Description:
 *     Ends I/O on a number of bytes attached to @req, but doesn't complete
 *     the request structure even if @req doesn't have leftover.
 *     If @req has leftover, sets it up for the next range of segments.
 *
 *     Passing the result of blk_rq_bytes() as @nr_bytes guarantees
 *     %false return from this function.
 *
 * Note:
 * The RQF_SPECIAL_PAYLOAD flag is ignored on purpose in this function
 *      except in the consistency check at the end of this function.
 *
 * Return:
 *     %false - this request doesn't have any more data
 *     %true  - this request has more data
 **/

bool blk_update_request(struct request *req, blk_status_t error,
  unsigned int nr_bytes)
{
 bool is_flush = req->rq_flags & RQF_FLUSH_SEQ;
 bool quiet = req->rq_flags & RQF_QUIET;
 int total_bytes;

 trace_block_rq_complete(req, error, nr_bytes);

 if (!req->bio)
  return false;

 if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ &&
     error == BLK_STS_OK)
  blk_integrity_complete(req, nr_bytes);

 /*
 * Upper layers may call blk_crypto_evict_key() anytime after the last
 * bio_endio().  Therefore, the keyslot must be released before that.
 */

 if (blk_crypto_rq_has_keyslot(req) && nr_bytes >= blk_rq_bytes(req))
  __blk_crypto_rq_put_keyslot(req);

 if (unlikely(error && !blk_rq_is_passthrough(req) && !quiet) &&
     !test_bit(GD_DEAD, &req->q->disk->state)) {
  blk_print_req_error(req, error);
  trace_block_rq_error(req, error, nr_bytes);
 }

 blk_account_io_completion(req, nr_bytes);

 total_bytes = 0;
 while (req->bio) {
  struct bio *bio = req->bio;
  unsigned bio_bytes = min(bio->bi_iter.bi_size, nr_bytes);

  if (unlikely(error))
   bio->bi_status = error;

  if (bio_bytes == bio->bi_iter.bi_size) {
   req->bio = bio->bi_next;
  } else if (bio_is_zone_append(bio) && error == BLK_STS_OK) {
   /*
 * Partial zone append completions cannot be supported
 * as the BIO fragments may end up not being written
 * sequentially.
 */

   bio->bi_status = BLK_STS_IOERR;
  }

  /* Completion has already been traced */
  bio_clear_flag(bio, BIO_TRACE_COMPLETION);
  if (unlikely(quiet))
   bio_set_flag(bio, BIO_QUIET);

  bio_advance(bio, bio_bytes);

  /* Don't actually finish bio if it's part of flush sequence */
  if (!bio->bi_iter.bi_size) {
   if (blk_req_bio_is_zone_append(req, bio))
    blk_zone_append_update_request_bio(req, bio);
   if (!is_flush)
    bio_endio(bio);
  }

  total_bytes += bio_bytes;
  nr_bytes -= bio_bytes;

  if (!nr_bytes)
   break;
 }

 /*
 * completely done
 */

 if (!req->bio) {
  /*
 * Reset counters so that the request stacking driver
 * can find how many bytes remain in the request
 * later.
 */

  req->__data_len = 0;
  return false;
 }

 req->__data_len -= total_bytes;

 /* update sector only for requests with clear definition of sector */
 if (!blk_rq_is_passthrough(req))
  req->__sector += total_bytes >> 9;

 /* mixed attributes always follow the first bio */
 if (req->rq_flags & RQF_MIXED_MERGE) {
  req->cmd_flags &= ~REQ_FAILFAST_MASK;
  req->cmd_flags |= req->bio->bi_opf & REQ_FAILFAST_MASK;
 }

 if (!(req->rq_flags & RQF_SPECIAL_PAYLOAD)) {
  /*
 * If total number of sectors is less than the first segment
 * size, something has gone terribly wrong.
 */

  if (blk_rq_bytes(req) < blk_rq_cur_bytes(req)) {
   blk_dump_rq_flags(req, "request botched");
   req->__data_len = blk_rq_cur_bytes(req);
  }

  /* recalculate the number of segments */
  req->nr_phys_segments = blk_recalc_rq_segments(req);
 }

 return true;
}
EXPORT_SYMBOL_GPL(blk_update_request);

static inline void blk_account_io_done(struct request *req, u64 now)
{
 trace_block_io_done(req);

 /*
 * Account IO completion.  flush_rq isn't accounted as a
 * normal IO on queueing nor completion.  Accounting the
 * containing request is enough.
 */

 if ((req->rq_flags & (RQF_IO_STAT|RQF_FLUSH_SEQ)) == RQF_IO_STAT) {
  const int sgrp = op_stat_group(req_op(req));

  part_stat_lock();
  update_io_ticks(req->part, jiffies, true);
  part_stat_inc(req->part, ios[sgrp]);
  part_stat_add(req->part, nsecs[sgrp], now - req->start_time_ns);
  part_stat_local_dec(req->part,
        in_flight[op_is_write(req_op(req))]);
  part_stat_unlock();
 }
}

static inline bool blk_rq_passthrough_stats(struct request *req)
{
 struct bio *bio = req->bio;

 if (!blk_queue_passthrough_stat(req->q))
  return false;

 /* Requests without a bio do not transfer data. */
 if (!bio)
  return false;

 /*
 * Stats are accumulated in the bdev, so must have one attached to a
 * bio to track stats. Most drivers do not set the bdev for passthrough
 * requests, but nvme is one that will set it.
 */

 if (!bio->bi_bdev)
  return false;

 /*
 * We don't know what a passthrough command does, but we know the
 * payload size and data direction. Ensuring the size is aligned to the
 * block size filters out most commands with payloads that don't
 * represent sector access.
 */

 if (blk_rq_bytes(req) & (bdev_logical_block_size(bio->bi_bdev) - 1))
  return false;
 return true;
}

static inline void blk_account_io_start(struct request *req)
{
 trace_block_io_start(req);

 if (!blk_queue_io_stat(req->q))
  return;
 if (blk_rq_is_passthrough(req) && !blk_rq_passthrough_stats(req))
  return;

 req->rq_flags |= RQF_IO_STAT;
 req->start_time_ns = blk_time_get_ns();

 /*
 * All non-passthrough requests are created from a bio with one
 * exception: when a flush command that is part of a flush sequence
 * generated by the state machine in blk-flush.c is cloned onto the
 * lower device by dm-multipath we can get here without a bio.
 */

 if (req->bio)
  req->part = req->bio->bi_bdev;
 else
  req->part = req->q->disk->part0;

 part_stat_lock();
 update_io_ticks(req->part, jiffies, false);
 part_stat_local_inc(req->part, in_flight[op_is_write(req_op(req))]);
 part_stat_unlock();
}

static inline void __blk_mq_end_request_acct(struct request *rq, u64 now)
{
 if (rq->rq_flags & RQF_STATS)
  blk_stat_add(rq, now);

 blk_mq_sched_completed_request(rq, now);
 blk_account_io_done(rq, now);
}

inline void __blk_mq_end_request(struct request *rq, blk_status_t error)
{
 if (blk_mq_need_time_stamp(rq))
  __blk_mq_end_request_acct(rq, blk_time_get_ns());

 blk_mq_finish_request(rq);

 if (rq->end_io) {
  rq_qos_done(rq->q, rq);
  if (rq->end_io(rq, error) == RQ_END_IO_FREE)
   blk_mq_free_request(rq);
 } else {
  blk_mq_free_request(rq);
 }
}
EXPORT_SYMBOL(__blk_mq_end_request);

void blk_mq_end_request(struct request *rq, blk_status_t error)
{
 if (blk_update_request(rq, error, blk_rq_bytes(rq)))
  BUG();
 __blk_mq_end_request(rq, error);
}
EXPORT_SYMBOL(blk_mq_end_request);

#define TAG_COMP_BATCH  32

static inline void blk_mq_flush_tag_batch(struct blk_mq_hw_ctx *hctx,
       int *tag_array, int nr_tags)
{
 struct request_queue *q = hctx->queue;

 blk_mq_sub_active_requests(hctx, nr_tags);

 blk_mq_put_tags(hctx->tags, tag_array, nr_tags);
 percpu_ref_put_many(&q->q_usage_counter, nr_tags);
}

void blk_mq_end_request_batch(struct io_comp_batch *iob)
{
 int tags[TAG_COMP_BATCH], nr_tags = 0;
 struct blk_mq_hw_ctx *cur_hctx = NULL;
 struct request *rq;
 u64 now = 0;

 if (iob->need_ts)
  now = blk_time_get_ns();

 while ((rq = rq_list_pop(&iob->req_list)) != NULL) {
  prefetch(rq->bio);
  prefetch(rq->rq_next);

  blk_complete_request(rq);
  if (iob->need_ts)
   __blk_mq_end_request_acct(rq, now);

  blk_mq_finish_request(rq);

  rq_qos_done(rq->q, rq);

  /*
 * If end_io handler returns NONE, then it still has
 * ownership of the request.
 */

  if (rq->end_io && rq->end_io(rq, 0) == RQ_END_IO_NONE)
   continue;

  WRITE_ONCE(rq->state, MQ_RQ_IDLE);
  if (!req_ref_put_and_test(rq))
   continue;

  blk_crypto_free_request(rq);
  blk_pm_mark_last_busy(rq);

  if (nr_tags == TAG_COMP_BATCH || cur_hctx != rq->mq_hctx) {
   if (cur_hctx)
    blk_mq_flush_tag_batch(cur_hctx, tags, nr_tags);
   nr_tags = 0;
   cur_hctx = rq->mq_hctx;
  }
  tags[nr_tags++] = rq->tag;
 }

 if (nr_tags)
  blk_mq_flush_tag_batch(cur_hctx, tags, nr_tags);
}
EXPORT_SYMBOL_GPL(blk_mq_end_request_batch);

static void blk_complete_reqs(struct llist_head *list)
{
 struct llist_node *entry = llist_reverse_order(llist_del_all(list));
 struct request *rq, *next;

 llist_for_each_entry_safe(rq, next, entry, ipi_list)
  rq->q->mq_ops->complete(rq);
}

static __latent_entropy void blk_done_softirq(void)
{
 blk_complete_reqs(this_cpu_ptr(&blk_cpu_done));
}

static int blk_softirq_cpu_dead(unsigned int cpu)
{
 blk_complete_reqs(&per_cpu(blk_cpu_done, cpu));
 return 0;
}

static void __blk_mq_complete_request_remote(void *data)
{
 __raise_softirq_irqoff(BLOCK_SOFTIRQ);
}

static inline bool blk_mq_complete_need_ipi(struct request *rq)
{
 int cpu = raw_smp_processor_id();

 if (!IS_ENABLED(CONFIG_SMP) ||
     !test_bit(QUEUE_FLAG_SAME_COMP, &rq->q->queue_flags))
  return false;
 /*
 * With force threaded interrupts enabled, raising softirq from an SMP
 * function call will always result in waking the ksoftirqd thread.
 * This is probably worse than completing the request on a different
 * cache domain.
 */

 if (force_irqthreads())
  return false;

 /* same CPU or cache domain and capacity?  Complete locally */
 if (cpu == rq->mq_ctx->cpu ||
     (!test_bit(QUEUE_FLAG_SAME_FORCE, &rq->q->queue_flags) &&
      cpus_share_cache(cpu, rq->mq_ctx->cpu) &&
      cpus_equal_capacity(cpu, rq->mq_ctx->cpu)))
  return false;

 /* don't try to IPI to an offline CPU */
 return cpu_online(rq->mq_ctx->cpu);
}

static void blk_mq_complete_send_ipi(struct request *rq)
{
 unsigned int cpu;

 cpu = rq->mq_ctx->cpu;
 if (llist_add(&rq->ipi_list, &per_cpu(blk_cpu_done, cpu)))
  smp_call_function_single_async(cpu, &per_cpu(blk_cpu_csd, cpu));
}

static void blk_mq_raise_softirq(struct request *rq)
{
 struct llist_head *list;

 preempt_disable();
 list = this_cpu_ptr(&blk_cpu_done);
 if (llist_add(&rq->ipi_list, list))
  raise_softirq(BLOCK_SOFTIRQ);
 preempt_enable();
}

bool blk_mq_complete_request_remote(struct request *rq)
{
 WRITE_ONCE(rq->state, MQ_RQ_COMPLETE);

 /*
 * For request which hctx has only one ctx mapping,
 * or a polled request, always complete locally,
 * it's pointless to redirect the completion.
 */

 if ((rq->mq_hctx->nr_ctx == 1 &&
      rq->mq_ctx->cpu == raw_smp_processor_id()) ||
      rq->cmd_flags & REQ_POLLED)
  return false;

 if (blk_mq_complete_need_ipi(rq)) {
  blk_mq_complete_send_ipi(rq);
  return true;
 }

 if (rq->q->nr_hw_queues == 1) {
  blk_mq_raise_softirq(rq);
  return true;
 }
 return false;
}
EXPORT_SYMBOL_GPL(blk_mq_complete_request_remote);

/**
 * blk_mq_complete_request - end I/O on a request
 * @rq: the request being processed
 *
 * Description:
 * Complete a request by scheduling the ->complete_rq operation.
 **/

void blk_mq_complete_request(struct request *rq)
{
 if (!blk_mq_complete_request_remote(rq))
  rq->q->mq_ops->complete(rq);
}
EXPORT_SYMBOL(blk_mq_complete_request);

/**
 * blk_mq_start_request - Start processing a request
 * @rq: Pointer to request to be started
 *
 * Function used by device drivers to notify the block layer that a request
 * is going to be processed now, so blk layer can do proper initializations
 * such as starting the timeout timer.
 */

void blk_mq_start_request(struct request *rq)
{
 struct request_queue *q = rq->q;

 trace_block_rq_issue(rq);

 if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags) &&
     !blk_rq_is_passthrough(rq)) {
  rq->io_start_time_ns = blk_time_get_ns();
  rq->stats_sectors = blk_rq_sectors(rq);
  rq->rq_flags |= RQF_STATS;
  rq_qos_issue(q, rq);
 }

 WARN_ON_ONCE(blk_mq_rq_state(rq) != MQ_RQ_IDLE);

 blk_add_timer(rq);
 WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT);
 rq->mq_hctx->tags->rqs[rq->tag] = rq;

 if (blk_integrity_rq(rq) && req_op(rq) == REQ_OP_WRITE)
  blk_integrity_prepare(rq);

 if (rq->bio && rq->bio->bi_opf & REQ_POLLED)
         WRITE_ONCE(rq->bio->bi_cookie, rq->mq_hctx->queue_num);
}
EXPORT_SYMBOL(blk_mq_start_request);

/*
 * Allow 2x BLK_MAX_REQUEST_COUNT requests on plug queue for multiple
 * queues. This is important for md arrays to benefit from merging
 * requests.
 */

static inline unsigned short blk_plug_max_rq_count(struct blk_plug *plug)
{
 if (plug->multiple_queues)
  return BLK_MAX_REQUEST_COUNT * 2;
 return BLK_MAX_REQUEST_COUNT;
}

static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq)
{
 struct request *last = rq_list_peek(&plug->mq_list);

 if (!plug->rq_count) {
  trace_block_plug(rq->q);
 } else if (plug->rq_count >= blk_plug_max_rq_count(plug) ||
     (!blk_queue_nomerges(rq->q) &&
      blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE)) {
  blk_mq_flush_plug_list(plug, false);
  last = NULL;
  trace_block_plug(rq->q);
 }

 if (!plug->multiple_queues && last && last->q != rq->q)
  plug->multiple_queues = true;
 /*
 * Any request allocated from sched tags can't be issued to
 * ->queue_rqs() directly
 */

 if (!plug->has_elevator && (rq->rq_flags & RQF_SCHED_TAGS))
  plug->has_elevator = true;
 rq_list_add_tail(&plug->mq_list, rq);
 plug->rq_count++;
}

/**
 * blk_execute_rq_nowait - insert a request to I/O scheduler for execution
 * @rq: request to insert
 * @at_head:    insert request at head or tail of queue
 *
 * 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 *rq, bool at_head)
{
 struct blk_mq_hw_ctx *hctx = rq->mq_hctx;

 WARN_ON(irqs_disabled());
 WARN_ON(!blk_rq_is_passthrough(rq));

 blk_account_io_start(rq);

 if (current->plug && !at_head) {
  blk_add_rq_to_plug(current->plug, rq);
  return;
 }

 blk_mq_insert_request(rq, at_head ? BLK_MQ_INSERT_AT_HEAD : 0);
 blk_mq_run_hw_queue(hctx, hctx->flags & BLK_MQ_F_BLOCKING);
}
EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);

struct blk_rq_wait {
 struct completion done;
 blk_status_t ret;
};

static enum rq_end_io_ret blk_end_sync_rq(struct request *rq, blk_status_t ret)
{
 struct blk_rq_wait *wait = rq->end_io_data;

 wait->ret = ret;
 complete(&wait->done);
 return RQ_END_IO_NONE;
}

bool blk_rq_is_poll(struct request *rq)
{
 if (!rq->mq_hctx)
  return false;
 if (rq->mq_hctx->type != HCTX_TYPE_POLL)
  return false;
 return true;
}
EXPORT_SYMBOL_GPL(blk_rq_is_poll);

static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
{
 do {
  blk_hctx_poll(rq->q, rq->mq_hctx, NULL, 0);
  cond_resched();
 } while (!completion_done(wait));
}

/**
 * blk_execute_rq - insert a request into queue for execution
 * @rq: request to insert
 * @at_head:    insert request at head or tail of queue
 *
 * Description:
 *    Insert a fully prepared request at the back of the I/O scheduler queue
 *    for execution and wait for completion.
 * Return: The blk_status_t result provided to blk_mq_end_request().
 */

blk_status_t blk_execute_rq(struct request *rq, bool at_head)
{
 struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
 struct blk_rq_wait wait = {
  .done = COMPLETION_INITIALIZER_ONSTACK(wait.done),
 };

 WARN_ON(irqs_disabled());
 WARN_ON(!blk_rq_is_passthrough(rq));

 rq->end_io_data = &wait;
 rq->end_io = blk_end_sync_rq;

 blk_account_io_start(rq);
 blk_mq_insert_request(rq, at_head ? BLK_MQ_INSERT_AT_HEAD : 0);
 blk_mq_run_hw_queue(hctx, false);

 if (blk_rq_is_poll(rq))
  blk_rq_poll_completion(rq, &wait.done);
 else
  blk_wait_io(&wait.done);

 return wait.ret;
}
EXPORT_SYMBOL(blk_execute_rq);

static void __blk_mq_requeue_request(struct request *rq)
{
 struct request_queue *q = rq->q;

 blk_mq_put_driver_tag(rq);

 trace_block_rq_requeue(rq);
 rq_qos_requeue(q, rq);

 if (blk_mq_request_started(rq)) {
  WRITE_ONCE(rq->state, MQ_RQ_IDLE);
  rq->rq_flags &= ~RQF_TIMED_OUT;
 }
}

void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list)
{
 struct request_queue *q = rq->q;
 unsigned long flags;

 __blk_mq_requeue_request(rq);

 /* this request will be re-inserted to io scheduler queue */
 blk_mq_sched_requeue_request(rq);

 spin_lock_irqsave(&q->requeue_lock, flags);
 list_add_tail(&rq->queuelist, &q->requeue_list);
 spin_unlock_irqrestore(&q->requeue_lock, flags);

 if (kick_requeue_list)
  blk_mq_kick_requeue_list(q);
}
EXPORT_SYMBOL(blk_mq_requeue_request);

static void blk_mq_requeue_work(struct work_struct *work)
{
 struct request_queue *q =
  container_of(work, struct request_queue, requeue_work.work);
 LIST_HEAD(rq_list);
 LIST_HEAD(flush_list);
 struct request *rq;

 spin_lock_irq(&q->requeue_lock);
 list_splice_init(&q->requeue_list, &rq_list);
 list_splice_init(&q->flush_list, &flush_list);
 spin_unlock_irq(&q->requeue_lock);

 while (!list_empty(&rq_list)) {
  rq = list_entry(rq_list.next, struct request, queuelist);
  list_del_init(&rq->queuelist);
  /*
 * If RQF_DONTPREP is set, the request has been started by the
 * driver already and might have driver-specific data allocated
 * already.  Insert it into the hctx dispatch list to avoid
 * block layer merges for the request.
 */

  if (rq->rq_flags & RQF_DONTPREP)
   blk_mq_request_bypass_insert(rq, 0);
  else
   blk_mq_insert_request(rq, BLK_MQ_INSERT_AT_HEAD);
 }

 while (!list_empty(&flush_list)) {
  rq = list_entry(flush_list.next, struct request, queuelist);
  list_del_init(&rq->queuelist);
  blk_mq_insert_request(rq, 0);
 }

 blk_mq_run_hw_queues(q, false);
}

void blk_mq_kick_requeue_list(struct request_queue *q)
{
 kblockd_mod_delayed_work_on(WORK_CPU_UNBOUND, &q->requeue_work, 0);
}
EXPORT_SYMBOL(blk_mq_kick_requeue_list);

void blk_mq_delay_kick_requeue_list(struct request_queue *q,
        unsigned long msecs)
{
 kblockd_mod_delayed_work_on(WORK_CPU_UNBOUND, &q->requeue_work,
        msecs_to_jiffies(msecs));
}
EXPORT_SYMBOL(blk_mq_delay_kick_requeue_list);

static bool blk_is_flush_data_rq(struct request *rq)
{
 return (rq->rq_flags & RQF_FLUSH_SEQ) && !is_flush_rq(rq);
}

static bool blk_mq_rq_inflight(struct request *rq, void *priv)
{
 /*
 * If we find a request that isn't idle we know the queue is busy
 * as it's checked in the iter.
 * Return false to stop the iteration.
 *
 * In case of queue quiesce, if one flush data request is completed,
 * don't count it as inflight given the flush sequence is suspended,
 * and the original flush data request is invisible to driver, just
 * like other pending requests because of quiesce
 */

 if (blk_mq_request_started(rq) && !(blk_queue_quiesced(rq->q) &&
    blk_is_flush_data_rq(rq) &&
    blk_mq_request_completed(rq))) {
  bool *busy = priv;

  *busy = true;
  return false;
 }

 return true;
}

bool blk_mq_queue_inflight(struct request_queue *q)
{
 bool busy = false;

 blk_mq_queue_tag_busy_iter(q, blk_mq_rq_inflight, &busy);
 return busy;
}
EXPORT_SYMBOL_GPL(blk_mq_queue_inflight);

static void blk_mq_rq_timed_out(struct request *req)
{
 req->rq_flags |= RQF_TIMED_OUT;
 if (req->q->mq_ops->timeout) {
  enum blk_eh_timer_return ret;

  ret = req->q->mq_ops->timeout(req);
  if (ret == BLK_EH_DONE)
   return;
  WARN_ON_ONCE(ret != BLK_EH_RESET_TIMER);
 }

 blk_add_timer(req);
}

struct blk_expired_data {
 bool has_timedout_rq;
 unsigned long next;
 unsigned long timeout_start;
};

static bool blk_mq_req_expired(struct request *rq, struct blk_expired_data *expired)
{
 unsigned long deadline;

 if (blk_mq_rq_state(rq) != MQ_RQ_IN_FLIGHT)
  return false;
 if (rq->rq_flags & RQF_TIMED_OUT)
  return false;

 deadline = READ_ONCE(rq->deadline);
 if (time_after_eq(expired->timeout_start, deadline))
  return true;

 if (expired->next == 0)
  expired->next = deadline;
 else if (time_after(expired->next, deadline))
  expired->next = deadline;
 return false;
}

void blk_mq_put_rq_ref(struct request *rq)
{
 if (is_flush_rq(rq)) {
  if (rq->end_io(rq, 0) == RQ_END_IO_FREE)
   blk_mq_free_request(rq);
 } else if (req_ref_put_and_test(rq)) {
  __blk_mq_free_request(rq);
 }
}

static bool blk_mq_check_expired(struct request *rq, void *priv)
{
 struct blk_expired_data *expired = priv;

 /*
 * blk_mq_queue_tag_busy_iter() has locked the request, so it cannot
 * be reallocated underneath the timeout handler's processing, then
 * the expire check is reliable. If the request is not expired, then
 * it was completed and reallocated as a new request after returning
 * from blk_mq_check_expired().
 */

 if (blk_mq_req_expired(rq, expired)) {
  expired->has_timedout_rq = true;
  return false;
 }
 return true;
}

static bool blk_mq_handle_expired(struct request *rq, void *priv)
{
 struct blk_expired_data *expired = priv;

 if (blk_mq_req_expired(rq, expired))
  blk_mq_rq_timed_out(rq);
 return true;
}

static void blk_mq_timeout_work(struct work_struct *work)
{
 struct request_queue *q =
  container_of(work, struct request_queue, timeout_work);
 struct blk_expired_data expired = {
  .timeout_start = jiffies,
 };
 struct blk_mq_hw_ctx *hctx;
 unsigned long i;

 /* A deadlock might occur if a request is stuck requiring a
 * timeout at the same time a queue freeze is waiting
 * completion, since the timeout code would not be able to
 * acquire the queue reference here.
 *
 * That's why we don't use blk_queue_enter here; instead, we use
 * percpu_ref_tryget directly, because we need to be able to
 * obtain a reference even in the short window between the queue
 * starting to freeze, by dropping the first reference in
 * blk_freeze_queue_start, and the moment the last request is
 * consumed, marked by the instant q_usage_counter reaches
 * zero.
 */

 if (!percpu_ref_tryget(&q->q_usage_counter))
  return;

 /* check if there is any timed-out request */
 blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &expired);
 if (expired.has_timedout_rq) {
  /*
 * Before walking tags, we must ensure any submit started
 * before the current time has finished. Since the submit
 * uses srcu or rcu, wait for a synchronization point to
 * ensure all running submits have finished
 */

  blk_mq_wait_quiesce_done(q->tag_set);

  expired.next = 0;
  blk_mq_queue_tag_busy_iter(q, blk_mq_handle_expired, &expired);
 }

 if (expired.next != 0) {
  mod_timer(&q->timeout, expired.next);
 } else {
  /*
 * Request timeouts are handled as a forward rolling timer. If
 * we end up here it means that no requests are pending and
 * also that no request has been pending for a while. Mark
 * each hctx as idle.
 */

  queue_for_each_hw_ctx(q, hctx, i) {
   /* the hctx may be unmapped, so check it here */
   if (blk_mq_hw_queue_mapped(hctx))
    blk_mq_tag_idle(hctx);
  }
 }
 blk_queue_exit(q);
}

struct flush_busy_ctx_data {
 struct blk_mq_hw_ctx *hctx;
 struct list_head *list;
};

static bool flush_busy_ctx(struct sbitmap *sb, unsigned int bitnr, void *data)
{
 struct flush_busy_ctx_data *flush_data = data;
 struct blk_mq_hw_ctx *hctx = flush_data->hctx;
 struct blk_mq_ctx *ctx = hctx->ctxs[bitnr];
 enum hctx_type type = hctx->type;

 spin_lock(&ctx->lock);
 list_splice_tail_init(&ctx->rq_lists[type], flush_data->list);
 sbitmap_clear_bit(sb, bitnr);
 spin_unlock(&ctx->lock);
 return true;
}

/*
 * Process software queues that have been marked busy, splicing them
 * to the for-dispatch
 */

void blk_mq_flush_busy_ctxs(struct blk_mq_hw_ctx *hctx, struct list_head *list)
{
 struct flush_busy_ctx_data data = {
  .hctx = hctx,
  .list = list,
 };

 sbitmap_for_each_set(&hctx->ctx_map, flush_busy_ctx, &data);
}

struct dispatch_rq_data {
 struct blk_mq_hw_ctx *hctx;
 struct request *rq;
};

static bool dispatch_rq_from_ctx(struct sbitmap *sb, unsigned int bitnr,
  void *data)
{
 struct dispatch_rq_data *dispatch_data = data;
 struct blk_mq_hw_ctx *hctx = dispatch_data->hctx;
 struct blk_mq_ctx *ctx = hctx->ctxs[bitnr];
 enum hctx_type type = hctx->type;

 spin_lock(&ctx->lock);
 if (!list_empty(&ctx->rq_lists[type])) {
  dispatch_data->rq = list_entry_rq(ctx->rq_lists[type].next);
  list_del_init(&dispatch_data->rq->queuelist);
  if (list_empty(&ctx->rq_lists[type]))
   sbitmap_clear_bit(sb, bitnr);
 }
 spin_unlock(&ctx->lock);

 return !dispatch_data->rq;
}

struct request *blk_mq_dequeue_from_ctx(struct blk_mq_hw_ctx *hctx,
     struct blk_mq_ctx *start)
{
 unsigned off = start ? start->index_hw[hctx->type] : 0;
 struct dispatch_rq_data data = {
  .hctx = hctx,
  .rq   = NULL,
 };

 __sbitmap_for_each_set(&hctx->ctx_map, off,
          dispatch_rq_from_ctx, &data);

 return data.rq;
}

bool __blk_mq_alloc_driver_tag(struct request *rq)
{
 struct sbitmap_queue *bt = &rq->mq_hctx->tags->bitmap_tags;
 unsigned int tag_offset = rq->mq_hctx->tags->nr_reserved_tags;
 int tag;

 blk_mq_tag_busy(rq->mq_hctx);

 if (blk_mq_tag_is_reserved(rq->mq_hctx->sched_tags, rq->internal_tag)) {
  bt = &rq->mq_hctx->tags->breserved_tags;
  tag_offset = 0;
 } else {
  if (!hctx_may_queue(rq->mq_hctx, bt))
   return false;
 }

 tag = __sbitmap_queue_get(bt);
 if (tag == BLK_MQ_NO_TAG)
  return false;

 rq->tag = tag + tag_offset;
 blk_mq_inc_active_requests(rq->mq_hctx);
 return true;
}

static int blk_mq_dispatch_wake(wait_queue_entry_t *wait, unsigned mode,
    int flags, void *key)
{
 struct blk_mq_hw_ctx *hctx;

 hctx = container_of(wait, struct blk_mq_hw_ctx, dispatch_wait);

 spin_lock(&hctx->dispatch_wait_lock);
 if (!list_empty(&wait->entry)) {
  struct sbitmap_queue *sbq;

  list_del_init(&wait->entry);
  sbq = &hctx->tags->bitmap_tags;
  atomic_dec(&sbq->ws_active);
 }
 spin_unlock(&hctx->dispatch_wait_lock);

 blk_mq_run_hw_queue(hctx, true);
 return 1;
}

/*
 * Mark us waiting for a tag. For shared tags, this involves hooking us into
 * the tag wakeups. For non-shared tags, we can simply mark us needing a
 * restart. For both cases, take care to check the condition again after
 * marking us as waiting.
 */

static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx *hctx,
     struct request *rq)
{
 struct sbitmap_queue *sbq;
 struct wait_queue_head *wq;
 wait_queue_entry_t *wait;
 bool ret;

 if (!(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED) &&
     !(blk_mq_is_shared_tags(hctx->flags))) {
  blk_mq_sched_mark_restart_hctx(hctx);

  /*
 * It's possible that a tag was freed in the window between the
 * allocation failure and adding the hardware queue to the wait
 * queue.
 *
 * Don't clear RESTART here, someone else could have set it.
 * At most this will cost an extra queue run.
 */

  return blk_mq_get_driver_tag(rq);
 }

 wait = &hctx->dispatch_wait;
 if (!list_empty_careful(&wait->entry))
  return false;

 if (blk_mq_tag_is_reserved(rq->mq_hctx->sched_tags, rq->internal_tag))
  sbq = &hctx->tags->breserved_tags;
 else
  sbq = &hctx->tags->bitmap_tags;
 wq = &bt_wait_ptr(sbq, hctx)->wait;

 spin_lock_irq(&wq->lock);
 spin_lock(&hctx->dispatch_wait_lock);
 if (!list_empty(&wait->entry)) {
  spin_unlock(&hctx->dispatch_wait_lock);
  spin_unlock_irq(&wq->lock);
  return false;
 }

 atomic_inc(&sbq->ws_active);
 wait->flags &= ~WQ_FLAG_EXCLUSIVE;
 __add_wait_queue(wq, wait);

 /*
 * Add one explicit barrier since blk_mq_get_driver_tag() may
 * not imply barrier in case of failure.
 *
 * Order adding us to wait queue and allocating driver tag.
 *
 * The pair is the one implied in sbitmap_queue_wake_up() which
 * orders clearing sbitmap tag bits and waitqueue_active() in
 * __sbitmap_queue_wake_up(), since waitqueue_active() is lockless
 *
 * Otherwise, re-order of adding wait queue and getting driver tag
 * may cause __sbitmap_queue_wake_up() to wake up nothing because
 * the waitqueue_active() may not observe us in wait queue.
 */

 smp_mb();

 /*
 * It's possible that a tag was freed in the window between the
 * allocation failure and adding the hardware queue to the wait
 * queue.
 */

 ret = blk_mq_get_driver_tag(rq);
 if (!ret) {
  spin_unlock(&hctx->dispatch_wait_lock);
  spin_unlock_irq(&wq->lock);
  return false;
 }

 /*
 * We got a tag, remove ourselves from the wait queue to ensure
 * someone else gets the wakeup.
 */

 list_del_init(&wait->entry);
 atomic_dec(&sbq->ws_active);
 spin_unlock(&hctx->dispatch_wait_lock);
 spin_unlock_irq(&wq->lock);

 return true;
}

#define BLK_MQ_DISPATCH_BUSY_EWMA_WEIGHT  8
#define BLK_MQ_DISPATCH_BUSY_EWMA_FACTOR  4
/*
 * Update dispatch busy with the Exponential Weighted Moving Average(EWMA):
 * - EWMA is one simple way to compute running average value
 * - weight(7/8 and 1/8) is applied so that it can decrease exponentially
 * - take 4 as factor for avoiding to get too small(0) result, and this
 *   factor doesn't matter because EWMA decreases exponentially
 */

static void blk_mq_update_dispatch_busy(struct blk_mq_hw_ctx *hctx, bool busy)
{
 unsigned int ewma;

 ewma = hctx->dispatch_busy;

 if (!ewma && !busy)
  return;

 ewma *= BLK_MQ_DISPATCH_BUSY_EWMA_WEIGHT - 1;
 if (busy)
  ewma += 1 << BLK_MQ_DISPATCH_BUSY_EWMA_FACTOR;
 ewma /= BLK_MQ_DISPATCH_BUSY_EWMA_WEIGHT;

 hctx->dispatch_busy = ewma;
}

#define BLK_MQ_RESOURCE_DELAY 3  /* ms units */

static void blk_mq_handle_dev_resource(struct request *rq,
           struct list_head *list)
{
 list_add(&rq->queuelist, list);
 __blk_mq_requeue_request(rq);
}

enum prep_dispatch {
 PREP_DISPATCH_OK,
 PREP_DISPATCH_NO_TAG,
 PREP_DISPATCH_NO_BUDGET,
};

static enum prep_dispatch blk_mq_prep_dispatch_rq(struct request *rq,
        bool need_budget)
{
 struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
 int budget_token = -1;

 if (need_budget) {
  budget_token = blk_mq_get_dispatch_budget(rq->q);
  if (budget_token < 0) {
   blk_mq_put_driver_tag(rq);
   return PREP_DISPATCH_NO_BUDGET;
  }
  blk_mq_set_rq_budget_token(rq, budget_token);
 }

 if (!blk_mq_get_driver_tag(rq)) {
  /*
 * The initial allocation attempt failed, so we need to
 * rerun the hardware queue when a tag is freed. The
 * waitqueue takes care of that. If the queue is run
 * before we add this entry back on the dispatch list,
 * we'll re-run it below.
 */

  if (!blk_mq_mark_tag_wait(hctx, rq)) {
   /*
 * All budgets not got from this function will be put
 * together during handling partial dispatch
 */

   if (need_budget)
    blk_mq_put_dispatch_budget(rq->q, budget_token);
   return PREP_DISPATCH_NO_TAG;
  }
 }

 return PREP_DISPATCH_OK;
}

/* release all allocated budgets before calling to blk_mq_dispatch_rq_list */
static void blk_mq_release_budgets(struct request_queue *q,
  struct list_head *list)
{
 struct request *rq;

 list_for_each_entry(rq, list, queuelist) {
  int budget_token = blk_mq_get_rq_budget_token(rq);

  if (budget_token >= 0)
   blk_mq_put_dispatch_budget(q, budget_token);
 }
}

/*
 * blk_mq_commit_rqs will notify driver using bd->last that there is no
 * more requests. (See comment in struct blk_mq_ops for commit_rqs for
 * details)
 * Attention, we should explicitly call this in unusual cases:
 *  1) did not queue everything initially scheduled to queue
 *  2) the last attempt to queue a request failed
 */

static void blk_mq_commit_rqs(struct blk_mq_hw_ctx *hctx, int queued,
         bool from_schedule)
{
 if (hctx->queue->mq_ops->commit_rqs && queued) {
  trace_block_unplug(hctx->queue, queued, !from_schedule);
  hctx->queue->mq_ops->commit_rqs(hctx);
 }
}

/*
 * Returns true if we did some work AND can potentially do more.
 */

bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
        bool get_budget)
{
 enum prep_dispatch prep;
 struct request_queue *q = hctx->queue;
 struct request *rq;
 int queued;
 blk_status_t ret = BLK_STS_OK;
 bool needs_resource = false;

 if (list_empty(list))
  return false;

 /*
 * Now process all the entries, sending them to the driver.
 */

 queued = 0;
 do {
  struct blk_mq_queue_data bd;

  rq = list_first_entry(list, struct request, queuelist);

  WARN_ON_ONCE(hctx != rq->mq_hctx);
  prep = blk_mq_prep_dispatch_rq(rq, get_budget);
  if (prep != PREP_DISPATCH_OK)
   break;

  list_del_init(&rq->queuelist);

  bd.rq = rq;
  bd.last = list_empty(list);

  ret = q->mq_ops->queue_rq(hctx, &bd);
  switch (ret) {
  case BLK_STS_OK:
   queued++;
   break;
  case BLK_STS_RESOURCE:
   needs_resource = true;
   fallthrough;
  case BLK_STS_DEV_RESOURCE:
   blk_mq_handle_dev_resource(rq, list);
   goto out;
  default:
   blk_mq_end_request(rq, ret);
  }
 } while (!list_empty(list));
out:
 /* If we didn't flush the entire list, we could have told the driver
 * there was more coming, but that turned out to be a lie.
 */

 if (!list_empty(list) || ret != BLK_STS_OK)
  blk_mq_commit_rqs(hctx, queued, false);

 /*
 * Any items that need requeuing? Stuff them into hctx->dispatch,
 * that is where we will continue on next queue run.
 */

 if (!list_empty(list)) {
  bool needs_restart;
  /* For non-shared tags, the RESTART check will suffice */
  bool no_tag = prep == PREP_DISPATCH_NO_TAG &&
   ((hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED) ||
   blk_mq_is_shared_tags(hctx->flags));

  /*
 * If the caller allocated budgets, free the budgets of the
 * requests that have not yet been passed to the block driver.
 */

  if (!get_budget)
   blk_mq_release_budgets(q, list);

  spin_lock(&hctx->lock);
  list_splice_tail_init(list, &hctx->dispatch);
  spin_unlock(&hctx->lock);

  /*
 * Order adding requests to hctx->dispatch and checking
 * SCHED_RESTART flag. The pair of this smp_mb() is the one
 * in blk_mq_sched_restart(). Avoid restart code path to
 * miss the new added requests to hctx->dispatch, meantime
 * SCHED_RESTART is observed here.
 */

  smp_mb();

  /*
 * If SCHED_RESTART was set by the caller of this function and
 * it is no longer set that means that it was cleared by another
 * thread and hence that a queue rerun is needed.
 *
 * If 'no_tag' is set, that means that we failed getting
 * a driver tag with an I/O scheduler attached. If our dispatch
 * waitqueue is no longer active, ensure that we run the queue
 * AFTER adding our entries back to the list.
 *
 * If no I/O scheduler has been configured it is possible that
 * the hardware queue got stopped and restarted before requests
 * were pushed back onto the dispatch list. Rerun the queue to
 * avoid starvation. Notes:
 * - blk_mq_run_hw_queue() checks whether or not a queue has
 *   been stopped before rerunning a queue.
 * - Some but not all block drivers stop a queue before
 *   returning BLK_STS_RESOURCE. Two exceptions are scsi-mq
 *   and dm-rq.
 *
 * If driver returns BLK_STS_RESOURCE and SCHED_RESTART
 * bit is set, run queue after a delay to avoid IO stalls
 * that could otherwise occur if the queue is idle.  We'll do
 * similar if we couldn't get budget or couldn't lock a zone
 * and SCHED_RESTART is set.
 */

  needs_restart = blk_mq_sched_needs_restart(hctx);
  if (prep == PREP_DISPATCH_NO_BUDGET)
   needs_resource = true;
  if (!needs_restart ||
      (no_tag && list_empty_careful(&hctx->dispatch_wait.entry)))
   blk_mq_run_hw_queue(hctx, true);
  else if (needs_resource)
   blk_mq_delay_run_hw_queue(hctx, BLK_MQ_RESOURCE_DELAY);

  blk_mq_update_dispatch_busy(hctx, true);
  return false;
 }

 blk_mq_update_dispatch_busy(hctx, false);
 return true;
}

static inline int blk_mq_first_mapped_cpu(struct blk_mq_hw_ctx *hctx)
{
 int cpu = cpumask_first_and(hctx->cpumask, cpu_online_mask);

 if (cpu >= nr_cpu_ids)
  cpu = cpumask_first(hctx->cpumask);
 return cpu;
}

/*
 * ->next_cpu is always calculated from hctx->cpumask, so simply use
 * it for speeding up the check
 */

static bool blk_mq_hctx_empty_cpumask(struct blk_mq_hw_ctx *hctx)
{
        return hctx->next_cpu >= nr_cpu_ids;
}

/*
 * It'd be great if the workqueue API had a way to pass
 * in a mask and had some smarts for more clever placement.
 * For now we just round-robin here, switching for every
 * BLK_MQ_CPU_WORK_BATCH queued items.
 */

static int blk_mq_hctx_next_cpu(struct blk_mq_hw_ctx *hctx)
{
 bool tried = false;
 int next_cpu = hctx->next_cpu;

 /* Switch to unbound if no allowable CPUs in this hctx */
 if (hctx->queue->nr_hw_queues == 1 || blk_mq_hctx_empty_cpumask(hctx))
  return WORK_CPU_UNBOUND;

 if (--hctx->next_cpu_batch <= 0) {
select_cpu:
  next_cpu = cpumask_next_and(next_cpu, hctx->cpumask,
    cpu_online_mask);
  if (next_cpu >= nr_cpu_ids)
   next_cpu = blk_mq_first_mapped_cpu(hctx);
  hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH;
 }

 /*
 * Do unbound schedule if we can't find a online CPU for this hctx,
 * and it should only happen in the path of handling CPU DEAD.
 */

 if (!cpu_online(next_cpu)) {
  if (!tried) {
   tried = true;
   goto select_cpu;
  }

  /*
 * Make sure to re-select CPU next time once after CPUs
 * in hctx->cpumask become online again.
 */

  hctx->next_cpu = next_cpu;
  hctx->next_cpu_batch = 1;
  return WORK_CPU_UNBOUND;
 }

 hctx->next_cpu = next_cpu;
 return next_cpu;
}

/**
 * blk_mq_delay_run_hw_queue - Run a hardware queue asynchronously.
 * @hctx: Pointer to the hardware queue to run.
 * @msecs: Milliseconds of delay to wait before running the queue.
 *
 * Run a hardware queue asynchronously with a delay of @msecs.
 */

void blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
{
 if (unlikely(blk_mq_hctx_stopped(hctx)))
  return;
 kblockd_mod_delayed_work_on(blk_mq_hctx_next_cpu(hctx), &hctx->run_work,
        msecs_to_jiffies(msecs));
}
EXPORT_SYMBOL(blk_mq_delay_run_hw_queue);

static inline bool blk_mq_hw_queue_need_run(struct blk_mq_hw_ctx *hctx)
{
 bool need_run;

 /*
 * When queue is quiesced, we may be switching io scheduler, or
 * updating nr_hw_queues, or other things, and we can't run queue
 * any more, even blk_mq_hctx_has_pending() can't be called safely.
 *
 * And queue will be rerun in blk_mq_unquiesce_queue() if it is
 * quiesced.
 */

 __blk_mq_run_dispatch_ops(hctx->queue, false,
  need_run = !blk_queue_quiesced(hctx->queue) &&
  blk_mq_hctx_has_pending(hctx));
 return need_run;
}

/**
 * blk_mq_run_hw_queue - Start to run a hardware queue.
 * @hctx: Pointer to the hardware queue to run.
 * @async: If we want to run the queue asynchronously.
 *
 * Check if the request queue is not in a quiesced state and if there are
 * pending requests to be sent. If this is true, run the queue to send requests
 * to hardware.
 */

void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
{
 bool need_run;

 /*
 * We can't run the queue inline with interrupts disabled.
 */

 WARN_ON_ONCE(!async && in_interrupt());

 might_sleep_if(!async && hctx->flags & BLK_MQ_F_BLOCKING);

 need_run = blk_mq_hw_queue_need_run(hctx);
 if (!need_run) {
  unsigned long flags;

  /*
 * Synchronize with blk_mq_unquiesce_queue(), because we check
 * if hw queue is quiesced locklessly above, we need the use
 * ->queue_lock to make sure we see the up-to-date status to
 * not miss rerunning the hw queue.
 */

  spin_lock_irqsave(&hctx->queue->queue_lock, flags);
  need_run = blk_mq_hw_queue_need_run(hctx);
  spin_unlock_irqrestore(&hctx->queue->queue_lock, flags);

  if (!need_run)
   return;
 }

 if (async || !cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask)) {
  blk_mq_delay_run_hw_queue(hctx, 0);
  return;
 }

 blk_mq_run_dispatch_ops(hctx->queue,
    blk_mq_sched_dispatch_requests(hctx));
}
EXPORT_SYMBOL(blk_mq_run_hw_queue);

/*
 * Return prefered queue to dispatch from (if any) for non-mq aware IO
 * scheduler.
 */

static struct blk_mq_hw_ctx *blk_mq_get_sq_hctx(struct request_queue *q)
{
 struct blk_mq_ctx *ctx = blk_mq_get_ctx(q);
 /*
 * If the IO scheduler does not respect hardware queues when
 * dispatching, we just don't bother with multiple HW queues and
 * dispatch from hctx for the current CPU since running multiple queues
 * just causes lock contention inside the scheduler and pointless cache
 * bouncing.
 */

 struct blk_mq_hw_ctx *hctx = ctx->hctxs[HCTX_TYPE_DEFAULT];

 if (!blk_mq_hctx_stopped(hctx))
  return hctx;
 return NULL;
}

/**
 * blk_mq_run_hw_queues - Run all hardware queues in a request queue.
 * @q: Pointer to the request queue to run.
 * @async: If we want to run the queue asynchronously.
 */

void blk_mq_run_hw_queues(struct request_queue *q, bool async)
{
 struct blk_mq_hw_ctx *hctx, *sq_hctx;
 unsigned long i;

 sq_hctx = NULL;
 if (blk_queue_sq_sched(q))
  sq_hctx = blk_mq_get_sq_hctx(q);
 queue_for_each_hw_ctx(q, hctx, i) {
  if (blk_mq_hctx_stopped(hctx))
   continue;
  /*
 * Dispatch from this hctx either if there's no hctx preferred
 * by IO scheduler or if it has requests that bypass the
 * scheduler.
 */

  if (!sq_hctx || sq_hctx == hctx ||
      !list_empty_careful(&hctx->dispatch))
   blk_mq_run_hw_queue(hctx, async);
 }
}
EXPORT_SYMBOL(blk_mq_run_hw_queues);

/**
 * blk_mq_delay_run_hw_queues - Run all hardware queues asynchronously.
 * @q: Pointer to the request queue to run.
 * @msecs: Milliseconds of delay to wait before running the queues.
 */

void blk_mq_delay_run_hw_queues(struct request_queue *q, unsigned long msecs)
{
 struct blk_mq_hw_ctx *hctx, *sq_hctx;
 unsigned long i;

 sq_hctx = NULL;
 if (blk_queue_sq_sched(q))
  sq_hctx = blk_mq_get_sq_hctx(q);
 queue_for_each_hw_ctx(q, hctx, i) {
  if (blk_mq_hctx_stopped(hctx))
   continue;
  /*
 * If there is already a run_work pending, leave the
 * pending delay untouched. Otherwise, a hctx can stall
 * if another hctx is re-delaying the other's work
 * before the work executes.
 */

  if (delayed_work_pending(&hctx->run_work))
   continue;
  /*
 * Dispatch from this hctx either if there's no hctx preferred
 * by IO scheduler or if it has requests that bypass the
 * scheduler.
 */

  if (!sq_hctx || sq_hctx == hctx ||
      !list_empty_careful(&hctx->dispatch))
   blk_mq_delay_run_hw_queue(hctx, msecs);
 }
}
EXPORT_SYMBOL(blk_mq_delay_run_hw_queues);

/*
 * This function is often used for pausing .queue_rq() by driver when
 * there isn't enough resource or some conditions aren't satisfied, and
 * BLK_STS_RESOURCE is usually returned.
 *
 * We do not guarantee that dispatch can be drained or blocked
 * after blk_mq_stop_hw_queue() returns. Please use
 * blk_mq_quiesce_queue() for that requirement.
 */

void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx)
{
 cancel_delayed_work(&hctx->run_work);

 set_bit(BLK_MQ_S_STOPPED, &hctx->state);
}
EXPORT_SYMBOL(blk_mq_stop_hw_queue);

/*
 * This function is often used for pausing .queue_rq() by driver when
 * there isn't enough resource or some conditions aren't satisfied, and
 * BLK_STS_RESOURCE is usually returned.
 *
 * We do not guarantee that dispatch can be drained or blocked
 * after blk_mq_stop_hw_queues() returns. Please use
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.63 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.