/* SPDX-License-Identifier: GPL-2.0 */
#ifndef BLK_MQ_H
#define BLK_MQ_H
#include <linux/blkdev.h>
#include <linux/sbitmap.h>
#include <linux/lockdep.h>
#include <linux/scatterlist.h>
#include <linux/prefetch.h>
#include <linux/srcu.h>
#include <linux/rw_hint.h>
struct blk_mq_tags;
struct blk_flush_queue;
#define BLKDEV_MIN_RQ 4
#define BLKDEV_DEFAULT_RQ 128
enum rq_end_io_ret {
RQ_END_IO_NONE,
RQ_END_IO_FREE,
};
typedef enum rq_end_io_ret (rq_end_io_fn)(struct request *, blk_status_t);
/*
* request flags */
typedef __u32 __bitwise req_flags_t;
/* Keep rqf_name[] in sync with the definitions below */
enum {
/* drive already may have started this one */
__RQF_STARTED,
/* request for flush sequence */
__RQF_FLUSH_SEQ,
/* merge of different types, fail separately */
__RQF_MIXED_MERGE,
/* don't call prep for this one */
__RQF_DONTPREP,
/* use hctx->sched_tags */
__RQF_SCHED_TAGS,
/* use an I/O scheduler for this request */
__RQF_USE_SCHED,
/* vaguely specified driver internal error. Ignored by block layer */
__RQF_FAILED,
/* don't warn about errors */
__RQF_QUIET,
/* account into disk and partition IO statistics */
__RQF_IO_STAT,
/* runtime pm request */
__RQF_PM,
/* on IO scheduler merge hash */
__RQF_HASHED,
/* track IO completion time */
__RQF_STATS,
/* Look at ->special_vec for the actual data payload instead of the
bio chain. */
__RQF_SPECIAL_PAYLOAD,
/* request completion needs to be signaled to zone write plugging. */
__RQF_ZONE_WRITE_PLUGGING,
/* ->timeout has been called, don't expire again */
__RQF_TIMED_OUT,
__RQF_RESV,
__RQF_BITS
};
#define RQF_STARTED ((__force req_flags_t)(1 << __RQF_STARTED))
#define RQF_FLUSH_SEQ ((__force req_flags_t)(1 << __RQF_FLUSH_SEQ))
#define RQF_MIXED_MERGE ((__force req_flags_t)(1 << __RQF_MIXED_MERGE))
#define RQF_DONTPREP ((__force req_flags_t)(1 << __RQF_DONTPREP))
#define RQF_SCHED_TAGS ((__force req_flags_t)(1 << __RQF_SCHED_TAGS))
#define RQF_USE_SCHED ((__force req_flags_t)(1 << __RQF_USE_SCHED))
#define RQF_FAILED ((__force req_flags_t)(1 << __RQF_FAILED))
#define RQF_QUIET ((__force req_flags_t)(1 << __RQF_QUIET))
#define RQF_IO_STAT ((__force req_flags_t)(1 << __RQF_IO_STAT))
#define RQF_PM ((__force req_flags_t)(1 << __RQF_PM))
#define RQF_HASHED ((__force req_flags_t)(1 << __RQF_HASHED))
#define RQF_STATS ((__force req_flags_t)(1 << __RQF_STATS))
#define RQF_SPECIAL_PAYLOAD \
((__force req_flags_t)(1 << __RQF_SPECIAL_PAYLOAD))
#define RQF_ZONE_WRITE_PLUGGING \
((__force req_flags_t)(1 << __RQF_ZONE_WRITE_PLUGGING))
#define RQF_TIMED_OUT ((__force req_flags_t)(1 << __RQF_TIMED_OUT))
#define RQF_RESV ((__force req_flags_t)(1 << __RQF_RESV))
/* flags that prevent us from merging requests: */
#define RQF_NOMERGE_FLAGS \
(RQF_STARTED | RQF_FLUSH_SEQ | RQF_SPECIAL_PAYLOAD)
enum mq_rq_state {
MQ_RQ_IDLE = 0,
MQ_RQ_IN_FLIGHT = 1,
MQ_RQ_COMPLETE = 2,
};
/*
* Try to put the fields that are referenced together in the same cacheline.
*
* If you modify this structure, make sure to update blk_rq_init() and
* especially blk_mq_rq_ctx_init() to take care of the added fields.
*/
struct request {
struct request_queue *q;
struct blk_mq_ctx *mq_ctx;
struct blk_mq_hw_ctx *mq_hctx;
blk_opf_t cmd_flags; /* op and common flags */
req_flags_t rq_flags;
int tag;
int internal_tag;
unsigned int timeout;
/* the following two fields are internal, NEVER access directly */
unsigned int __data_len; /* total data len */
sector_t __sector; /* sector cursor */
struct bio *bio;
struct bio *biotail;
union {
struct list_head queuelist;
struct request *rq_next;
};
struct block_device *part;
#ifdef CONFIG_BLK_RQ_ALLOC_TIME
/* Time that the first bio started allocating this request. */
u64 alloc_time_ns;
#endif
/* Time that this request was allocated for this IO. */
u64 start_time_ns;
/* Time that I/O was submitted to the device. */
u64 io_start_time_ns;
#ifdef CONFIG_BLK_WBT
unsigned short wbt_flags;
#endif
/*
* rq sectors used for blk stats. It has the same value
* with blk_rq_sectors(rq), except that it never be zeroed
* by completion.
*/
unsigned short stats_sectors;
/*
* Number of scatter-gather DMA addr+len pairs after
* physical address coalescing is performed.
*/
unsigned short nr_phys_segments;
unsigned short nr_integrity_segments;
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
struct bio_crypt_ctx *crypt_ctx;
struct blk_crypto_keyslot *crypt_keyslot;
#endif
enum rw_hint write_hint;
unsigned short ioprio;
enum mq_rq_state state;
atomic_t ref;
unsigned long deadline;
/*
* The hash is used inside the scheduler, and killed once the
* request reaches the dispatch list. The ipi_list is only used
* to queue the request for softirq completion, which is long
* after the request has been unhashed (and even removed from
* the dispatch list).
*/
union {
struct hlist_node hash; /* merge hash */
struct llist_node ipi_list;
};
/*
* The rb_node is only used inside the io scheduler, requests
* are pruned when moved to the dispatch queue. special_vec must
* only be used if RQF_SPECIAL_PAYLOAD is set, and those cannot be
* insert into an IO scheduler.
*/
union {
struct rb_node rb_node; /* sort/lookup */
struct bio_vec special_vec;
};
/*
* Three pointers are available for the IO schedulers, if they need
* more they have to dynamically allocate it.
*/
struct {
struct io_cq *icq;
void *priv[2];
} elv;
struct {
unsigned int seq;
rq_end_io_fn *saved_end_io;
} flush;
u64 fifo_time;
/*
* completion callback.
*/
rq_end_io_fn *end_io;
void *end_io_data;
};
static inline enum req_op req_op(const struct request *req)
{
return req->cmd_flags & REQ_OP_MASK;
}
static inline bool blk_rq_is_passthrough(struct request *rq)
{
return blk_op_is_passthrough(rq->cmd_flags);
}
static inline unsigned short req_get_ioprio(struct request *req)
{
return req->ioprio;
}
#define rq_data_dir(rq) (op_is_write(req_op(rq)) ? WRITE : READ)
#define rq_dm