[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251221025233.87087-5-agruenba@redhat.com>
Date: Sun, 21 Dec 2025 03:52:19 +0100
From: Andreas Gruenbacher <agruenba@...hat.com>
To: Christoph Hellwig <hch@...radead.org>,
Jens Axboe <axboe@...nel.dk>,
Chris Mason <clm@...com>,
David Sterba <dsterba@...e.com>,
Satya Tangirala <satyat@...gle.com>
Cc: Andreas Gruenbacher <agruenba@...hat.com>,
linux-block@...r.kernel.org,
linux-btrfs@...r.kernel.org,
linux-raid@...r.kernel.org,
dm-devel@...ts.linux.dev,
linux-kernel@...r.kernel.org
Subject: [RFC v2 04/17] bio: add bio_set_status
Add a bio_set_status(bio, status) helper that sets bio->bi_status to
status if status != BLK_STS_OK. Replace instances of this pattern in
the code with a call to the new helper.
The WRITE_ONCE() in bio_set_status() ensures that the compiler won't
reorder things in a weird way, but tearing is not an issue because
bi_status is a single-byte field.
Created with Coccinelle using the following semantic patch and option
'--disable-iso unlikely'.
(Coccinelle occasionally likes to add unnecessary curly braces
in if statements; those were removed by hand.)
@@
expression status;
struct bio *bio;
@@
- if (status)
- bio->bi_status = status;
+ bio_set_status(bio, status);
@@
expression status;
struct bio *bio;
@@
- if (unlikely(status))
- bio->bi_status = status;
+ if (unlikely(status))
+ bio_set_status(bio, status);
@@
expression status;
struct bio *bio;
@@
if (status) {
<...
- bio->bi_status = status;
+ bio_set_status(bio, status);
...>
}
@@
expression status;
struct bio *bio;
@@
if (status != BLK_STS_OK) {
<...
- bio->bi_status = status;
+ bio_set_status(bio, status);
...>
}
@@
expression status;
struct bio *bio;
statement S;
@@
if (status)
- bio->bi_status = status;
+ bio_set_status(bio, status);
else
S
Signed-off-by: Andreas Gruenbacher <agruenba@...hat.com>
---
block/blk-crypto-fallback.c | 4 ++--
block/blk-mq.c | 4 ++--
block/t10-pi.c | 2 +-
drivers/md/dm-cache-target.c | 3 ++-
drivers/md/dm.c | 3 +--
drivers/nvdimm/pmem.c | 2 +-
include/linux/bio.h | 16 ++++++++++++++++
7 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
index 86b27f96051a..a9cb5647879c 100644
--- a/block/blk-crypto-fallback.c
+++ b/block/blk-crypto-fallback.c
@@ -292,7 +292,7 @@ static bool blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr)
blk_st = blk_crypto_get_keyslot(blk_crypto_fallback_profile,
bc->bc_key, &slot);
if (blk_st != BLK_STS_OK) {
- src_bio->bi_status = blk_st;
+ bio_set_status(src_bio, blk_st);
goto out_put_enc_bio;
}
@@ -395,7 +395,7 @@ static void blk_crypto_fallback_decrypt_bio(struct work_struct *work)
blk_st = blk_crypto_get_keyslot(blk_crypto_fallback_profile,
bc->bc_key, &slot);
if (blk_st != BLK_STS_OK) {
- bio->bi_status = blk_st;
+ bio_set_status(bio, blk_st);
goto out_no_keyslot;
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index d626d32f6e57..9d1883d653c4 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -970,7 +970,7 @@ bool blk_update_request(struct request *req, blk_status_t error,
unsigned bio_bytes = min(bio->bi_iter.bi_size, nr_bytes);
if (unlikely(error))
- bio->bi_status = error;
+ bio_set_status(bio, error);
if (bio_bytes == bio->bi_iter.bi_size) {
req->bio = bio->bi_next;
@@ -3206,7 +3206,7 @@ void blk_mq_submit_bio(struct bio *bio)
ret = blk_crypto_rq_get_keyslot(rq);
if (ret != BLK_STS_OK) {
- bio->bi_status = ret;
+ bio_set_status(bio, ret);
bio_endio(bio);
blk_mq_free_request(rq);
return;
diff --git a/block/t10-pi.c b/block/t10-pi.c
index 0c4ed9702146..968cf1fe45f0 100644
--- a/block/t10-pi.c
+++ b/block/t10-pi.c
@@ -440,7 +440,7 @@ void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter)
kunmap_local(kaddr);
if (ret) {
- bio->bi_status = ret;
+ bio_set_status(bio, ret);
return;
}
}
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index a10d75a562db..03816f0dcb58 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -1190,7 +1190,8 @@ static void mg_complete(struct dm_cache_migration *mg, bool success)
if (success)
force_set_dirty(cache, cblock);
else if (mg->k.input)
- mg->overwrite_bio->bi_status = mg->k.input;
+ bio_set_status(mg->overwrite_bio,
+ mg->k.input);
else
mg->overwrite_bio->bi_status = BLK_STS_IOERR;
bio_endio(mg->overwrite_bio);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 6c83ab940af7..cbc64377fa96 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -983,8 +983,7 @@ static void __dm_io_complete(struct dm_io *io, bool first_stage)
queue_io(md, bio);
} else {
/* done with normal IO or empty flush */
- if (io_error)
- bio->bi_status = io_error;
+ bio_set_status(bio, io_error);
bio_endio(bio);
}
}
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 05785ff21a8b..4fdcbe56a3bc 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -222,7 +222,7 @@ static void pmem_submit_bio(struct bio *bio)
rc = pmem_do_read(pmem, bvec.bv_page, bvec.bv_offset,
iter.bi_sector, bvec.bv_len);
if (rc) {
- bio->bi_status = rc;
+ bio_set_status(bio, rc);
break;
}
}
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 16c1c85613b7..a1324ce61ebd 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -376,6 +376,22 @@ void submit_bio(struct bio *bio);
extern void bio_endio(struct bio *);
+/**
+ * bio_set_status - set the status of bio
+ * @bio: bio
+ * @status: a BLK_STS_* status code
+ *
+ * Set the status of @bio to @status unless @status is BLK_STS_OK (0). In bio
+ * chains, this function may be called repeatedly on the same bio. In that
+ * case, it can override a previous error, but it will never revert from an
+ * error back to BLK_STS_OK.
+ */
+static inline void bio_set_status(struct bio *bio, blk_status_t status)
+{
+ if (status != BLK_STS_OK)
+ WRITE_ONCE(bio->bi_status, status);
+}
+
static inline void bio_io_error(struct bio *bio)
{
bio->bi_status = BLK_STS_IOERR;
--
2.52.0
Powered by blists - more mailing lists