2017-11-01 15:07:57 +01:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2008-01-29 14:51:59 +01:00
|
|
|
#ifndef BLK_INTERNAL_H
|
|
|
|
|
#define BLK_INTERNAL_H
|
|
|
|
|
|
2024-07-02 17:10:19 +02:00
|
|
|
#include <linux/bio-integrity.h>
|
2020-05-14 00:37:18 +00:00
|
|
|
#include <linux/blk-crypto.h>
|
2024-10-25 08:37:20 +08:00
|
|
|
#include <linux/lockdep.h>
|
2021-03-31 09:30:00 +02:00
|
|
|
#include <linux/memblock.h> /* for max_pfn/max_low_pfn */
|
2024-02-23 07:59:09 -08:00
|
|
|
#include <linux/sched/sysctl.h>
|
2024-01-15 14:45:07 -07:00
|
|
|
#include <linux/timekeeping.h>
|
2018-09-25 13:30:08 -07:00
|
|
|
#include <xen/xen.h>
|
2020-05-14 00:37:18 +00:00
|
|
|
#include "blk-crypto-internal.h"
|
2011-12-14 00:33:37 +01:00
|
|
|
|
2025-11-13 14:28:18 +05:30
|
|
|
struct elv_change_ctx;
|
2021-09-20 14:33:23 +02:00
|
|
|
|
2025-06-18 15:00:45 +09:00
|
|
|
/*
|
|
|
|
|
* Default upper limit for the software max_sectors limit used for regular I/Os.
|
|
|
|
|
* This can be increased through sysfs.
|
|
|
|
|
*
|
|
|
|
|
* This should not be confused with the max_hw_sector limit that is entirely
|
|
|
|
|
* controlled by the block device driver, usually based on hardware limits.
|
|
|
|
|
*/
|
|
|
|
|
#define BLK_DEF_MAX_SECTORS_CAP (SZ_4M >> SECTOR_SHIFT)
|
|
|
|
|
|
2025-01-15 17:26:48 +08:00
|
|
|
#define BLK_DEV_MAX_SECTORS (LLONG_MAX >> 9)
|
2025-02-25 10:21:41 +08:00
|
|
|
#define BLK_MIN_SEGMENT_SIZE 4096
|
2025-01-15 17:26:48 +08:00
|
|
|
|
2014-05-13 15:10:52 -06:00
|
|
|
/* Max future timer expiry for timeouts */
|
|
|
|
|
#define BLK_MAX_TIMEOUT (5 * HZ)
|
|
|
|
|
|
2025-08-08 13:36:09 +08:00
|
|
|
extern const struct kobj_type blk_queue_ktype;
|
2017-01-31 14:53:20 -08:00
|
|
|
extern struct dentry *blk_debugfs_root;
|
|
|
|
|
|
2014-09-25 23:23:43 +08:00
|
|
|
struct blk_flush_queue {
|
2023-07-17 12:00:57 +08:00
|
|
|
spinlock_t mq_flush_lock;
|
2014-09-25 23:23:43 +08:00
|
|
|
unsigned int flush_pending_idx:1;
|
|
|
|
|
unsigned int flush_running_idx:1;
|
2019-09-27 16:19:55 +08:00
|
|
|
blk_status_t rq_status;
|
2014-09-25 23:23:43 +08:00
|
|
|
unsigned long flush_pending_since;
|
|
|
|
|
struct list_head flush_queue[2];
|
2023-07-17 12:00:57 +08:00
|
|
|
unsigned long flush_data_in_flight;
|
2014-09-25 23:23:43 +08:00
|
|
|
struct request *flush_rq;
|
2025-08-30 10:18:22 +08:00
|
|
|
struct rcu_head rcu_head;
|
2014-09-25 23:23:43 +08:00
|
|
|
};
|
|
|
|
|
|
2021-08-18 09:09:25 +08:00
|
|
|
bool is_flush_rq(struct request *req);
|
2019-09-27 16:19:55 +08:00
|
|
|
|
2020-03-09 22:41:37 +01:00
|
|
|
struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
|
|
|
|
|
gfp_t flags);
|
2014-09-25 23:23:47 +08:00
|
|
|
void blk_free_flush_queue(struct blk_flush_queue *q);
|
2014-09-25 23:23:40 +08:00
|
|
|
|
2024-10-25 08:37:20 +08:00
|
|
|
bool __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic);
|
|
|
|
|
bool blk_queue_start_drain(struct request_queue *q);
|
2024-10-31 21:37:19 +08:00
|
|
|
bool __blk_freeze_queue_start(struct request_queue *q,
|
|
|
|
|
struct task_struct *owner);
|
2021-11-04 12:45:51 -06:00
|
|
|
int __bio_queue_enter(struct request_queue *q, struct bio *bio);
|
2025-09-10 14:30:55 +08:00
|
|
|
void submit_bio_noacct_nocheck(struct bio *bio, bool split);
|
2026-04-07 16:05:27 +02:00
|
|
|
int bio_submit_or_kill(struct bio *bio, unsigned int flags);
|
2021-11-04 12:45:51 -06:00
|
|
|
|
|
|
|
|
static inline bool blk_try_enter_queue(struct request_queue *q, bool pm)
|
|
|
|
|
{
|
|
|
|
|
rcu_read_lock();
|
|
|
|
|
if (!percpu_ref_tryget_live_rcu(&q->q_usage_counter))
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The code that increments the pm_only counter must ensure that the
|
|
|
|
|
* counter is globally visible before the queue is unfrozen.
|
|
|
|
|
*/
|
|
|
|
|
if (blk_queue_pm_only(q) &&
|
|
|
|
|
(!pm || queue_rpm_status(q) == RPM_SUSPENDED))
|
|
|
|
|
goto fail_put;
|
|
|
|
|
|
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
fail_put:
|
|
|
|
|
blk_queue_exit(q);
|
|
|
|
|
fail:
|
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int bio_queue_enter(struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
struct request_queue *q = bdev_get_queue(bio->bi_bdev);
|
|
|
|
|
|
2024-10-25 08:37:20 +08:00
|
|
|
if (blk_try_enter_queue(q, false)) {
|
|
|
|
|
rwsem_acquire_read(&q->io_lockdep_map, 0, 0, _RET_IP_);
|
|
|
|
|
rwsem_release(&q->io_lockdep_map, _RET_IP_);
|
2021-11-04 12:45:51 -06:00
|
|
|
return 0;
|
2024-10-25 08:37:20 +08:00
|
|
|
}
|
2021-11-04 12:45:51 -06:00
|
|
|
return __bio_queue_enter(q, bio);
|
|
|
|
|
}
|
2015-10-21 13:20:12 -04:00
|
|
|
|
2024-02-23 07:59:09 -08:00
|
|
|
static inline void blk_wait_io(struct completion *done)
|
|
|
|
|
{
|
|
|
|
|
/* Prevent hang_check timer from firing at us during very long I/O */
|
|
|
|
|
unsigned long timeout = sysctl_hung_task_timeout_secs * HZ / 2;
|
|
|
|
|
|
|
|
|
|
if (timeout)
|
|
|
|
|
while (!wait_for_completion_io_timeout(done, timeout))
|
|
|
|
|
;
|
|
|
|
|
else
|
|
|
|
|
wait_for_completion_io(done);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-23 07:37:41 +02:00
|
|
|
struct block_device *blkdev_get_no_open(dev_t dev, bool autoload);
|
2025-04-23 07:37:39 +02:00
|
|
|
void blkdev_put_no_open(struct block_device *bdev);
|
|
|
|
|
|
2023-08-03 11:48:27 +09:00
|
|
|
bool bvec_try_merge_hw_page(struct request_queue *q, struct bio_vec *bv,
|
2025-05-12 06:23:54 +02:00
|
|
|
struct page *page, unsigned len, unsigned offset);
|
2023-08-03 11:48:27 +09:00
|
|
|
|
2018-09-24 09:43:52 +02:00
|
|
|
static inline bool biovec_phys_mergeable(struct request_queue *q,
|
|
|
|
|
struct bio_vec *vec1, struct bio_vec *vec2)
|
2018-09-24 09:43:50 +02:00
|
|
|
{
|
2018-09-24 09:43:52 +02:00
|
|
|
unsigned long mask = queue_segment_boundary(q);
|
2024-07-06 09:52:17 +02:00
|
|
|
phys_addr_t addr1 = bvec_phys(vec1);
|
|
|
|
|
phys_addr_t addr2 = bvec_phys(vec2);
|
2018-09-24 09:43:52 +02:00
|
|
|
|
2022-09-15 17:04:01 +02:00
|
|
|
/*
|
|
|
|
|
* Merging adjacent physical pages may not work correctly under KMSAN
|
|
|
|
|
* if their metadata pages aren't adjacent. Just disable merging.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_ENABLED(CONFIG_KMSAN))
|
|
|
|
|
return false;
|
|
|
|
|
|
2018-09-24 09:43:52 +02:00
|
|
|
if (addr1 + vec1->bv_len != addr2)
|
2018-09-24 09:43:50 +02:00
|
|
|
return false;
|
2026-04-10 15:34:13 +00:00
|
|
|
if (!zone_device_pages_have_same_pgmap(vec1->bv_page, vec2->bv_page))
|
|
|
|
|
return false;
|
2019-03-29 15:07:54 +08:00
|
|
|
if (xen_domain() && !xen_biovec_phys_mergeable(vec1, vec2->bv_page))
|
2018-09-24 09:43:50 +02:00
|
|
|
return false;
|
2018-09-24 09:43:52 +02:00
|
|
|
if ((addr1 | mask) != ((addr2 + vec2->bv_len - 1) | mask))
|
|
|
|
|
return false;
|
2018-09-24 09:43:50 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-10 15:34:14 +00:00
|
|
|
/*
|
|
|
|
|
* Check if two pages from potentially different zone device pgmaps can
|
|
|
|
|
* coexist as separate bvec entries in the same bio.
|
|
|
|
|
*
|
|
|
|
|
* The block DMA iterator (blk_dma_map_iter_start) caches the P2PDMA mapping
|
|
|
|
|
* state from the first segment and applies it to all subsequent segments, so
|
|
|
|
|
* P2PDMA pages from different pgmaps must not be mixed in the same bio.
|
|
|
|
|
*
|
|
|
|
|
* Other zone device types (FS_DAX, GENERIC) use the same dma_map_phys() path
|
|
|
|
|
* as normal RAM. PRIVATE and COHERENT pages never appear in bios.
|
|
|
|
|
*/
|
|
|
|
|
static inline bool zone_device_pages_compatible(const struct page *a,
|
|
|
|
|
const struct page *b)
|
|
|
|
|
{
|
|
|
|
|
if (is_pci_p2pdma_page(a) || is_pci_p2pdma_page(b))
|
|
|
|
|
return zone_device_pages_have_same_pgmap(a, b);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-25 12:17:54 -07:00
|
|
|
static inline bool __bvec_gap_to_prev(const struct queue_limits *lim,
|
2018-09-24 09:43:49 +02:00
|
|
|
struct bio_vec *bprv, unsigned int offset)
|
|
|
|
|
{
|
2022-07-27 12:23:00 -04:00
|
|
|
return (offset & lim->virt_boundary_mask) ||
|
|
|
|
|
((bprv->bv_offset + bprv->bv_len) & lim->virt_boundary_mask);
|
2018-09-24 09:43:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check if adding a bio_vec after bprv with offset would create a gap in
|
|
|
|
|
* the SG list. Most drivers don't care about this, but some do.
|
|
|
|
|
*/
|
2022-10-25 12:17:54 -07:00
|
|
|
static inline bool bvec_gap_to_prev(const struct queue_limits *lim,
|
2018-09-24 09:43:49 +02:00
|
|
|
struct bio_vec *bprv, unsigned int offset)
|
|
|
|
|
{
|
2022-07-27 12:23:00 -04:00
|
|
|
if (!lim->virt_boundary_mask)
|
2018-09-24 09:43:49 +02:00
|
|
|
return false;
|
2022-07-27 12:23:00 -04:00
|
|
|
return __bvec_gap_to_prev(lim, bprv, offset);
|
2018-09-24 09:43:49 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-20 14:33:26 +02:00
|
|
|
static inline bool rq_mergeable(struct request *rq)
|
|
|
|
|
{
|
|
|
|
|
if (blk_rq_is_passthrough(rq))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (req_op(rq) == REQ_OP_FLUSH)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (req_op(rq) == REQ_OP_WRITE_ZEROES)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (req_op(rq) == REQ_OP_ZONE_APPEND)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (rq->cmd_flags & REQ_NOMERGE_FLAGS)
|
|
|
|
|
return false;
|
|
|
|
|
if (rq->rq_flags & RQF_NOMERGE_FLAGS)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* There are two different ways to handle DISCARD merges:
|
|
|
|
|
* 1) If max_discard_segments > 1, the driver treats every bio as a range and
|
|
|
|
|
* send the bios to controller together. The ranges don't need to be
|
|
|
|
|
* contiguous.
|
|
|
|
|
* 2) Otherwise, the request will be normal read/write requests. The ranges
|
|
|
|
|
* need to be contiguous.
|
|
|
|
|
*/
|
|
|
|
|
static inline bool blk_discard_mergable(struct request *req)
|
|
|
|
|
{
|
|
|
|
|
if (req_op(req) == REQ_OP_DISCARD &&
|
|
|
|
|
queue_max_discard_segments(req->q) > 1)
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-28 17:06:55 -07:00
|
|
|
static inline unsigned int blk_rq_get_max_segments(struct request *rq)
|
|
|
|
|
{
|
|
|
|
|
if (req_op(rq) == REQ_OP_DISCARD)
|
|
|
|
|
return queue_max_discard_segments(rq->q);
|
|
|
|
|
return queue_max_segments(rq->q);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-20 12:53:50 +00:00
|
|
|
static inline unsigned int blk_queue_get_max_sectors(struct request *rq)
|
2022-06-14 11:09:34 +02:00
|
|
|
{
|
2024-06-20 12:53:50 +00:00
|
|
|
struct request_queue *q = rq->q;
|
|
|
|
|
enum req_op op = req_op(rq);
|
|
|
|
|
|
2026-02-04 11:40:02 +08:00
|
|
|
if (unlikely(op == REQ_OP_DISCARD))
|
2022-06-14 11:09:34 +02:00
|
|
|
return min(q->limits.max_discard_sectors,
|
|
|
|
|
UINT_MAX >> SECTOR_SHIFT);
|
|
|
|
|
|
2026-02-04 11:40:02 +08:00
|
|
|
if (unlikely(op == REQ_OP_SECURE_ERASE))
|
|
|
|
|
return min(q->limits.max_secure_erase_sectors,
|
|
|
|
|
UINT_MAX >> SECTOR_SHIFT);
|
|
|
|
|
|
2022-06-14 11:09:34 +02:00
|
|
|
if (unlikely(op == REQ_OP_WRITE_ZEROES))
|
|
|
|
|
return q->limits.max_write_zeroes_sectors;
|
|
|
|
|
|
2024-06-20 12:53:54 +00:00
|
|
|
if (rq->cmd_flags & REQ_ATOMIC)
|
|
|
|
|
return q->limits.atomic_write_max_sectors;
|
|
|
|
|
|
2022-06-14 11:09:34 +02:00
|
|
|
return q->limits.max_sectors;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-21 13:20:23 -04:00
|
|
|
#ifdef CONFIG_BLK_DEV_INTEGRITY
|
|
|
|
|
void blk_flush_integrity(void);
|
2019-12-05 10:09:01 +08:00
|
|
|
void bio_integrity_free(struct bio *bio);
|
2024-07-02 17:10:23 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Integrity payloads can either be owned by the submitter, in which case
|
|
|
|
|
* bio_uninit will free them, or owned and generated by the block layer,
|
|
|
|
|
* in which case we'll verify them here (for reads) and free them before
|
|
|
|
|
* the bio is handed back to the submitted.
|
|
|
|
|
*/
|
|
|
|
|
bool __bio_integrity_endio(struct bio *bio);
|
2017-07-03 16:58:43 -06:00
|
|
|
static inline bool bio_integrity_endio(struct bio *bio)
|
|
|
|
|
{
|
2024-07-02 17:10:23 +02:00
|
|
|
struct bio_integrity_payload *bip = bio_integrity(bio);
|
|
|
|
|
|
|
|
|
|
if (bip && (bip->bip_flags & BIP_BLOCK_INTEGRITY))
|
2017-07-03 16:58:43 -06:00
|
|
|
return __bio_integrity_endio(bio);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-09-24 09:43:47 +02:00
|
|
|
|
2020-10-06 09:07:17 +02:00
|
|
|
bool blk_integrity_merge_rq(struct request_queue *, struct request *,
|
|
|
|
|
struct request *);
|
2020-10-06 09:07:18 +02:00
|
|
|
bool blk_integrity_merge_bio(struct request_queue *, struct request *,
|
|
|
|
|
struct bio *);
|
2020-10-06 09:07:17 +02:00
|
|
|
|
2018-09-24 09:43:47 +02:00
|
|
|
static inline bool integrity_req_gap_back_merge(struct request *req,
|
|
|
|
|
struct bio *next)
|
|
|
|
|
{
|
|
|
|
|
struct bio_integrity_payload *bip = bio_integrity(req->bio);
|
|
|
|
|
struct bio_integrity_payload *bip_next = bio_integrity(next);
|
|
|
|
|
|
2022-07-27 12:23:00 -04:00
|
|
|
return bvec_gap_to_prev(&req->q->limits,
|
|
|
|
|
&bip->bip_vec[bip->bip_vcnt - 1],
|
2018-09-24 09:43:47 +02:00
|
|
|
bip_next->bip_vec[0].bv_offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool integrity_req_gap_front_merge(struct request *req,
|
|
|
|
|
struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
struct bio_integrity_payload *bip = bio_integrity(bio);
|
|
|
|
|
struct bio_integrity_payload *bip_next = bio_integrity(req->bio);
|
|
|
|
|
|
2022-07-27 12:23:00 -04:00
|
|
|
return bvec_gap_to_prev(&req->q->limits,
|
|
|
|
|
&bip->bip_vec[bip->bip_vcnt - 1],
|
2018-09-24 09:43:47 +02:00
|
|
|
bip_next->bip_vec[0].bv_offset);
|
|
|
|
|
}
|
2020-03-25 16:48:41 +01:00
|
|
|
|
2023-03-18 17:36:25 +00:00
|
|
|
extern const struct attribute_group blk_integrity_attr_group;
|
2018-09-24 09:43:47 +02:00
|
|
|
#else /* CONFIG_BLK_DEV_INTEGRITY */
|
2020-10-06 09:07:17 +02:00
|
|
|
static inline bool blk_integrity_merge_rq(struct request_queue *rq,
|
|
|
|
|
struct request *r1, struct request *r2)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-10-06 09:07:18 +02:00
|
|
|
static inline bool blk_integrity_merge_bio(struct request_queue *rq,
|
|
|
|
|
struct request *r, struct bio *b)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-09-24 09:43:47 +02:00
|
|
|
static inline bool integrity_req_gap_back_merge(struct request *req,
|
|
|
|
|
struct bio *next)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
static inline bool integrity_req_gap_front_merge(struct request *req,
|
|
|
|
|
struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-21 13:20:23 -04:00
|
|
|
static inline void blk_flush_integrity(void)
|
|
|
|
|
{
|
|
|
|
|
}
|
2017-07-03 16:58:43 -06:00
|
|
|
static inline bool bio_integrity_endio(struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2019-12-05 10:09:01 +08:00
|
|
|
static inline void bio_integrity_free(struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
}
|
2018-09-24 09:43:47 +02:00
|
|
|
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
2008-01-29 14:51:59 +01:00
|
|
|
|
2014-05-13 15:10:52 -06:00
|
|
|
unsigned long blk_rq_timeout(unsigned long timeout);
|
2014-04-24 08:51:47 -06:00
|
|
|
void blk_add_timer(struct request *req);
|
2013-10-24 09:20:05 +01:00
|
|
|
|
2024-04-08 10:41:05 +09:00
|
|
|
enum bio_merge_status {
|
|
|
|
|
BIO_MERGE_OK,
|
|
|
|
|
BIO_MERGE_NONE,
|
|
|
|
|
BIO_MERGE_FAILED,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum bio_merge_status bio_attempt_back_merge(struct request *req,
|
|
|
|
|
struct bio *bio, unsigned int nr_segs);
|
2013-10-24 09:20:05 +01:00
|
|
|
bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
|
2021-11-23 17:04:41 +01:00
|
|
|
unsigned int nr_segs);
|
2020-08-28 10:52:55 +08:00
|
|
|
bool blk_bio_list_merge(struct request_queue *q, struct list_head *list,
|
|
|
|
|
struct bio *bio, unsigned int nr_segs);
|
2013-10-24 09:20:05 +01:00
|
|
|
|
2021-10-06 12:01:07 -06:00
|
|
|
/*
|
|
|
|
|
* Plug flush limits
|
|
|
|
|
*/
|
|
|
|
|
#define BLK_MAX_REQUEST_COUNT 32
|
|
|
|
|
#define BLK_PLUG_FLUSH_SIZE (128 * 1024)
|
|
|
|
|
|
2009-04-23 11:05:18 +09:00
|
|
|
/*
|
|
|
|
|
* Internal elevator interface
|
|
|
|
|
*/
|
2016-10-20 15:12:13 +02:00
|
|
|
#define ELV_ON_HASH(rq) ((rq)->rq_flags & RQF_HASHED)
|
2009-04-23 11:05:18 +09:00
|
|
|
|
2023-05-19 06:40:46 +02:00
|
|
|
bool blk_insert_flush(struct request *rq);
|
2010-09-03 11:56:16 +02:00
|
|
|
|
2025-11-13 14:28:18 +05:30
|
|
|
void elv_update_nr_hw_queues(struct request_queue *q,
|
|
|
|
|
struct elv_change_ctx *ctx);
|
2025-05-05 22:17:54 +08:00
|
|
|
void elevator_set_default(struct request_queue *q);
|
|
|
|
|
void elevator_set_none(struct request_queue *q);
|
2018-01-17 11:48:08 -08:00
|
|
|
|
2020-03-24 08:25:13 +01:00
|
|
|
ssize_t part_size_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
|
char *buf);
|
|
|
|
|
ssize_t part_stat_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
|
char *buf);
|
|
|
|
|
ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
|
char *buf);
|
|
|
|
|
ssize_t part_fail_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
|
char *buf);
|
|
|
|
|
ssize_t part_fail_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
|
const char *buf, size_t count);
|
2008-09-14 05:56:33 -07:00
|
|
|
ssize_t part_timeout_show(struct device *, struct device_attribute *, char *);
|
|
|
|
|
ssize_t part_timeout_store(struct device *, struct device_attribute *,
|
|
|
|
|
const char *, size_t);
|
|
|
|
|
|
2024-08-26 19:37:54 +02:00
|
|
|
struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim,
|
|
|
|
|
unsigned *nsegs);
|
|
|
|
|
struct bio *bio_split_write_zeroes(struct bio *bio,
|
|
|
|
|
const struct queue_limits *lim, unsigned *nsegs);
|
|
|
|
|
struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
|
|
|
|
|
unsigned *nr_segs);
|
2024-08-26 19:37:56 +02:00
|
|
|
struct bio *bio_split_zone_append(struct bio *bio,
|
|
|
|
|
const struct queue_limits *lim, unsigned *nr_segs);
|
2021-10-13 12:43:41 -06:00
|
|
|
|
2024-08-26 19:37:54 +02:00
|
|
|
/*
|
|
|
|
|
* All drivers must accept single-segments bios that are smaller than PAGE_SIZE.
|
|
|
|
|
*
|
|
|
|
|
* This is a quick and dirty check that relies on the fact that bi_io_vec[0] is
|
|
|
|
|
* always valid if a bio has data. The check might lead to occasional false
|
|
|
|
|
* positives when bios are cloned, but compared to the performance impact of
|
|
|
|
|
* cloned bios themselves the loop below doesn't matter anyway.
|
|
|
|
|
*/
|
|
|
|
|
static inline bool bio_may_need_split(struct bio *bio,
|
|
|
|
|
const struct queue_limits *lim)
|
|
|
|
|
{
|
2025-12-31 11:00:55 +08:00
|
|
|
const struct bio_vec *bv;
|
|
|
|
|
|
2025-02-25 10:21:41 +08:00
|
|
|
if (lim->chunk_sectors)
|
|
|
|
|
return true;
|
2025-12-31 11:00:55 +08:00
|
|
|
|
|
|
|
|
if (!bio->bi_io_vec)
|
2025-02-25 10:21:41 +08:00
|
|
|
return true;
|
2025-12-31 11:00:55 +08:00
|
|
|
|
|
|
|
|
bv = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
|
2026-01-10 21:42:36 +08:00
|
|
|
if (bio->bi_iter.bi_size > bv->bv_len - bio->bi_iter.bi_bvec_done)
|
2025-12-31 11:00:55 +08:00
|
|
|
return true;
|
|
|
|
|
return bv->bv_len + bv->bv_offset > lim->max_fast_segment_size;
|
2021-10-13 12:43:41 -06:00
|
|
|
}
|
|
|
|
|
|
2024-08-26 19:37:54 +02:00
|
|
|
/**
|
|
|
|
|
* __bio_split_to_limits - split a bio to fit the queue limits
|
|
|
|
|
* @bio: bio to be split
|
|
|
|
|
* @lim: queue limits to split based on
|
|
|
|
|
* @nr_segs: returns the number of segments in the returned bio
|
|
|
|
|
*
|
|
|
|
|
* Check if @bio needs splitting based on the queue limits, and if so split off
|
|
|
|
|
* a bio fitting the limits from the beginning of @bio and return it. @bio is
|
|
|
|
|
* shortened to the remainder and re-submitted.
|
|
|
|
|
*
|
|
|
|
|
* The split bio is allocated from @q->bio_split, which is provided by the
|
|
|
|
|
* block layer.
|
|
|
|
|
*/
|
|
|
|
|
static inline struct bio *__bio_split_to_limits(struct bio *bio,
|
|
|
|
|
const struct queue_limits *lim, unsigned int *nr_segs)
|
|
|
|
|
{
|
|
|
|
|
switch (bio_op(bio)) {
|
2024-08-26 19:37:57 +02:00
|
|
|
case REQ_OP_READ:
|
|
|
|
|
case REQ_OP_WRITE:
|
2024-08-26 19:37:54 +02:00
|
|
|
if (bio_may_need_split(bio, lim))
|
|
|
|
|
return bio_split_rw(bio, lim, nr_segs);
|
|
|
|
|
*nr_segs = 1;
|
|
|
|
|
return bio;
|
2024-08-26 19:37:56 +02:00
|
|
|
case REQ_OP_ZONE_APPEND:
|
|
|
|
|
return bio_split_zone_append(bio, lim, nr_segs);
|
2024-08-26 19:37:54 +02:00
|
|
|
case REQ_OP_DISCARD:
|
|
|
|
|
case REQ_OP_SECURE_ERASE:
|
|
|
|
|
return bio_split_discard(bio, lim, nr_segs);
|
|
|
|
|
case REQ_OP_WRITE_ZEROES:
|
|
|
|
|
return bio_split_write_zeroes(bio, lim, nr_segs);
|
2024-08-26 19:37:57 +02:00
|
|
|
default:
|
|
|
|
|
/* other operations can't be split */
|
|
|
|
|
*nr_segs = 0;
|
|
|
|
|
return bio;
|
2024-08-26 19:37:54 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-13 09:14:32 +02:00
|
|
|
/**
|
|
|
|
|
* get_max_segment_size() - maximum number of bytes to add as a single segment
|
|
|
|
|
* @lim: Request queue limits.
|
|
|
|
|
* @paddr: address of the range to add
|
|
|
|
|
* @len: maximum length available to add at @paddr
|
|
|
|
|
*
|
|
|
|
|
* Returns the maximum number of bytes of the range starting at @paddr that can
|
|
|
|
|
* be added to a single segment.
|
|
|
|
|
*/
|
|
|
|
|
static inline unsigned get_max_segment_size(const struct queue_limits *lim,
|
|
|
|
|
phys_addr_t paddr, unsigned int len)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Prevent an overflow if mask = ULONG_MAX and offset = 0 by adding 1
|
|
|
|
|
* after having calculated the minimum.
|
|
|
|
|
*/
|
|
|
|
|
return min_t(unsigned long, len,
|
|
|
|
|
min(lim->seg_boundary_mask - (lim->seg_boundary_mask & paddr),
|
|
|
|
|
(unsigned long)lim->max_segment_size - 1) + 1);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-06 12:29:01 +02:00
|
|
|
int ll_back_merge_fn(struct request *req, struct bio *bio,
|
|
|
|
|
unsigned int nr_segs);
|
2021-06-23 11:36:34 +02:00
|
|
|
bool blk_attempt_req_merge(struct request_queue *q, struct request *rq,
|
2011-03-21 10:14:27 +01:00
|
|
|
struct request *next);
|
2019-06-06 12:29:02 +02:00
|
|
|
unsigned int blk_recalc_rq_segments(struct request *rq);
|
2012-02-08 09:19:38 +01:00
|
|
|
bool blk_rq_merge_ok(struct request *rq, struct bio *bio);
|
2017-02-08 14:46:48 +01:00
|
|
|
enum elv_merge blk_try_merge(struct request *rq, struct bio *bio);
|
2008-01-29 14:04:06 +01:00
|
|
|
|
2024-02-13 08:34:14 +01:00
|
|
|
int blk_set_default_limits(struct queue_limits *lim);
|
2024-06-26 16:26:27 +02:00
|
|
|
void blk_apply_bdi_limits(struct backing_dev_info *bdi,
|
|
|
|
|
struct queue_limits *lim);
|
2008-03-04 11:23:45 +01:00
|
|
|
int blk_dev_init(void);
|
|
|
|
|
|
2021-11-17 07:14:01 +01:00
|
|
|
void update_io_ticks(struct block_device *part, unsigned long now, bool end);
|
2009-02-02 08:42:32 +01:00
|
|
|
|
2017-02-08 14:46:47 +01:00
|
|
|
static inline void req_set_nomerge(struct request_queue *q, struct request *req)
|
|
|
|
|
{
|
|
|
|
|
req->cmd_flags |= REQ_NOMERGE;
|
|
|
|
|
if (req == q->last_merge)
|
|
|
|
|
q->last_merge = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-14 00:33:40 +01:00
|
|
|
/*
|
|
|
|
|
* Internal io_context interface
|
|
|
|
|
*/
|
2021-11-26 12:58:10 +01:00
|
|
|
struct io_cq *ioc_find_get_icq(struct request_queue *q);
|
2021-11-26 12:58:17 +01:00
|
|
|
struct io_cq *ioc_lookup_icq(struct request_queue *q);
|
2021-12-09 07:31:31 +01:00
|
|
|
#ifdef CONFIG_BLK_ICQ
|
2011-12-14 00:33:42 +01:00
|
|
|
void ioc_clear_queue(struct request_queue *q);
|
2021-12-09 07:31:31 +01:00
|
|
|
#else
|
|
|
|
|
static inline void ioc_clear_queue(struct request_queue *q)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endif /* CONFIG_BLK_ICQ */
|
2011-12-14 00:33:40 +01:00
|
|
|
|
2018-10-12 19:08:50 +09:00
|
|
|
#ifdef CONFIG_BLK_DEV_ZONED
|
2024-04-08 10:41:07 +09:00
|
|
|
void disk_init_zone_resources(struct gendisk *disk);
|
|
|
|
|
void disk_free_zone_resources(struct gendisk *disk);
|
|
|
|
|
static inline bool bio_zone_write_plugging(struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
return bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING);
|
|
|
|
|
}
|
2025-07-15 13:53:21 +02:00
|
|
|
static inline bool blk_req_bio_is_zone_append(struct request *rq,
|
|
|
|
|
struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
return req_op(rq) == REQ_OP_ZONE_APPEND ||
|
|
|
|
|
bio_flagged(bio, BIO_EMULATES_ZONE_APPEND);
|
|
|
|
|
}
|
2024-04-08 10:41:07 +09:00
|
|
|
void blk_zone_write_plug_bio_merged(struct bio *bio);
|
2024-05-01 20:09:02 +09:00
|
|
|
void blk_zone_write_plug_init_request(struct request *rq);
|
2025-07-15 13:53:21 +02:00
|
|
|
void blk_zone_append_update_request_bio(struct request *rq, struct bio *bio);
|
2025-11-05 06:22:35 +09:00
|
|
|
void blk_zone_mgmt_bio_endio(struct bio *bio);
|
2024-04-08 10:41:07 +09:00
|
|
|
void blk_zone_write_plug_bio_endio(struct bio *bio);
|
|
|
|
|
static inline void blk_zone_bio_endio(struct bio *bio)
|
|
|
|
|
{
|
2025-11-05 06:22:35 +09:00
|
|
|
/*
|
|
|
|
|
* Zone management BIOs may impact zone write plugs (e.g. a zone reset
|
|
|
|
|
* changes a zone write plug zone write pointer offset), but these
|
|
|
|
|
* operation do not go through zone write plugging as they may operate
|
|
|
|
|
* on zones that do not have a zone write
|
|
|
|
|
* plug. blk_zone_mgmt_bio_endio() handles the potential changes to zone
|
|
|
|
|
* write plugs that are present.
|
|
|
|
|
*/
|
|
|
|
|
if (op_is_zone_mgmt(bio_op(bio))) {
|
|
|
|
|
blk_zone_mgmt_bio_endio(bio);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-08 10:41:07 +09:00
|
|
|
/*
|
|
|
|
|
* For write BIOs to zoned devices, signal the completion of the BIO so
|
|
|
|
|
* that the next write BIO can be submitted by zone write plugging.
|
|
|
|
|
*/
|
|
|
|
|
if (bio_zone_write_plugging(bio))
|
|
|
|
|
blk_zone_write_plug_bio_endio(bio);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 20:09:04 +09:00
|
|
|
void blk_zone_write_plug_finish_request(struct request *rq);
|
|
|
|
|
static inline void blk_zone_finish_request(struct request *rq)
|
2024-04-08 10:41:07 +09:00
|
|
|
{
|
|
|
|
|
if (rq->rq_flags & RQF_ZONE_WRITE_PLUGGING)
|
2024-05-01 20:09:04 +09:00
|
|
|
blk_zone_write_plug_finish_request(rq);
|
2024-04-08 10:41:07 +09:00
|
|
|
}
|
2023-06-08 13:02:54 +02:00
|
|
|
int blkdev_report_zones_ioctl(struct block_device *bdev, unsigned int cmd,
|
|
|
|
|
unsigned long arg);
|
2023-06-08 13:02:55 +02:00
|
|
|
int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
|
2023-06-08 13:02:53 +02:00
|
|
|
unsigned int cmd, unsigned long arg);
|
|
|
|
|
#else /* CONFIG_BLK_DEV_ZONED */
|
2024-04-08 10:41:07 +09:00
|
|
|
static inline void disk_init_zone_resources(struct gendisk *disk)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
static inline void disk_free_zone_resources(struct gendisk *disk)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
static inline bool bio_zone_write_plugging(struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-07-15 13:53:21 +02:00
|
|
|
static inline bool blk_req_bio_is_zone_append(struct request *req,
|
|
|
|
|
struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2024-04-08 10:41:07 +09:00
|
|
|
static inline void blk_zone_write_plug_bio_merged(struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
}
|
2024-05-01 20:09:02 +09:00
|
|
|
static inline void blk_zone_write_plug_init_request(struct request *rq)
|
2024-04-08 10:41:03 +09:00
|
|
|
{
|
|
|
|
|
}
|
2025-07-15 13:53:21 +02:00
|
|
|
static inline void blk_zone_append_update_request_bio(struct request *rq,
|
|
|
|
|
struct bio *bio)
|
2024-04-08 10:41:03 +09:00
|
|
|
{
|
|
|
|
|
}
|
2024-04-08 10:41:07 +09:00
|
|
|
static inline void blk_zone_bio_endio(struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
}
|
2024-05-01 20:09:04 +09:00
|
|
|
static inline void blk_zone_finish_request(struct request *rq)
|
2024-04-08 10:41:07 +09:00
|
|
|
{
|
|
|
|
|
}
|
2023-06-08 13:02:53 +02:00
|
|
|
static inline int blkdev_report_zones_ioctl(struct block_device *bdev,
|
2023-06-08 13:02:54 +02:00
|
|
|
unsigned int cmd, unsigned long arg)
|
2023-06-08 13:02:53 +02:00
|
|
|
{
|
|
|
|
|
return -ENOTTY;
|
|
|
|
|
}
|
|
|
|
|
static inline int blkdev_zone_mgmt_ioctl(struct block_device *bdev,
|
2023-06-08 13:02:55 +02:00
|
|
|
blk_mode_t mode, unsigned int cmd, unsigned long arg)
|
2023-06-08 13:02:53 +02:00
|
|
|
{
|
|
|
|
|
return -ENOTTY;
|
|
|
|
|
}
|
|
|
|
|
#endif /* CONFIG_BLK_DEV_ZONED */
|
|
|
|
|
|
|
|
|
|
struct block_device *bdev_alloc(struct gendisk *disk, u8 partno);
|
|
|
|
|
void bdev_add(struct block_device *bdev, dev_t dev);
|
2024-04-28 19:01:39 -04:00
|
|
|
void bdev_unhash(struct block_device *bdev);
|
|
|
|
|
void bdev_drop(struct block_device *bdev);
|
2018-10-12 19:08:50 +09:00
|
|
|
|
2021-05-21 07:50:51 +02:00
|
|
|
int blk_alloc_ext_minor(void);
|
|
|
|
|
void blk_free_ext_minor(unsigned int minor);
|
2020-03-25 16:48:41 +01:00
|
|
|
#define ADDPART_FLAG_NONE 0
|
|
|
|
|
#define ADDPART_FLAG_RAID 1
|
|
|
|
|
#define ADDPART_FLAG_WHOLEDISK 2
|
2024-10-03 00:11:41 +02:00
|
|
|
#define ADDPART_FLAG_READONLY 4
|
2021-08-10 17:45:10 +02:00
|
|
|
int bdev_add_partition(struct gendisk *disk, int partno, sector_t start,
|
|
|
|
|
sector_t length);
|
2021-08-10 17:45:11 +02:00
|
|
|
int bdev_del_partition(struct gendisk *disk, int partno);
|
2021-08-10 17:45:12 +02:00
|
|
|
int bdev_resize_partition(struct gendisk *disk, int partno, sector_t start,
|
|
|
|
|
sector_t length);
|
2023-06-01 11:44:50 +02:00
|
|
|
void drop_partition(struct block_device *part);
|
2020-03-25 16:48:41 +01:00
|
|
|
|
2023-04-24 22:13:18 +09:00
|
|
|
void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors);
|
|
|
|
|
|
2022-06-19 08:05:51 +02:00
|
|
|
struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
|
|
|
|
|
struct lock_class_key *lkclass);
|
2024-02-13 08:34:18 +01:00
|
|
|
struct request_queue *blk_alloc_queue(struct queue_limits *lim, int node_id);
|
2021-12-03 21:15:32 +08:00
|
|
|
|
2023-06-08 13:02:55 +02:00
|
|
|
int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode);
|
2021-05-21 07:51:16 +02:00
|
|
|
|
2021-08-18 16:45:39 +02:00
|
|
|
int disk_alloc_events(struct gendisk *disk);
|
2021-06-24 09:38:42 +02:00
|
|
|
void disk_add_events(struct gendisk *disk);
|
|
|
|
|
void disk_del_events(struct gendisk *disk);
|
|
|
|
|
void disk_release_events(struct gendisk *disk);
|
2022-01-24 10:39:11 +01:00
|
|
|
void disk_block_events(struct gendisk *disk);
|
|
|
|
|
void disk_unblock_events(struct gendisk *disk);
|
|
|
|
|
void disk_flush_events(struct gendisk *disk, unsigned int mask);
|
2021-06-24 09:38:43 +02:00
|
|
|
extern struct device_attribute dev_attr_events;
|
|
|
|
|
extern struct device_attribute dev_attr_events_async;
|
|
|
|
|
extern struct device_attribute dev_attr_events_poll_msecs;
|
2021-06-24 09:38:42 +02:00
|
|
|
|
2022-06-28 19:18:45 +02:00
|
|
|
extern struct attribute_group blk_trace_attr_group;
|
|
|
|
|
|
2023-06-08 13:02:55 +02:00
|
|
|
blk_mode_t file_to_blk_mode(struct file *file);
|
|
|
|
|
int truncate_bdev_range(struct block_device *bdev, blk_mode_t mode,
|
|
|
|
|
loff_t lstart, loff_t lend);
|
2021-10-12 12:44:50 +02:00
|
|
|
long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg);
|
2024-09-11 17:34:41 +01:00
|
|
|
int blkdev_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags);
|
2021-10-12 12:44:49 +02:00
|
|
|
long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg);
|
|
|
|
|
|
2021-09-07 16:13:02 +02:00
|
|
|
extern const struct address_space_operations def_blk_aops;
|
|
|
|
|
|
2022-06-29 08:20:13 +02:00
|
|
|
int disk_register_independent_access_ranges(struct gendisk *disk);
|
2021-10-27 11:22:19 +09:00
|
|
|
void disk_unregister_independent_access_ranges(struct gendisk *disk);
|
|
|
|
|
|
2025-09-10 14:30:54 +08:00
|
|
|
int should_fail_bio(struct bio *bio);
|
2021-11-17 07:13:58 +01:00
|
|
|
#ifdef CONFIG_FAIL_MAKE_REQUEST
|
|
|
|
|
bool should_fail_request(struct block_device *part, unsigned int bytes);
|
|
|
|
|
#else /* CONFIG_FAIL_MAKE_REQUEST */
|
|
|
|
|
static inline bool should_fail_request(struct block_device *part,
|
|
|
|
|
unsigned int bytes)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif /* CONFIG_FAIL_MAKE_REQUEST */
|
|
|
|
|
|
2021-10-14 14:39:59 -06:00
|
|
|
/*
|
|
|
|
|
* Optimized request reference counting. Ideally we'd make timeouts be more
|
|
|
|
|
* clever, as that's the only reason we need references at all... But until
|
|
|
|
|
* this happens, this is faster than using refcount_t. Also see:
|
|
|
|
|
*
|
|
|
|
|
* abc54d634334 ("io_uring: switch to atomic_t for io_kiocb reference count")
|
|
|
|
|
*/
|
|
|
|
|
#define req_ref_zero_or_close_to_overflow(req) \
|
|
|
|
|
((unsigned int) atomic_read(&(req->ref)) + 127u <= 127u)
|
|
|
|
|
|
|
|
|
|
static inline bool req_ref_inc_not_zero(struct request *req)
|
|
|
|
|
{
|
|
|
|
|
return atomic_inc_not_zero(&req->ref);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool req_ref_put_and_test(struct request *req)
|
|
|
|
|
{
|
|
|
|
|
WARN_ON_ONCE(req_ref_zero_or_close_to_overflow(req));
|
|
|
|
|
return atomic_dec_and_test(&req->ref);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void req_ref_set(struct request *req, int value)
|
|
|
|
|
{
|
|
|
|
|
atomic_set(&req->ref, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int req_ref_read(struct request *req)
|
|
|
|
|
{
|
|
|
|
|
return atomic_read(&req->ref);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-15 14:45:07 -07:00
|
|
|
static inline u64 blk_time_get_ns(void)
|
|
|
|
|
{
|
2024-01-15 14:46:03 -07:00
|
|
|
struct blk_plug *plug = current->plug;
|
|
|
|
|
|
2024-03-12 15:58:41 -06:00
|
|
|
if (!plug || !in_task())
|
2024-01-15 14:46:03 -07:00
|
|
|
return ktime_get_ns();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 0 could very well be a valid time, but rather than flag "this is
|
|
|
|
|
* a valid timestamp" separately, just accept that we'll do an extra
|
|
|
|
|
* ktime_get_ns() if we just happen to get 0 as the current time.
|
|
|
|
|
*/
|
2024-01-16 09:18:39 -07:00
|
|
|
if (!plug->cur_ktime) {
|
2024-01-15 14:46:03 -07:00
|
|
|
plug->cur_ktime = ktime_get_ns();
|
2024-01-16 09:18:39 -07:00
|
|
|
current->flags |= PF_BLOCK_TS;
|
|
|
|
|
}
|
2024-01-15 14:46:03 -07:00
|
|
|
return plug->cur_ktime;
|
2024-01-15 14:45:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline ktime_t blk_time_get(void)
|
|
|
|
|
{
|
|
|
|
|
return ns_to_ktime(blk_time_get_ns());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-23 14:26:47 +01:00
|
|
|
void bdev_release(struct file *bdev_file);
|
2024-01-23 14:26:46 +01:00
|
|
|
int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
|
|
|
|
|
const struct blk_holder_ops *hops, struct file *bdev_file);
|
|
|
|
|
int bdev_permission(dev_t dev, blk_mode_t mode, void *holder);
|
2024-03-11 11:43:44 -07:00
|
|
|
|
2026-02-23 05:20:04 -08:00
|
|
|
void bio_integrity_generate(struct bio *bio);
|
|
|
|
|
blk_status_t bio_integrity_verify(struct bio *bio,
|
|
|
|
|
struct bvec_iter *saved_iter);
|
|
|
|
|
|
2024-06-13 10:48:15 +02:00
|
|
|
void blk_integrity_prepare(struct request *rq);
|
|
|
|
|
void blk_integrity_complete(struct request *rq, unsigned int nr_bytes);
|
|
|
|
|
|
2024-11-27 21:51:28 +08:00
|
|
|
#ifdef CONFIG_LOCKDEP
|
2024-11-27 21:51:30 +08:00
|
|
|
static inline void blk_freeze_acquire_lock(struct request_queue *q)
|
2024-10-25 08:37:20 +08:00
|
|
|
{
|
2024-11-27 21:51:28 +08:00
|
|
|
if (!q->mq_freeze_disk_dead)
|
2024-10-25 08:37:20 +08:00
|
|
|
rwsem_acquire(&q->io_lockdep_map, 0, 1, _RET_IP_);
|
2024-11-27 21:51:30 +08:00
|
|
|
if (!q->mq_freeze_queue_dying)
|
2024-10-25 08:37:20 +08:00
|
|
|
rwsem_acquire(&q->q_lockdep_map, 0, 1, _RET_IP_);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-27 21:51:30 +08:00
|
|
|
static inline void blk_unfreeze_release_lock(struct request_queue *q)
|
2024-10-25 08:37:20 +08:00
|
|
|
{
|
2024-11-27 21:51:30 +08:00
|
|
|
if (!q->mq_freeze_queue_dying)
|
2024-10-25 08:37:20 +08:00
|
|
|
rwsem_release(&q->q_lockdep_map, _RET_IP_);
|
2024-11-27 21:51:28 +08:00
|
|
|
if (!q->mq_freeze_disk_dead)
|
2024-10-25 08:37:20 +08:00
|
|
|
rwsem_release(&q->io_lockdep_map, _RET_IP_);
|
|
|
|
|
}
|
2024-11-27 21:51:28 +08:00
|
|
|
#else
|
2024-11-27 21:51:30 +08:00
|
|
|
static inline void blk_freeze_acquire_lock(struct request_queue *q)
|
2024-11-27 21:51:28 +08:00
|
|
|
{
|
|
|
|
|
}
|
2024-11-27 21:51:30 +08:00
|
|
|
static inline void blk_unfreeze_release_lock(struct request_queue *q)
|
2024-11-27 21:51:28 +08:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2024-10-25 08:37:20 +08:00
|
|
|
|
2026-02-14 13:43:50 +08:00
|
|
|
/*
|
|
|
|
|
* debugfs directory and file creation can trigger fs reclaim, which can enter
|
|
|
|
|
* back into the block layer request_queue. This can cause deadlock if the
|
|
|
|
|
* queue is frozen. Use NOIO context together with debugfs_mutex to prevent fs
|
|
|
|
|
* reclaim from triggering block I/O.
|
|
|
|
|
*/
|
|
|
|
|
static inline void blk_debugfs_lock_nomemsave(struct request_queue *q)
|
|
|
|
|
{
|
|
|
|
|
mutex_lock(&q->debugfs_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void blk_debugfs_unlock_nomemrestore(struct request_queue *q)
|
|
|
|
|
{
|
|
|
|
|
mutex_unlock(&q->debugfs_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int __must_check blk_debugfs_lock(struct request_queue *q)
|
|
|
|
|
{
|
|
|
|
|
unsigned int memflags = memalloc_noio_save();
|
|
|
|
|
|
|
|
|
|
blk_debugfs_lock_nomemsave(q);
|
|
|
|
|
return memflags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void blk_debugfs_unlock(struct request_queue *q,
|
|
|
|
|
unsigned int memflags)
|
|
|
|
|
{
|
|
|
|
|
blk_debugfs_unlock_nomemrestore(q);
|
|
|
|
|
memalloc_noio_restore(memflags);
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-19 14:31:18 +02:00
|
|
|
#endif /* BLK_INTERNAL_H */
|