diff --git a/block/blk-core.c b/block/blk-core.c index b6568200e9fa..411f005e6b1f 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -882,8 +882,41 @@ end_io: } EXPORT_SYMBOL(submit_bio_noacct); +#ifdef CONFIG_BLK_DEV_ZONED +/** + * blk_bio_is_seq_zoned_write() - Check if @bio requires write serialization. + * @bio: Bio to examine. + * + * Note: REQ_OP_ZONE_APPEND bios do not require serialization. + * Note: this function treats conventional zones on a zoned block device as + * sequential zones. This is fine since zoned UFS devices have no conventional + * zones. + */ +static bool blk_bio_is_seq_zoned_write(struct bio *bio) +{ + if (!bdev_is_zoned(bio->bi_bdev)) + return false; + + return bio_op(bio) == REQ_OP_WRITE || + bio_op(bio) == REQ_OP_WRITE_ZEROES; +} +#else +static bool blk_bio_is_seq_zoned_write(struct bio *bio) +{ + return false; +} +#endif + static void bio_set_ioprio(struct bio *bio) { + /* + * Do not set the I/O priority of sequential zoned write bios because + * this could lead to reordering by the mq-deadline I/O scheduler and + * hence to unaligned write errors. + */ + if (blk_bio_is_seq_zoned_write(bio)) + return; + /* Nobody set ioprio so far? Initialize it based on task's nice value */ if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) == IOPRIO_CLASS_NONE) bio->bi_ioprio = get_current_ioprio();