]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
block: Fix handling of non-empty flush write requests to zones
authorDamien Le Moal <dlemoal@kernel.org>
Wed, 1 May 2024 11:09:02 +0000 (20:09 +0900)
committerJens Axboe <axboe@kernel.dk>
Wed, 1 May 2024 14:08:43 +0000 (08:08 -0600)
Zone write plugging ignores empty (no data) flush operations but handles
flush BIOs that have data to ensure that the flush machinery generated
write is processed in order. However, the call to
blk_zone_write_plug_attempt_merge() which sets a request
RQF_ZONE_WRITE_PLUGGING flag is called after blk_insert_flush(), thus
missing indicating that a non empty flush request completion needs
handling by zone write plugging.

Fix this by moving the call to blk_zone_write_plug_attempt_merge()
before blk_insert_flush(). And while at it, rename that function as
blk_zone_write_plug_init_request() to be clear that it is not just about
merging plugged BIOs in the request. While at it, also add a WARN_ONCE()
check that the zone write plug for the request is not NULL.

Fixes: dd291d77cc90 ("block: Introduce zone write plugging")
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Link: https://lore.kernel.org/r/20240501110907.96950-10-dlemoal@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-mq.c
block/blk-zoned.c
block/blk.h

index 434d45219e2347c67379fa3aefa5c2f0058f6207..0fae9bd0ecd417a17d220de50a3f22b3f7bb5dca 100644 (file)
@@ -3001,12 +3001,12 @@ new_request:
                return;
        }
 
+       if (bio_zone_write_plugging(bio))
+               blk_zone_write_plug_init_request(rq);
+
        if (op_is_flush(bio->bi_opf) && blk_insert_flush(rq))
                return;
 
-       if (bio_zone_write_plugging(bio))
-               blk_zone_write_plug_attempt_merge(rq);
-
        if (plug) {
                blk_add_rq_to_plug(plug, rq);
                return;
index 1e5f362f0409549fad802db38c95d6f4332b1059..cd0049f5bf2ff16c4009bfdaef8962f4b4aaffbd 100644 (file)
@@ -874,8 +874,9 @@ void blk_zone_write_plug_bio_merged(struct bio *bio)
 
        /*
         * If the BIO was already plugged, then we were called through
-        * blk_zone_write_plug_attempt_merge() -> blk_attempt_bio_merge().
-        * For this case, blk_zone_write_plug_attempt_merge() will handle the
+        * blk_zone_write_plug_init_request() -> blk_attempt_bio_merge().
+        * For this case, we already hold a reference on the zone write plug for
+        * the BIO and blk_zone_write_plug_init_request() will handle the
         * zone write pointer offset update.
         */
        if (bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING))
@@ -899,7 +900,7 @@ void blk_zone_write_plug_bio_merged(struct bio *bio)
  * already went through zone write plugging (either a new BIO or one that was
  * unplugged).
  */
-void blk_zone_write_plug_attempt_merge(struct request *req)
+void blk_zone_write_plug_init_request(struct request *req)
 {
        sector_t req_back_sector = blk_rq_pos(req) + blk_rq_sectors(req);
        struct request_queue *q = req->q;
@@ -910,6 +911,9 @@ void blk_zone_write_plug_attempt_merge(struct request *req)
        unsigned long flags;
        struct bio *bio;
 
+       if (WARN_ON_ONCE(!zwplug))
+               return;
+
        /*
         * Indicate that completion of this request needs to be handled with
         * blk_zone_write_plug_complete_request(), which will drop the reference
@@ -1269,7 +1273,7 @@ void blk_zone_write_plug_complete_request(struct request *req)
 
        /*
         * Drop the reference we took when the request was initialized in
-        * blk_zone_write_plug_attempt_merge().
+        * blk_zone_write_plug_init_request().
         */
        disk_put_zone_wplug(zwplug);
 
index 1140c4a0be03d4997f7376612bb053b99d7dd7c9..8a62b861453cc72d68a816c47d8b4e18fb527c9e 100644 (file)
@@ -427,7 +427,7 @@ static inline bool bio_is_zone_append(struct bio *bio)
                bio_flagged(bio, BIO_EMULATES_ZONE_APPEND);
 }
 void blk_zone_write_plug_bio_merged(struct bio *bio);
-void blk_zone_write_plug_attempt_merge(struct request *rq);
+void blk_zone_write_plug_init_request(struct request *rq);
 static inline void blk_zone_update_request_bio(struct request *rq,
                                               struct bio *bio)
 {
@@ -481,7 +481,7 @@ static inline bool bio_is_zone_append(struct bio *bio)
 static inline void blk_zone_write_plug_bio_merged(struct bio *bio)
 {
 }
-static inline void blk_zone_write_plug_attempt_merge(struct request *rq)
+static inline void blk_zone_write_plug_init_request(struct request *rq)
 {
 }
 static inline void blk_zone_update_request_bio(struct request *rq,