mirror of
https://github.com/t2linux/kernel.git
synced 2026-04-30 13:48:59 -07:00
Merge tag 'for-5.12/block-2021-02-17' of git://git.kernel.dk/linux-block
Pull core block updates from Jens Axboe: "Another nice round of removing more code than what is added, mostly due to Christoph's relentless pursuit of tech debt removal/cleanups. This pull request contains: - Two series of BFQ improvements (Paolo, Jan, Jia) - Block iov_iter improvements (Pavel) - bsg error path fix (Pan) - blk-mq scheduler improvements (Jan) - -EBUSY discard fix (Jan) - bvec allocation improvements (Ming, Christoph) - bio allocation and init improvements (Christoph) - Store bdev pointer in bio instead of gendisk + partno (Christoph) - Block trace point cleanups (Christoph) - hard read-only vs read-only split (Christoph) - Block based swap cleanups (Christoph) - Zoned write granularity support (Damien) - Various fixes/tweaks (Chunguang, Guoqing, Lei, Lukas, Huhai)" * tag 'for-5.12/block-2021-02-17' of git://git.kernel.dk/linux-block: (104 commits) mm: simplify swapdev_block sd_zbc: clear zone resources for non-zoned case block: introduce blk_queue_clear_zone_settings() zonefs: use zone write granularity as block size block: introduce zone_write_granularity limit block: use blk_queue_set_zoned in add_partition() nullb: use blk_queue_set_zoned() to setup zoned devices nvme: cleanup zone information initialization block: document zone_append_max_bytes attribute block: use bi_max_vecs to find the bvec pool md/raid10: remove dead code in reshape_request block: mark the bio as cloned in bio_iov_bvec_set block: set BIO_NO_PAGE_REF in bio_iov_bvec_set block: remove a layer of indentation in bio_iov_iter_get_pages block: turn the nr_iovecs argument to bio_alloc* into an unsigned short block: remove the 1 and 4 vec bvec_slabs entries block: streamline bvec_alloc block: factor out a bvec_alloc_gfp helper block: move struct biovec_slab to bio.c block: reuse BIO_INLINE_VECS for integrity bvecs ...
This commit is contained in:
@@ -40,6 +40,8 @@ normal code doesn't have to deal with bi_bvec_done.
|
||||
There is a lower level advance function - bvec_iter_advance() - which takes
|
||||
a pointer to a biovec, not a bio; this is used by the bio integrity code.
|
||||
|
||||
As of 5.12 bvec segments with zero bv_len are not supported.
|
||||
|
||||
What's all this get us?
|
||||
=======================
|
||||
|
||||
|
||||
@@ -261,6 +261,12 @@ For block drivers that support REQ_OP_WRITE_ZEROES, the maximum number of
|
||||
bytes that can be zeroed at once. The value 0 means that REQ_OP_WRITE_ZEROES
|
||||
is not supported.
|
||||
|
||||
zone_append_max_bytes (RO)
|
||||
--------------------------
|
||||
This is the maximum number of bytes that can be written to a sequential
|
||||
zone of a zoned block device using a zone append write operation
|
||||
(REQ_OP_ZONE_APPEND). This value is always 0 for regular block devices.
|
||||
|
||||
zoned (RO)
|
||||
----------
|
||||
This indicates if the device is a zoned block device and the zone model of the
|
||||
@@ -273,4 +279,11 @@ devices are described in the ZBC (Zoned Block Commands) and ZAC
|
||||
do not support zone commands, they will be treated as regular block devices
|
||||
and zoned will report "none".
|
||||
|
||||
zone_write_granularity (RO)
|
||||
---------------------------
|
||||
This indicates the alignment constraint, in bytes, for write operations in
|
||||
sequential zones of zoned block devices (devices with a zoned attributed
|
||||
that reports "host-managed" or "host-aware"). This value is always 0 for
|
||||
regular block devices.
|
||||
|
||||
Jens Axboe <jens.axboe@oracle.com>, February 2009
|
||||
|
||||
@@ -179,7 +179,6 @@ fault_type=%d Support configuring fault injection type, should be
|
||||
FAULT_KVMALLOC 0x000000002
|
||||
FAULT_PAGE_ALLOC 0x000000004
|
||||
FAULT_PAGE_GET 0x000000008
|
||||
FAULT_ALLOC_BIO 0x000000010
|
||||
FAULT_ALLOC_NID 0x000000020
|
||||
FAULT_ORPHAN 0x000000040
|
||||
FAULT_BLOCK 0x000000080
|
||||
|
||||
@@ -865,3 +865,19 @@ no matter what. Everything is handled by the caller.
|
||||
|
||||
clone_private_mount() returns a longterm mount now, so the proper destructor of
|
||||
its result is kern_unmount() or kern_unmount_array().
|
||||
|
||||
---
|
||||
|
||||
**mandatory**
|
||||
|
||||
zero-length bvec segments are disallowed, they must be filtered out before
|
||||
passed on to an iterator.
|
||||
|
||||
---
|
||||
|
||||
**mandatory**
|
||||
|
||||
For bvec based itererators bio_iov_iter_get_pages() now doesn't copy bvecs but
|
||||
uses the one provided. Anyone issuing kiocb-I/O should ensure that the bvec and
|
||||
page references stay until I/O has completed, i.e. until ->ki_complete() has
|
||||
been called or returned with non -EIOCBQUEUED code.
|
||||
|
||||
@@ -61,7 +61,7 @@ struct nfhd_device {
|
||||
|
||||
static blk_qc_t nfhd_submit_bio(struct bio *bio)
|
||||
{
|
||||
struct nfhd_device *dev = bio->bi_disk->private_data;
|
||||
struct nfhd_device *dev = bio->bi_bdev->bd_disk->private_data;
|
||||
struct bio_vec bvec;
|
||||
struct bvec_iter iter;
|
||||
int dir, len, shift;
|
||||
|
||||
@@ -103,7 +103,7 @@ static void simdisk_transfer(struct simdisk *dev, unsigned long sector,
|
||||
|
||||
static blk_qc_t simdisk_submit_bio(struct bio *bio)
|
||||
{
|
||||
struct simdisk *dev = bio->bi_disk->private_data;
|
||||
struct simdisk *dev = bio->bi_bdev->bd_disk->private_data;
|
||||
struct bio_vec bvec;
|
||||
struct bvec_iter iter;
|
||||
sector_t sector = bio->bi_iter.bi_sector;
|
||||
|
||||
+276
-169
File diff suppressed because it is too large
Load Diff
+19
-10
@@ -291,6 +291,11 @@ struct bfq_queue {
|
||||
/* associated @bfq_ttime struct */
|
||||
struct bfq_ttime ttime;
|
||||
|
||||
/* when bfqq started to do I/O within the last observation window */
|
||||
u64 io_start_time;
|
||||
/* how long bfqq has remained empty during the last observ. window */
|
||||
u64 tot_idle_time;
|
||||
|
||||
/* bit vector: a 1 for each seeky requests in history */
|
||||
u32 seek_history;
|
||||
|
||||
@@ -371,6 +376,11 @@ struct bfq_queue {
|
||||
* bfq_select_queue().
|
||||
*/
|
||||
struct bfq_queue *waker_bfqq;
|
||||
/* pointer to the curr. tentative waker queue, see bfq_check_waker() */
|
||||
struct bfq_queue *tentative_waker_bfqq;
|
||||
/* number of times the same tentative waker has been detected */
|
||||
unsigned int num_waker_detections;
|
||||
|
||||
/* node for woken_list, see below */
|
||||
struct hlist_node woken_list_node;
|
||||
/*
|
||||
@@ -407,6 +417,9 @@ struct bfq_io_cq {
|
||||
*/
|
||||
bool saved_IO_bound;
|
||||
|
||||
u64 saved_io_start_time;
|
||||
u64 saved_tot_idle_time;
|
||||
|
||||
/*
|
||||
* Same purpose as the previous fields for the value of the
|
||||
* field keeping the queue's belonging to a large burst
|
||||
@@ -432,9 +445,15 @@ struct bfq_io_cq {
|
||||
*/
|
||||
unsigned long saved_wr_coeff;
|
||||
unsigned long saved_last_wr_start_finish;
|
||||
unsigned long saved_service_from_wr;
|
||||
unsigned long saved_wr_start_at_switch_to_srt;
|
||||
unsigned int saved_wr_cur_max_time;
|
||||
struct bfq_ttime saved_ttime;
|
||||
|
||||
/* Save also injection state */
|
||||
u64 saved_last_serv_time_ns;
|
||||
unsigned int saved_inject_limit;
|
||||
unsigned long saved_decrease_time_jif;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -641,14 +660,6 @@ struct bfq_data {
|
||||
*/
|
||||
unsigned int bfq_timeout;
|
||||
|
||||
/*
|
||||
* Number of consecutive requests that must be issued within
|
||||
* the idle time slice to set again idling to a queue which
|
||||
* was marked as non-I/O-bound (see the definition of the
|
||||
* IO_bound flag for further details).
|
||||
*/
|
||||
unsigned int bfq_requests_within_timer;
|
||||
|
||||
/*
|
||||
* Force device idling whenever needed to provide accurate
|
||||
* service guarantees, without caring about throughput
|
||||
@@ -770,7 +781,6 @@ enum bfqq_state_flags {
|
||||
*/
|
||||
BFQQF_coop, /* bfqq is shared */
|
||||
BFQQF_split_coop, /* shared bfqq will be split */
|
||||
BFQQF_has_waker /* bfqq has a waker queue */
|
||||
};
|
||||
|
||||
#define BFQ_BFQQ_FNS(name) \
|
||||
@@ -790,7 +800,6 @@ BFQ_BFQQ_FNS(in_large_burst);
|
||||
BFQ_BFQQ_FNS(coop);
|
||||
BFQ_BFQQ_FNS(split_coop);
|
||||
BFQ_BFQQ_FNS(softrt_update);
|
||||
BFQ_BFQQ_FNS(has_waker);
|
||||
#undef BFQ_BFQQ_FNS
|
||||
|
||||
/* Expiration reasons. */
|
||||
|
||||
@@ -137,9 +137,6 @@ static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
|
||||
|
||||
sd->next_in_service = next_in_service;
|
||||
|
||||
if (!next_in_service)
|
||||
return parent_sched_may_change;
|
||||
|
||||
return parent_sched_may_change;
|
||||
}
|
||||
|
||||
|
||||
+15
-20
@@ -14,8 +14,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include "blk.h"
|
||||
|
||||
#define BIP_INLINE_VECS 4
|
||||
|
||||
static struct kmem_cache *bip_slab;
|
||||
static struct workqueue_struct *kintegrityd_wq;
|
||||
|
||||
@@ -30,7 +28,7 @@ static void __bio_integrity_free(struct bio_set *bs,
|
||||
if (bs && mempool_initialized(&bs->bio_integrity_pool)) {
|
||||
if (bip->bip_vec)
|
||||
bvec_free(&bs->bvec_integrity_pool, bip->bip_vec,
|
||||
bip->bip_slab);
|
||||
bip->bip_max_vcnt);
|
||||
mempool_free(bip, &bs->bio_integrity_pool);
|
||||
} else {
|
||||
kfree(bip);
|
||||
@@ -63,7 +61,7 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
|
||||
inline_vecs = nr_vecs;
|
||||
} else {
|
||||
bip = mempool_alloc(&bs->bio_integrity_pool, gfp_mask);
|
||||
inline_vecs = BIP_INLINE_VECS;
|
||||
inline_vecs = BIO_INLINE_VECS;
|
||||
}
|
||||
|
||||
if (unlikely(!bip))
|
||||
@@ -72,14 +70,11 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
|
||||
memset(bip, 0, sizeof(*bip));
|
||||
|
||||
if (nr_vecs > inline_vecs) {
|
||||
unsigned long idx = 0;
|
||||
|
||||
bip->bip_vec = bvec_alloc(gfp_mask, nr_vecs, &idx,
|
||||
&bs->bvec_integrity_pool);
|
||||
bip->bip_max_vcnt = nr_vecs;
|
||||
bip->bip_vec = bvec_alloc(&bs->bvec_integrity_pool,
|
||||
&bip->bip_max_vcnt, gfp_mask);
|
||||
if (!bip->bip_vec)
|
||||
goto err;
|
||||
bip->bip_max_vcnt = bvec_nr_vecs(idx);
|
||||
bip->bip_slab = idx;
|
||||
} else {
|
||||
bip->bip_vec = bip->bip_inline_vecs;
|
||||
bip->bip_max_vcnt = inline_vecs;
|
||||
@@ -140,7 +135,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
|
||||
iv = bip->bip_vec + bip->bip_vcnt;
|
||||
|
||||
if (bip->bip_vcnt &&
|
||||
bvec_gap_to_prev(bio->bi_disk->queue,
|
||||
bvec_gap_to_prev(bio->bi_bdev->bd_disk->queue,
|
||||
&bip->bip_vec[bip->bip_vcnt - 1], offset))
|
||||
return 0;
|
||||
|
||||
@@ -162,7 +157,7 @@ EXPORT_SYMBOL(bio_integrity_add_page);
|
||||
static blk_status_t bio_integrity_process(struct bio *bio,
|
||||
struct bvec_iter *proc_iter, integrity_processing_fn *proc_fn)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct blk_integrity_iter iter;
|
||||
struct bvec_iter bviter;
|
||||
struct bio_vec bv;
|
||||
@@ -171,7 +166,7 @@ static blk_status_t bio_integrity_process(struct bio *bio,
|
||||
void *prot_buf = page_address(bip->bip_vec->bv_page) +
|
||||
bip->bip_vec->bv_offset;
|
||||
|
||||
iter.disk_name = bio->bi_disk->disk_name;
|
||||
iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
|
||||
iter.interval = 1 << bi->interval_exp;
|
||||
iter.seed = proc_iter->bi_sector;
|
||||
iter.prot_buf = prot_buf;
|
||||
@@ -208,8 +203,8 @@ static blk_status_t bio_integrity_process(struct bio *bio,
|
||||
bool bio_integrity_prep(struct bio *bio)
|
||||
{
|
||||
struct bio_integrity_payload *bip;
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
|
||||
struct request_queue *q = bio->bi_disk->queue;
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct request_queue *q = bio->bi_bdev->bd_disk->queue;
|
||||
void *buf;
|
||||
unsigned long start, end;
|
||||
unsigned int len, nr_pages;
|
||||
@@ -329,7 +324,7 @@ static void bio_integrity_verify_fn(struct work_struct *work)
|
||||
struct bio_integrity_payload *bip =
|
||||
container_of(work, struct bio_integrity_payload, bip_work);
|
||||
struct bio *bio = bip->bip_bio;
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
|
||||
/*
|
||||
* At the moment verify is called bio's iterator was advanced
|
||||
@@ -355,7 +350,7 @@ static void bio_integrity_verify_fn(struct work_struct *work)
|
||||
*/
|
||||
bool __bio_integrity_endio(struct bio *bio)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
|
||||
if (bio_op(bio) == REQ_OP_READ && !bio->bi_status &&
|
||||
@@ -381,7 +376,7 @@ bool __bio_integrity_endio(struct bio *bio)
|
||||
void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
|
||||
{
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
|
||||
|
||||
bip->bip_iter.bi_sector += bytes_done >> 9;
|
||||
@@ -397,7 +392,7 @@ void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
|
||||
void bio_integrity_trim(struct bio *bio)
|
||||
{
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
|
||||
bip->bip_iter.bi_size = bio_integrity_bytes(bi, bio_sectors(bio));
|
||||
}
|
||||
@@ -470,6 +465,6 @@ void __init bio_integrity_init(void)
|
||||
|
||||
bip_slab = kmem_cache_create("bio_integrity_payload",
|
||||
sizeof(struct bio_integrity_payload) +
|
||||
sizeof(struct bio_vec) * BIP_INLINE_VECS,
|
||||
sizeof(struct bio_vec) * BIO_INLINE_VECS,
|
||||
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
|
||||
}
|
||||
|
||||
+256
-321
File diff suppressed because it is too large
Load Diff
+12
-10
@@ -32,8 +32,6 @@
|
||||
#include <linux/psi.h>
|
||||
#include "blk.h"
|
||||
|
||||
#define MAX_KEY_LEN 100
|
||||
|
||||
/*
|
||||
* blkcg_pol_mutex protects blkcg_policy[] and policy [de]activation.
|
||||
* blkcg_pol_register_mutex nests outside of it and synchronizes entire
|
||||
@@ -1765,12 +1763,15 @@ void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay)
|
||||
if (unlikely(current->flags & PF_KTHREAD))
|
||||
return;
|
||||
|
||||
if (!blk_get_queue(q))
|
||||
return;
|
||||
if (current->throttle_queue != q) {
|
||||
if (!blk_get_queue(q))
|
||||
return;
|
||||
|
||||
if (current->throttle_queue)
|
||||
blk_put_queue(current->throttle_queue);
|
||||
current->throttle_queue = q;
|
||||
}
|
||||
|
||||
if (current->throttle_queue)
|
||||
blk_put_queue(current->throttle_queue);
|
||||
current->throttle_queue = q;
|
||||
if (use_memdelay)
|
||||
current->use_memdelay = use_memdelay;
|
||||
set_notify_resume(current);
|
||||
@@ -1808,7 +1809,8 @@ static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio,
|
||||
struct blkcg_gq *blkg, *ret_blkg = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
blkg = blkg_lookup_create(css_to_blkcg(css), bio->bi_disk->queue);
|
||||
blkg = blkg_lookup_create(css_to_blkcg(css),
|
||||
bio->bi_bdev->bd_disk->queue);
|
||||
while (blkg) {
|
||||
if (blkg_tryget(blkg)) {
|
||||
ret_blkg = blkg;
|
||||
@@ -1844,8 +1846,8 @@ void bio_associate_blkg_from_css(struct bio *bio,
|
||||
if (css && css->parent) {
|
||||
bio->bi_blkg = blkg_tryget_closest(bio, css);
|
||||
} else {
|
||||
blkg_get(bio->bi_disk->queue->root_blkg);
|
||||
bio->bi_blkg = bio->bi_disk->queue->root_blkg;
|
||||
blkg_get(bio->bi_bdev->bd_disk->queue->root_blkg);
|
||||
bio->bi_blkg = bio->bi_bdev->bd_disk->queue->root_blkg;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bio_associate_blkg_from_css);
|
||||
|
||||
+46
-53
@@ -476,7 +476,7 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
|
||||
|
||||
static inline int bio_queue_enter(struct bio *bio)
|
||||
{
|
||||
struct request_queue *q = bio->bi_disk->queue;
|
||||
struct request_queue *q = bio->bi_bdev->bd_disk->queue;
|
||||
bool nowait = bio->bi_opf & REQ_NOWAIT;
|
||||
int ret;
|
||||
|
||||
@@ -531,7 +531,7 @@ struct request_queue *blk_alloc_queue(int node_id)
|
||||
if (q->id < 0)
|
||||
goto fail_q;
|
||||
|
||||
ret = bioset_init(&q->bio_split, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
|
||||
ret = bioset_init(&q->bio_split, BIO_POOL_SIZE, 0, 0);
|
||||
if (ret)
|
||||
goto fail_id;
|
||||
|
||||
@@ -692,11 +692,9 @@ static inline bool should_fail_request(struct block_device *part,
|
||||
|
||||
#endif /* CONFIG_FAIL_MAKE_REQUEST */
|
||||
|
||||
static inline bool bio_check_ro(struct bio *bio, struct block_device *part)
|
||||
static inline bool bio_check_ro(struct bio *bio)
|
||||
{
|
||||
const int op = bio_op(bio);
|
||||
|
||||
if (part->bd_read_only && op_is_write(op)) {
|
||||
if (op_is_write(bio_op(bio)) && bdev_read_only(bio->bi_bdev)) {
|
||||
char b[BDEVNAME_SIZE];
|
||||
|
||||
if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
|
||||
@@ -704,7 +702,7 @@ static inline bool bio_check_ro(struct bio *bio, struct block_device *part)
|
||||
|
||||
WARN_ONCE(1,
|
||||
"Trying to write to read-only block-device %s (partno %d)\n",
|
||||
bio_devname(bio, b), part->bd_partno);
|
||||
bio_devname(bio, b), bio->bi_bdev->bd_partno);
|
||||
/* Older lvm-tools actually trigger this */
|
||||
return false;
|
||||
}
|
||||
@@ -714,7 +712,7 @@ static inline bool bio_check_ro(struct bio *bio, struct block_device *part)
|
||||
|
||||
static noinline int should_fail_bio(struct bio *bio)
|
||||
{
|
||||
if (should_fail_request(bio->bi_disk->part0, bio->bi_iter.bi_size))
|
||||
if (should_fail_request(bdev_whole(bio->bi_bdev), bio->bi_iter.bi_size))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
@@ -725,8 +723,9 @@ ALLOW_ERROR_INJECTION(should_fail_bio, ERRNO);
|
||||
* This may well happen - the kernel calls bread() without checking the size of
|
||||
* the device, e.g., when mounting a file system.
|
||||
*/
|
||||
static inline int bio_check_eod(struct bio *bio, sector_t maxsector)
|
||||
static inline int bio_check_eod(struct bio *bio)
|
||||
{
|
||||
sector_t maxsector = bdev_nr_sectors(bio->bi_bdev);
|
||||
unsigned int nr_sectors = bio_sectors(bio);
|
||||
|
||||
if (nr_sectors && maxsector &&
|
||||
@@ -741,33 +740,20 @@ static inline int bio_check_eod(struct bio *bio, sector_t maxsector)
|
||||
/*
|
||||
* Remap block n of partition p to block n+start(p) of the disk.
|
||||
*/
|
||||
static inline int blk_partition_remap(struct bio *bio)
|
||||
static int blk_partition_remap(struct bio *bio)
|
||||
{
|
||||
struct block_device *p;
|
||||
int ret = -EIO;
|
||||
struct block_device *p = bio->bi_bdev;
|
||||
|
||||
rcu_read_lock();
|
||||
p = __disk_get_part(bio->bi_disk, bio->bi_partno);
|
||||
if (unlikely(!p))
|
||||
goto out;
|
||||
if (unlikely(should_fail_request(p, bio->bi_iter.bi_size)))
|
||||
goto out;
|
||||
if (unlikely(bio_check_ro(bio, p)))
|
||||
goto out;
|
||||
|
||||
return -EIO;
|
||||
if (bio_sectors(bio)) {
|
||||
if (bio_check_eod(bio, bdev_nr_sectors(p)))
|
||||
goto out;
|
||||
bio->bi_iter.bi_sector += p->bd_start_sect;
|
||||
trace_block_bio_remap(bio, p->bd_dev,
|
||||
bio->bi_iter.bi_sector -
|
||||
p->bd_start_sect);
|
||||
}
|
||||
bio->bi_partno = 0;
|
||||
ret = 0;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
bio_set_flag(bio, BIO_REMAPPED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -807,7 +793,8 @@ static inline blk_status_t blk_check_zone_append(struct request_queue *q,
|
||||
|
||||
static noinline_for_stack bool submit_bio_checks(struct bio *bio)
|
||||
{
|
||||
struct request_queue *q = bio->bi_disk->queue;
|
||||
struct block_device *bdev = bio->bi_bdev;
|
||||
struct request_queue *q = bdev->bd_disk->queue;
|
||||
blk_status_t status = BLK_STS_IOERR;
|
||||
struct blk_plug *plug;
|
||||
|
||||
@@ -826,14 +813,12 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio)
|
||||
|
||||
if (should_fail_bio(bio))
|
||||
goto end_io;
|
||||
|
||||
if (bio->bi_partno) {
|
||||
if (unlikely(blk_partition_remap(bio)))
|
||||
if (unlikely(bio_check_ro(bio)))
|
||||
goto end_io;
|
||||
if (!bio_flagged(bio, BIO_REMAPPED)) {
|
||||
if (unlikely(bio_check_eod(bio)))
|
||||
goto end_io;
|
||||
} else {
|
||||
if (unlikely(bio_check_ro(bio, bio->bi_disk->part0)))
|
||||
goto end_io;
|
||||
if (unlikely(bio_check_eod(bio, get_capacity(bio->bi_disk))))
|
||||
if (bdev->bd_partno && unlikely(blk_partition_remap(bio)))
|
||||
goto end_io;
|
||||
}
|
||||
|
||||
@@ -926,7 +911,7 @@ end_io:
|
||||
|
||||
static blk_qc_t __submit_bio(struct bio *bio)
|
||||
{
|
||||
struct gendisk *disk = bio->bi_disk;
|
||||
struct gendisk *disk = bio->bi_bdev->bd_disk;
|
||||
blk_qc_t ret = BLK_QC_T_NONE;
|
||||
|
||||
if (blk_crypto_bio_prep(&bio)) {
|
||||
@@ -968,7 +953,7 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio)
|
||||
current->bio_list = bio_list_on_stack;
|
||||
|
||||
do {
|
||||
struct request_queue *q = bio->bi_disk->queue;
|
||||
struct request_queue *q = bio->bi_bdev->bd_disk->queue;
|
||||
struct bio_list lower, same;
|
||||
|
||||
if (unlikely(bio_queue_enter(bio) != 0))
|
||||
@@ -989,7 +974,7 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio)
|
||||
bio_list_init(&lower);
|
||||
bio_list_init(&same);
|
||||
while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL)
|
||||
if (q == bio->bi_disk->queue)
|
||||
if (q == bio->bi_bdev->bd_disk->queue)
|
||||
bio_list_add(&same, bio);
|
||||
else
|
||||
bio_list_add(&lower, bio);
|
||||
@@ -1014,7 +999,7 @@ static blk_qc_t __submit_bio_noacct_mq(struct bio *bio)
|
||||
current->bio_list = bio_list;
|
||||
|
||||
do {
|
||||
struct gendisk *disk = bio->bi_disk;
|
||||
struct gendisk *disk = bio->bi_bdev->bd_disk;
|
||||
|
||||
if (unlikely(bio_queue_enter(bio) != 0))
|
||||
continue;
|
||||
@@ -1057,7 +1042,7 @@ blk_qc_t submit_bio_noacct(struct bio *bio)
|
||||
return BLK_QC_T_NONE;
|
||||
}
|
||||
|
||||
if (!bio->bi_disk->fops->submit_bio)
|
||||
if (!bio->bi_bdev->bd_disk->fops->submit_bio)
|
||||
return __submit_bio_noacct_mq(bio);
|
||||
return __submit_bio_noacct(bio);
|
||||
}
|
||||
@@ -1069,7 +1054,7 @@ EXPORT_SYMBOL(submit_bio_noacct);
|
||||
*
|
||||
* submit_bio() is used to submit I/O requests to block devices. It is passed a
|
||||
* fully set up &struct bio that describes the I/O that needs to be done. The
|
||||
* bio will be send to the device described by the bi_disk and bi_partno fields.
|
||||
* bio will be send to the device described by the bi_bdev field.
|
||||
*
|
||||
* The success/failure status of the request, along with notification of
|
||||
* completion, is delivered asynchronously through the ->bi_end_io() callback
|
||||
@@ -1089,7 +1074,8 @@ blk_qc_t submit_bio(struct bio *bio)
|
||||
unsigned int count;
|
||||
|
||||
if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME))
|
||||
count = queue_logical_block_size(bio->bi_disk->queue) >> 9;
|
||||
count = queue_logical_block_size(
|
||||
bio->bi_bdev->bd_disk->queue) >> 9;
|
||||
else
|
||||
count = bio_sectors(bio);
|
||||
|
||||
@@ -1313,7 +1299,11 @@ void blk_account_io_start(struct request *rq)
|
||||
if (!blk_do_io_stat(rq))
|
||||
return;
|
||||
|
||||
rq->part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
|
||||
/* passthrough requests can hold bios that do not have ->bi_bdev set */
|
||||
if (rq->bio && rq->bio->bi_bdev)
|
||||
rq->part = rq->bio->bi_bdev;
|
||||
else
|
||||
rq->part = rq->rq_disk->part0;
|
||||
|
||||
part_stat_lock();
|
||||
update_io_ticks(rq->part, jiffies, false);
|
||||
@@ -1336,14 +1326,17 @@ static unsigned long __part_start_io_acct(struct block_device *part,
|
||||
return now;
|
||||
}
|
||||
|
||||
unsigned long part_start_io_acct(struct gendisk *disk, struct block_device **part,
|
||||
struct bio *bio)
|
||||
/**
|
||||
* bio_start_io_acct - start I/O accounting for bio based drivers
|
||||
* @bio: bio to start account for
|
||||
*
|
||||
* Returns the start time that should be passed back to bio_end_io_acct().
|
||||
*/
|
||||
unsigned long bio_start_io_acct(struct bio *bio)
|
||||
{
|
||||
*part = disk_map_sector_rcu(disk, bio->bi_iter.bi_sector);
|
||||
|
||||
return __part_start_io_acct(*part, bio_sectors(bio), bio_op(bio));
|
||||
return __part_start_io_acct(bio->bi_bdev, bio_sectors(bio), bio_op(bio));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(part_start_io_acct);
|
||||
EXPORT_SYMBOL_GPL(bio_start_io_acct);
|
||||
|
||||
unsigned long disk_start_io_acct(struct gendisk *disk, unsigned int sectors,
|
||||
unsigned int op)
|
||||
@@ -1366,12 +1359,12 @@ static void __part_end_io_acct(struct block_device *part, unsigned int op,
|
||||
part_stat_unlock();
|
||||
}
|
||||
|
||||
void part_end_io_acct(struct block_device *part, struct bio *bio,
|
||||
unsigned long start_time)
|
||||
void bio_end_io_acct_remapped(struct bio *bio, unsigned long start_time,
|
||||
struct block_device *orig_bdev)
|
||||
{
|
||||
__part_end_io_acct(part, bio_op(bio), start_time);
|
||||
__part_end_io_acct(orig_bdev, bio_op(bio), start_time);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(part_end_io_acct);
|
||||
EXPORT_SYMBOL_GPL(bio_end_io_acct_remapped);
|
||||
|
||||
void disk_end_io_acct(struct gendisk *disk, unsigned int op,
|
||||
unsigned long start_time)
|
||||
|
||||
@@ -164,10 +164,12 @@ static struct bio *blk_crypto_clone_bio(struct bio *bio_src)
|
||||
struct bio_vec bv;
|
||||
struct bio *bio;
|
||||
|
||||
bio = bio_alloc_bioset(GFP_NOIO, bio_segments(bio_src), NULL);
|
||||
bio = bio_kmalloc(GFP_NOIO, bio_segments(bio_src));
|
||||
if (!bio)
|
||||
return NULL;
|
||||
bio->bi_disk = bio_src->bi_disk;
|
||||
bio->bi_bdev = bio_src->bi_bdev;
|
||||
if (bio_flagged(bio_src, BIO_REMAPPED))
|
||||
bio_set_flag(bio, BIO_REMAPPED);
|
||||
bio->bi_opf = bio_src->bi_opf;
|
||||
bio->bi_ioprio = bio_src->bi_ioprio;
|
||||
bio->bi_write_hint = bio_src->bi_write_hint;
|
||||
|
||||
+1
-1
@@ -280,7 +280,7 @@ bool __blk_crypto_bio_prep(struct bio **bio_ptr)
|
||||
* Success if device supports the encryption context, or if we succeeded
|
||||
* in falling back to the crypto API.
|
||||
*/
|
||||
if (blk_ksm_crypto_cfg_supported(bio->bi_disk->queue->ksm,
|
||||
if (blk_ksm_crypto_cfg_supported(bio->bi_bdev->bd_disk->queue->ksm,
|
||||
&bc_key->crypto_cfg))
|
||||
return true;
|
||||
|
||||
|
||||
+5
-9
@@ -31,8 +31,7 @@ static void blk_end_sync_rq(struct request *rq, blk_status_t error)
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_execute_rq_nowait - insert a request into queue for execution
|
||||
* @q: queue to insert the request in
|
||||
* blk_execute_rq_nowait - insert a request to I/O scheduler for execution
|
||||
* @bd_disk: matching gendisk
|
||||
* @rq: request to insert
|
||||
* @at_head: insert request at head or tail of queue
|
||||
@@ -45,9 +44,8 @@ static void blk_end_sync_rq(struct request *rq, blk_status_t error)
|
||||
* Note:
|
||||
* This function will invoke @done directly if the queue is dead.
|
||||
*/
|
||||
void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
|
||||
struct request *rq, int at_head,
|
||||
rq_end_io_fn *done)
|
||||
void blk_execute_rq_nowait(struct gendisk *bd_disk, struct request *rq,
|
||||
int at_head, rq_end_io_fn *done)
|
||||
{
|
||||
WARN_ON(irqs_disabled());
|
||||
WARN_ON(!blk_rq_is_passthrough(rq));
|
||||
@@ -67,7 +65,6 @@ EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
|
||||
|
||||
/**
|
||||
* blk_execute_rq - insert a request into queue for execution
|
||||
* @q: queue to insert the request in
|
||||
* @bd_disk: matching gendisk
|
||||
* @rq: request to insert
|
||||
* @at_head: insert request at head or tail of queue
|
||||
@@ -76,14 +73,13 @@ EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
|
||||
* Insert a fully prepared request at the back of the I/O scheduler queue
|
||||
* for execution and wait for completion.
|
||||
*/
|
||||
void blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
|
||||
struct request *rq, int at_head)
|
||||
void blk_execute_rq(struct gendisk *bd_disk, struct request *rq, int at_head)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(wait);
|
||||
unsigned long hang_check;
|
||||
|
||||
rq->end_io_data = &wait;
|
||||
blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
|
||||
blk_execute_rq_nowait(bd_disk, rq, at_head, blk_end_sync_rq);
|
||||
|
||||
/* Prevent hang_check timer from firing at us during very long I/O */
|
||||
hang_check = sysctl_hung_task_timeout_secs;
|
||||
|
||||
+6
-11
@@ -432,23 +432,18 @@ void blk_insert_flush(struct request *rq)
|
||||
/**
|
||||
* blkdev_issue_flush - queue a flush
|
||||
* @bdev: blockdev to issue flush for
|
||||
* @gfp_mask: memory allocation flags (for bio_alloc)
|
||||
*
|
||||
* Description:
|
||||
* Issue a flush for the block device in question.
|
||||
*/
|
||||
int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask)
|
||||
int blkdev_issue_flush(struct block_device *bdev)
|
||||
{
|
||||
struct bio *bio;
|
||||
int ret = 0;
|
||||
struct bio bio;
|
||||
|
||||
bio = bio_alloc(gfp_mask, 0);
|
||||
bio_set_dev(bio, bdev);
|
||||
bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
|
||||
|
||||
ret = submit_bio_wait(bio);
|
||||
bio_put(bio);
|
||||
return ret;
|
||||
bio_init(&bio, NULL, 0);
|
||||
bio_set_dev(&bio, bdev);
|
||||
bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
|
||||
return submit_bio_wait(&bio);
|
||||
}
|
||||
EXPORT_SYMBOL(blkdev_issue_flush);
|
||||
|
||||
|
||||
+8
-9
@@ -298,14 +298,13 @@ split:
|
||||
* Split a bio into two bios, chain the two bios, submit the second half and
|
||||
* store a pointer to the first half in *@bio. If the second bio is still too
|
||||
* big it will be split by a recursive call to this function. Since this
|
||||
* function may allocate a new bio from @bio->bi_disk->queue->bio_split, it is
|
||||
* the responsibility of the caller to ensure that
|
||||
* @bio->bi_disk->queue->bio_split is only released after processing of the
|
||||
* split bio has finished.
|
||||
* function may allocate a new bio from q->bio_split, it is the responsibility
|
||||
* of the caller to ensure that q->bio_split is only released after processing
|
||||
* of the split bio has finished.
|
||||
*/
|
||||
void __blk_queue_split(struct bio **bio, unsigned int *nr_segs)
|
||||
{
|
||||
struct request_queue *q = (*bio)->bi_disk->queue;
|
||||
struct request_queue *q = (*bio)->bi_bdev->bd_disk->queue;
|
||||
struct bio *split = NULL;
|
||||
|
||||
switch (bio_op(*bio)) {
|
||||
@@ -358,9 +357,9 @@ void __blk_queue_split(struct bio **bio, unsigned int *nr_segs)
|
||||
*
|
||||
* Split a bio into two bios, chains the two bios, submit the second half and
|
||||
* store a pointer to the first half in *@bio. Since this function may allocate
|
||||
* a new bio from @bio->bi_disk->queue->bio_split, it is the responsibility of
|
||||
* the caller to ensure that @bio->bi_disk->queue->bio_split is only released
|
||||
* after processing of the split bio has finished.
|
||||
* a new bio from q->bio_split, it is the responsibility of the caller to ensure
|
||||
* that q->bio_split is only released after processing of the split bio has
|
||||
* finished.
|
||||
*/
|
||||
void blk_queue_split(struct bio **bio)
|
||||
{
|
||||
@@ -866,7 +865,7 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
|
||||
return false;
|
||||
|
||||
/* must be same device */
|
||||
if (rq->rq_disk != bio->bi_disk)
|
||||
if (rq->rq_disk != bio->bi_bdev->bd_disk)
|
||||
return false;
|
||||
|
||||
/* only merge integrity protected bio into ditto rq */
|
||||
|
||||
+61
-8
@@ -1646,6 +1646,42 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
|
||||
}
|
||||
EXPORT_SYMBOL(blk_mq_run_hw_queue);
|
||||
|
||||
/*
|
||||
* Is the request queue handled by an IO scheduler that does not respect
|
||||
* hardware queues when dispatching?
|
||||
*/
|
||||
static bool blk_mq_has_sqsched(struct request_queue *q)
|
||||
{
|
||||
struct elevator_queue *e = q->elevator;
|
||||
|
||||
if (e && e->type->ops.dispatch_request &&
|
||||
!(e->type->elevator_features & ELEVATOR_F_MQ_AWARE))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_hw_ctx *hctx;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
hctx = blk_mq_map_queue_type(q, HCTX_TYPE_DEFAULT,
|
||||
raw_smp_processor_id());
|
||||
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.
|
||||
@@ -1653,14 +1689,23 @@ EXPORT_SYMBOL(blk_mq_run_hw_queue);
|
||||
*/
|
||||
void blk_mq_run_hw_queues(struct request_queue *q, bool async)
|
||||
{
|
||||
struct blk_mq_hw_ctx *hctx;
|
||||
struct blk_mq_hw_ctx *hctx, *sq_hctx;
|
||||
int i;
|
||||
|
||||
sq_hctx = NULL;
|
||||
if (blk_mq_has_sqsched(q))
|
||||
sq_hctx = blk_mq_get_sq_hctx(q);
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
if (blk_mq_hctx_stopped(hctx))
|
||||
continue;
|
||||
|
||||
blk_mq_run_hw_queue(hctx, async);
|
||||
/*
|
||||
* 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);
|
||||
@@ -1672,14 +1717,23 @@ EXPORT_SYMBOL(blk_mq_run_hw_queues);
|
||||
*/
|
||||
void blk_mq_delay_run_hw_queues(struct request_queue *q, unsigned long msecs)
|
||||
{
|
||||
struct blk_mq_hw_ctx *hctx;
|
||||
struct blk_mq_hw_ctx *hctx, *sq_hctx;
|
||||
int i;
|
||||
|
||||
sq_hctx = NULL;
|
||||
if (blk_mq_has_sqsched(q))
|
||||
sq_hctx = blk_mq_get_sq_hctx(q);
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
if (blk_mq_hctx_stopped(hctx))
|
||||
continue;
|
||||
|
||||
blk_mq_delay_run_hw_queue(hctx, msecs);
|
||||
/*
|
||||
* 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);
|
||||
@@ -2128,7 +2182,7 @@ static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq)
|
||||
*/
|
||||
blk_qc_t blk_mq_submit_bio(struct bio *bio)
|
||||
{
|
||||
struct request_queue *q = bio->bi_disk->queue;
|
||||
struct request_queue *q = bio->bi_bdev->bd_disk->queue;
|
||||
const int is_sync = op_is_sync(bio->bi_opf);
|
||||
const int is_flush_fua = op_is_flush(bio->bi_opf);
|
||||
struct blk_mq_alloc_data data = {
|
||||
@@ -2653,7 +2707,6 @@ blk_mq_alloc_hctx(struct request_queue *q, struct blk_mq_tag_set *set,
|
||||
goto free_hctx;
|
||||
|
||||
atomic_set(&hctx->nr_active, 0);
|
||||
atomic_set(&hctx->elevator_queued, 0);
|
||||
if (node == NUMA_NO_NODE)
|
||||
node = set->numa_node;
|
||||
hctx->numa_node = node;
|
||||
|
||||
+39
-2
@@ -60,6 +60,7 @@ void blk_set_default_limits(struct queue_limits *lim)
|
||||
lim->io_opt = 0;
|
||||
lim->misaligned = 0;
|
||||
lim->zoned = BLK_ZONED_NONE;
|
||||
lim->zone_write_granularity = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(blk_set_default_limits);
|
||||
|
||||
@@ -366,6 +367,28 @@ void blk_queue_physical_block_size(struct request_queue *q, unsigned int size)
|
||||
}
|
||||
EXPORT_SYMBOL(blk_queue_physical_block_size);
|
||||
|
||||
/**
|
||||
* blk_queue_zone_write_granularity - set zone write granularity for the queue
|
||||
* @q: the request queue for the zoned device
|
||||
* @size: the zone write granularity size, in bytes
|
||||
*
|
||||
* Description:
|
||||
* This should be set to the lowest possible size allowing to write in
|
||||
* sequential zones of a zoned block device.
|
||||
*/
|
||||
void blk_queue_zone_write_granularity(struct request_queue *q,
|
||||
unsigned int size)
|
||||
{
|
||||
if (WARN_ON_ONCE(!blk_queue_is_zoned(q)))
|
||||
return;
|
||||
|
||||
q->limits.zone_write_granularity = size;
|
||||
|
||||
if (q->limits.zone_write_granularity < q->limits.logical_block_size)
|
||||
q->limits.zone_write_granularity = q->limits.logical_block_size;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_queue_zone_write_granularity);
|
||||
|
||||
/**
|
||||
* blk_queue_alignment_offset - set physical block alignment offset
|
||||
* @q: the request queue for the device
|
||||
@@ -631,6 +654,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
t->discard_granularity;
|
||||
}
|
||||
|
||||
t->zone_write_granularity = max(t->zone_write_granularity,
|
||||
b->zone_write_granularity);
|
||||
t->zoned = max(t->zoned, b->zoned);
|
||||
return ret;
|
||||
}
|
||||
@@ -847,6 +872,8 @@ EXPORT_SYMBOL_GPL(blk_queue_can_use_dma_map_merging);
|
||||
*/
|
||||
void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
|
||||
switch (model) {
|
||||
case BLK_ZONED_HM:
|
||||
/*
|
||||
@@ -865,7 +892,7 @@ void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
|
||||
* we do nothing special as far as the block layer is concerned.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) ||
|
||||
disk_has_partitions(disk))
|
||||
!xa_empty(&disk->part_tbl))
|
||||
model = BLK_ZONED_NONE;
|
||||
break;
|
||||
case BLK_ZONED_NONE:
|
||||
@@ -875,7 +902,17 @@ void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
|
||||
break;
|
||||
}
|
||||
|
||||
disk->queue->limits.zoned = model;
|
||||
q->limits.zoned = model;
|
||||
if (model != BLK_ZONED_NONE) {
|
||||
/*
|
||||
* Set the zone write granularity to the device logical block
|
||||
* size by default. The driver can change this value if needed.
|
||||
*/
|
||||
blk_queue_zone_write_granularity(q,
|
||||
queue_logical_block_size(q));
|
||||
} else {
|
||||
blk_queue_clear_zone_settings(q);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_queue_set_zoned);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user