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.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Diese beiden folgenden Angebotsgruppen bietet das Unternehmen

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.