mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
synced 2025-09-14 11:19:08 +10:00
block: Introduce bio_needs_zone_write_plugging()
commitf70291411b
upstream. In preparation for fixing device mapper zone write handling, introduce the inline helper function bio_needs_zone_write_plugging() to test if a BIO requires handling through zone write plugging using the function blk_zone_plug_bio(). This function returns true for any write (op_is_write(bio) == true) operation directed at a zoned block device using zone write plugging, that is, a block device with a disk that has a zone write plug hash table. This helper allows simplifying the check on entry to blk_zone_plug_bio() and used in to protect calls to it for blk-mq devices and DM devices. Fixes:f211268ed1
("dm: Use the block layer zone append emulation") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Link: https://lore.kernel.org/r/20250625093327.548866-3-dlemoal@kernel.org Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
93795b80af
commit
4b3f4afaea
@ -3117,8 +3117,10 @@ void blk_mq_submit_bio(struct bio *bio)
|
||||
if (blk_mq_attempt_bio_merge(q, bio, nr_segs))
|
||||
goto queue_exit;
|
||||
|
||||
if (blk_queue_is_zoned(q) && blk_zone_plug_bio(bio, nr_segs))
|
||||
goto queue_exit;
|
||||
if (bio_needs_zone_write_plugging(bio)) {
|
||||
if (blk_zone_plug_bio(bio, nr_segs))
|
||||
goto queue_exit;
|
||||
}
|
||||
|
||||
new_request:
|
||||
if (rq) {
|
||||
|
@ -1116,25 +1116,7 @@ bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs)
|
||||
{
|
||||
struct block_device *bdev = bio->bi_bdev;
|
||||
|
||||
if (!bdev->bd_disk->zone_wplugs_hash)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If the BIO already has the plugging flag set, then it was already
|
||||
* handled through this path and this is a submission from the zone
|
||||
* plug bio submit work.
|
||||
*/
|
||||
if (bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* We do not need to do anything special for empty flush BIOs, e.g
|
||||
* BIOs such as issued by blkdev_issue_flush(). The is because it is
|
||||
* the responsibility of the user to first wait for the completion of
|
||||
* write operations for flush to have any effect on the persistence of
|
||||
* the written data.
|
||||
*/
|
||||
if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
|
||||
if (WARN_ON_ONCE(!bdev->bd_disk->zone_wplugs_hash))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
@ -1802,7 +1802,9 @@ static inline bool dm_zone_bio_needs_split(struct mapped_device *md,
|
||||
}
|
||||
static inline bool dm_zone_plug_bio(struct mapped_device *md, struct bio *bio)
|
||||
{
|
||||
return dm_emulate_zone_append(md) && blk_zone_plug_bio(bio, 0);
|
||||
if (!bio_needs_zone_write_plugging(bio))
|
||||
return false;
|
||||
return blk_zone_plug_bio(bio, 0);
|
||||
}
|
||||
|
||||
static blk_status_t __send_zone_reset_all_emulated(struct clone_info *ci,
|
||||
|
@ -835,6 +835,55 @@ static inline unsigned int disk_nr_zones(struct gendisk *disk)
|
||||
{
|
||||
return disk->nr_zones;
|
||||
}
|
||||
|
||||
/**
|
||||
* bio_needs_zone_write_plugging - Check if a BIO needs to be handled with zone
|
||||
* write plugging
|
||||
* @bio: The BIO being submitted
|
||||
*
|
||||
* Return true whenever @bio execution needs to be handled through zone
|
||||
* write plugging (using blk_zone_plug_bio()). Return false otherwise.
|
||||
*/
|
||||
static inline bool bio_needs_zone_write_plugging(struct bio *bio)
|
||||
{
|
||||
enum req_op op = bio_op(bio);
|
||||
|
||||
/*
|
||||
* Only zoned block devices have a zone write plug hash table. But not
|
||||
* all of them have one (e.g. DM devices may not need one).
|
||||
*/
|
||||
if (!bio->bi_bdev->bd_disk->zone_wplugs_hash)
|
||||
return false;
|
||||
|
||||
/* Only write operations need zone write plugging. */
|
||||
if (!op_is_write(op))
|
||||
return false;
|
||||
|
||||
/* Ignore empty flush */
|
||||
if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
|
||||
return false;
|
||||
|
||||
/* Ignore BIOs that already have been handled by zone write plugging. */
|
||||
if (bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* All zone write operations must be handled through zone write plugging
|
||||
* using blk_zone_plug_bio().
|
||||
*/
|
||||
switch (op) {
|
||||
case REQ_OP_ZONE_APPEND:
|
||||
case REQ_OP_WRITE:
|
||||
case REQ_OP_WRITE_ZEROES:
|
||||
case REQ_OP_ZONE_FINISH:
|
||||
case REQ_OP_ZONE_RESET:
|
||||
case REQ_OP_ZONE_RESET_ALL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs);
|
||||
|
||||
/**
|
||||
@ -864,6 +913,12 @@ static inline unsigned int disk_nr_zones(struct gendisk *disk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool bio_needs_zone_write_plugging(struct bio *bio)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs)
|
||||
{
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user