* [RFC 00/12] bio cleanups
@ 2025-12-08 12:10 Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 01/12] bio: rename bio_chain arguments Andreas Gruenbacher
` (12 more replies)
0 siblings, 13 replies; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
Satya Tangirala
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
Hello,
we are not quite careful enough about setting bio->bi_status in all
places (see BACKGROUND below). This patch queue tries to fix this by
systematically eliminating the direct assignments to bi_status sprinkled
all throughout the code. Please comment.
The first patch ("bio: rename bio_chain arguments") is an loosely
related cleanup. The remaining changes are:
- Use bio_io_error() in more places.
- Add a bio_set_errno() helper for setting bi_status based on an errno.
Use this helper throughout the code.
- Add a bio_set_status() helper for setting bi_status to a blk_status_t
status code. Use this helper in places in the code where it's
necessary, or at least useful without adding any overhead.
And on top of that, we have two more cleanups:
- Add a bio_endio_errno() helper that combines bio_set_errno() and
bio_endio().
- Add a bio_endio_status() helper that combines bio_set_status() and
bio_endio().
The patches are currently based on v6.18.
GIT tree:
https://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/log/?h=bio-cleanups
With these changes, only a few direct assignments to bio->bi_status
remain, in BTRFS and in MD, and SOME OF THOSE MAY BE UNSAFE. Could the
maintainers of those subsystems please have a look?
Once the remaining direct assignments to bi_status are gone, we may want
to think about "write protecting" bi_status to prevent unintended new
direct assignments from creeping back in.
BACKGROUND
'struct bio' objects start out with their bi_status field initialized to
BLK_STS_OK (0). When the bio completes, that field needs to be left
unchanged in case of success, and set to a BLK_STS_* error code
otherwise.
This is important when bios are chained (bio_chain()) because then,
multiple execution contexts will race updating the same bi_status field.
When an execution context resets bi_status to BLK_STS_OK (0) during bio
completion, this could hide the error code of the adjacent bio in the
chain.
When more than a single bio fails in a chain, we know that the resulting
bi_status will not be BLK_STS_OK, but we don't know which of the status
error codes will win.
CRYPTO FALLBACK (SATYA TANGIRALA?)
Related to chained bios but unrelated to setting bio->bi_status,
blk_crypto_fallback_encrypt_bio() in block/blk-crypto-fallback.c swaps
out bi_private and bi_end_io and reuses the same bio for downcalls, then
restores those fields in blk_crypto_fallback_decrypt_endio() before
calling bio_endio() again on the same bio. This will at the very least
break with chained bios because it will mess up __bi_remaining.
Thanks,
Andreas
Andreas Gruenbacher (12):
bio: rename bio_chain arguments
bio: use bio_io_error more often
bio: add bio_set_errno
bio: use bio_set_errno in more places
bio: add bio_set_status
bio: don't check target->bi_status on error
bio: use bio_set_status for BLK_STS_* status codes
bio: use bio_set_status in some more places
bio: switch to bio_set_status in submit_bio_noacct
bio: never set bi_status to BLK_STS_OK during completion
bio: add bio_endio_errno
bio: add bio_endio_status
block/bio-integrity-auto.c | 3 +--
block/bio.c | 25 ++++++++++++-------------
block/blk-core.c | 10 ++++------
block/blk-crypto-fallback.c | 22 +++++++++++-----------
block/blk-crypto-internal.h | 2 +-
block/blk-crypto.c | 4 ++--
block/blk-merge.c | 6 ++----
block/blk-mq.c | 11 ++++-------
block/fops.c | 6 ++----
block/t10-pi.c | 2 +-
drivers/block/aoe/aoecmd.c | 8 ++++----
drivers/block/aoe/aoedev.c | 2 +-
drivers/block/drbd/drbd_int.h | 3 +--
drivers/block/drbd/drbd_req.c | 9 +++------
drivers/block/ps3vram.c | 3 +--
drivers/block/zram/zram_drv.c | 4 ++--
drivers/md/bcache/bcache.h | 3 +--
drivers/md/bcache/request.c | 8 +++-----
drivers/md/dm-cache-target.c | 9 +++++----
drivers/md/dm-ebs-target.c | 2 +-
drivers/md/dm-flakey.c | 2 +-
drivers/md/dm-integrity.c | 30 +++++++++++-------------------
drivers/md/dm-mpath.c | 6 ++----
drivers/md/dm-pcache/dm_pcache.c | 3 +--
drivers/md/dm-raid1.c | 7 +++----
drivers/md/dm-thin.c | 5 ++---
drivers/md/dm-vdo/data-vio.c | 3 +--
drivers/md/dm-verity-target.c | 2 +-
drivers/md/dm-writecache.c | 7 +++----
drivers/md/dm-zoned-target.c | 2 +-
drivers/md/dm.c | 4 +---
drivers/md/md.c | 8 +++-----
drivers/md/raid1-10.c | 3 +--
drivers/md/raid1.c | 2 +-
drivers/md/raid10.c | 18 +++++++-----------
drivers/md/raid5.c | 4 ++--
drivers/nvdimm/btt.c | 4 ++--
drivers/nvdimm/pmem.c | 7 ++-----
fs/btrfs/bio.c | 8 ++++----
fs/btrfs/direct-io.c | 2 +-
fs/btrfs/raid56.c | 6 ++----
fs/crypto/bio.c | 2 +-
fs/erofs/fileio.c | 2 +-
fs/erofs/fscache.c | 4 ++--
fs/f2fs/data.c | 6 +++---
fs/f2fs/segment.c | 3 +--
fs/iomap/ioend.c | 3 +--
fs/verity/verify.c | 2 +-
fs/xfs/xfs_aops.c | 3 +--
fs/xfs/xfs_zone_alloc.c | 2 +-
include/linux/bio.h | 30 +++++++++++++++++++++++++++---
51 files changed, 153 insertions(+), 179 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 27+ messages in thread
* [RFC 01/12] bio: rename bio_chain arguments
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-16 7:57 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 02/12] bio: use bio_io_error more often Andreas Gruenbacher
` (11 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
Use the same argument names in bio_chain() as in bio_chain_and_submit()
to be consistent. Slightly improve the function description.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/bio.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/block/bio.c b/block/bio.c
index b3a79285c278..3f408e1ba13f 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -327,22 +327,22 @@ static void bio_chain_endio(struct bio *bio)
/**
* bio_chain - chain bio completions
- * @bio: the target bio
- * @parent: the parent bio of @bio
+ * @prev: the bio to chain
+ * @new: the bio to chain to
*
- * The caller won't have a bi_end_io called when @bio completes - instead,
- * @parent's bi_end_io won't be called until both @parent and @bio have
- * completed; the chained bio will also be freed when it completes.
+ * The caller won't have a bi_end_io called when @prev completes. Instead,
+ * @new's bi_end_io will be called once both @new and @prev have completed.
+ * Like an unchained bio, @prev will be put when it completes.
*
- * The caller must not set bi_private or bi_end_io in @bio.
+ * The caller must not set bi_private or bi_end_io in @prev.
*/
-void bio_chain(struct bio *bio, struct bio *parent)
+void bio_chain(struct bio *prev, struct bio *new)
{
- BUG_ON(bio->bi_private || bio->bi_end_io);
+ BUG_ON(prev->bi_private || prev->bi_end_io);
- bio->bi_private = parent;
- bio->bi_end_io = bio_chain_endio;
- bio_inc_remaining(parent);
+ prev->bi_private = new;
+ prev->bi_end_io = bio_chain_endio;
+ bio_inc_remaining(new);
}
EXPORT_SYMBOL(bio_chain);
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 02/12] bio: use bio_io_error more often
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 01/12] bio: rename bio_chain arguments Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-16 7:57 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 03/12] bio: add bio_set_errno Andreas Gruenbacher
` (10 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
Instead of setting bio->bi_status to BLK_STS_IOERR and calling
bio_endio(bio), use the shorthand bio_io_error(bio).
Created with Coccinelle using the following semantic patch:
@@
struct bio *bio;
@@
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/fops.c | 3 +--
drivers/block/drbd/drbd_int.h | 3 +--
drivers/md/bcache/bcache.h | 3 +--
drivers/md/bcache/request.c | 6 ++----
drivers/md/dm-mpath.c | 3 +--
drivers/md/dm-writecache.c | 3 +--
fs/f2fs/segment.c | 3 +--
7 files changed, 8 insertions(+), 16 deletions(-)
diff --git a/block/fops.c b/block/fops.c
index 5e3db9fead77..b4f911273289 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -221,8 +221,7 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
ret = blkdev_iov_iter_get_pages(bio, iter, bdev);
if (unlikely(ret)) {
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
break;
}
if (iocb->ki_flags & IOCB_NOWAIT) {
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index f6d6276974ee..32639e8ea72a 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1491,8 +1491,7 @@ static inline void drbd_submit_bio_noacct(struct drbd_device *device,
__release(local);
if (!bio->bi_bdev) {
drbd_err(device, "drbd_submit_bio_noacct: bio->bi_bdev == NULL\n");
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
return;
}
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 1d33e40d26ea..7ad7c778d8ff 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -940,8 +940,7 @@ static inline void closure_bio_submit(struct cache_set *c,
{
closure_get(cl);
if (unlikely(test_bit(CACHE_SET_IO_DISABLE, &c->flags))) {
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
return;
}
submit_bio_noacct(bio);
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index af345dc6fde1..acccecd061ea 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -1192,8 +1192,7 @@ void cached_dev_submit_bio(struct bio *bio)
if (unlikely((d->c && test_bit(CACHE_SET_IO_DISABLE, &d->c->flags)) ||
dc->io_disable)) {
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
return;
}
@@ -1296,8 +1295,7 @@ void flash_dev_submit_bio(struct bio *bio)
struct bcache_device *d = bio->bi_bdev->bd_disk->private_data;
if (unlikely(d->c && test_bit(CACHE_SET_IO_DISABLE, &d->c->flags))) {
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
return;
}
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index aaf4a0a4b0eb..1424ef75d088 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -719,8 +719,7 @@ static void process_queued_bios(struct work_struct *work)
r = __multipath_map_bio(m, bio, mpio);
switch (r) {
case DM_MAPIO_KILL:
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
break;
case DM_MAPIO_REQUEUE:
bio->bi_status = BLK_STS_DM_REQUEUE;
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index d8de4a3076a1..4f70e2673e4b 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -1877,8 +1877,7 @@ static void __writecache_writeback_pmem(struct dm_writecache *wc, struct writeba
if (WC_MODE_FUA(wc))
bio->bi_opf |= REQ_FUA;
if (writecache_has_error(wc)) {
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
} else if (unlikely(!bio_sectors(bio))) {
bio->bi_status = BLK_STS_OK;
bio_endio(bio);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index b45eace879d7..6444d572f0c7 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -4090,8 +4090,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
if (fio->bio && *(fio->bio)) {
struct bio *bio = *(fio->bio);
- bio->bi_status = BLK_STS_IOERR;
- bio_endio(bio);
+ bio_io_error(bio);
*(fio->bio) = NULL;
}
return err;
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 03/12] bio: add bio_set_errno
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 01/12] bio: rename bio_chain arguments Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 02/12] bio: use bio_io_error more often Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-16 7:58 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 04/12] bio: use bio_set_errno in more places Andreas Gruenbacher
` (9 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
Add a bio_set_errno(bio, errno) helper that sets bio->bi_status to
errno_to_blk_status(errno) if errno != 0. Replace instances of this
pattern in the code with a call to the new helper.
The WRITE_ONCE() in bio_set_errno() ensures that the compiler won't
reorder things in a weird way, but it isn't needed to prevent tearing
because a single-byte field like bi_status cannot tear.
Created with Coccinelle using the following semantic patch:
@@
struct bio *bio;
expression errno;
@@
- if (errno)
- bio->bi_status = errno_to_blk_status(errno);
+ bio_set_errno(bio, errno);
@@
struct bio *bio;
expression errno;
@@
- if (unlikely(errno))
- bio->bi_status = errno_to_blk_status(errno);
+ bio_set_errno(bio, errno);
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
drivers/block/drbd/drbd_req.c | 3 +--
drivers/nvdimm/pmem.c | 3 +--
include/linux/bio.h | 8 ++++++++
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index d15826f6ee81..bd4bc882cc5a 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -176,8 +176,7 @@ void start_new_tl_epoch(struct drbd_connection *connection)
void complete_master_bio(struct drbd_device *device,
struct bio_and_error *m)
{
- if (unlikely(m->error))
- m->bio->bi_status = errno_to_blk_status(m->error);
+ bio_set_errno(m->bio, m->error);
bio_endio(m->bio);
dec_ap_bio(device);
}
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 05785ff21a8b..a2f8b5a85326 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -232,8 +232,7 @@ static void pmem_submit_bio(struct bio *bio)
if (bio->bi_opf & REQ_FUA)
ret = nvdimm_flush(nd_region, bio);
- if (ret)
- bio->bi_status = errno_to_blk_status(ret);
+ bio_set_errno(bio, ret);
bio_endio(bio);
}
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 16c1c85613b7..38ebf03036cb 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -389,6 +389,14 @@ static inline void bio_wouldblock_error(struct bio *bio)
bio_endio(bio);
}
+blk_status_t errno_to_blk_status(int errno);
+
+static inline void bio_set_errno(struct bio *bio, int errno)
+{
+ if (errno)
+ WRITE_ONCE(bio->bi_status, errno_to_blk_status(errno));
+}
+
/*
* Calculate number of bvec segments that should be allocated to fit data
* pointed by @iter. If @iter is backed by bvec it's going to be reused
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 04/12] bio: use bio_set_errno in more places
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (2 preceding siblings ...)
2025-12-08 12:10 ` [RFC 03/12] bio: add bio_set_errno Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 05/12] bio: add bio_set_status Andreas Gruenbacher
` (8 subsequent siblings)
12 siblings, 0 replies; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
Replace variations of 'bio->bi_status = errno_to_blk_status(errno)' with
a call to bio_set_errno(bio, errno).
Note that bio_set_errno(bio, errno) only sets bio->bi_status to
errno_to_blk_status(errno) if errno is not 0. We must never set
bio->bi_status to 0 during bio completion.
Also note that bio_set_errno() is an inline function so that the
compiler can get rid of the errno check in case it knows that errno is
not 0. This is true for all bio_set_errno() calls this patch adds
except for the following two:
drivers/md/dm-pcache/dm_pcache.c:end_req()
drivers/md/dm-vdo/data-vio.c:acknowledge_data_vio()
In both of these cases, it seems that bi_status can be set to 0 during
bio completion, so the additional check that comes with using
bio_set_errno() appears to be necessary.
Created with Coccinelle using the following semantic patch:
@@
struct bio *bio;
expression errno;
@@
- bio->bi_status = errno_to_blk_status(errno);
+ bio_set_errno(bio, errno);
@@
struct bio bio;
expression errno;
@@
- bio.bi_status = errno_to_blk_status(errno);
+ bio_set_errno(&bio, errno);
@@
struct iomap_ioend *ioend;
expression error;
@@
- ioend->io_bio.bi_status = errno_to_blk_status(error);
+ bio_set_errno(&ioend->io_bio, error);
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/blk-merge.c | 4 ++--
drivers/md/dm-ebs-target.c | 2 +-
drivers/md/dm-integrity.c | 8 ++++----
drivers/md/dm-pcache/dm_pcache.c | 2 +-
drivers/md/dm-thin.c | 2 +-
drivers/md/dm-vdo/data-vio.c | 2 +-
drivers/md/raid10.c | 4 ++--
drivers/nvdimm/btt.c | 2 +-
fs/btrfs/bio.c | 2 +-
fs/btrfs/direct-io.c | 2 +-
fs/btrfs/raid56.c | 4 ++--
fs/crypto/bio.c | 2 +-
fs/erofs/fileio.c | 2 +-
fs/erofs/fscache.c | 4 ++--
fs/iomap/ioend.c | 2 +-
fs/xfs/xfs_aops.c | 2 +-
fs/xfs/xfs_zone_alloc.c | 2 +-
17 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 37864c5d287e..441013bf59d7 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -122,7 +122,7 @@ struct bio *bio_submit_split_bioset(struct bio *bio, unsigned int split_sectors,
struct bio *split = bio_split(bio, split_sectors, GFP_NOIO, bs);
if (IS_ERR(split)) {
- bio->bi_status = errno_to_blk_status(PTR_ERR(split));
+ bio_set_errno(bio, PTR_ERR(split));
bio_endio(bio);
return NULL;
}
@@ -143,7 +143,7 @@ EXPORT_SYMBOL_GPL(bio_submit_split_bioset);
static struct bio *bio_submit_split(struct bio *bio, int split_sectors)
{
if (unlikely(split_sectors < 0)) {
- bio->bi_status = errno_to_blk_status(split_sectors);
+ bio_set_errno(bio, split_sectors);
bio_endio(bio);
return NULL;
}
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c
index 6abb31ca9662..d9f46cbfe89f 100644
--- a/drivers/md/dm-ebs-target.c
+++ b/drivers/md/dm-ebs-target.c
@@ -217,7 +217,7 @@ static void __ebs_process_bios(struct work_struct *ws)
}
if (r < 0)
- bio->bi_status = errno_to_blk_status(r);
+ bio_set_errno(bio, r);
}
/*
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 170bf67a2edd..26e500730b3c 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -1581,7 +1581,7 @@ static void do_endio(struct dm_integrity_c *ic, struct bio *bio)
r = dm_integrity_failed(ic);
if (unlikely(r) && !bio->bi_status)
- bio->bi_status = errno_to_blk_status(r);
+ bio_set_errno(bio, r);
if (unlikely(ic->synchronous_mode) && bio_op(bio) == REQ_OP_WRITE) {
unsigned long flags;
@@ -2594,7 +2594,7 @@ static int dm_integrity_map_inline(struct dm_integrity_io *dio, bool from_map)
bip = bio_integrity_alloc(bio, GFP_NOIO, 1);
if (IS_ERR(bip)) {
- bio->bi_status = errno_to_blk_status(PTR_ERR(bip));
+ bio_set_errno(bio, PTR_ERR(bip));
bio_endio(bio);
return DM_MAPIO_SUBMITTED;
}
@@ -2662,7 +2662,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
bip = bio_integrity_alloc(outgoing_bio, GFP_NOIO, 1);
if (IS_ERR(bip)) {
bio_put(outgoing_bio);
- bio->bi_status = errno_to_blk_status(PTR_ERR(bip));
+ bio_set_errno(bio, PTR_ERR(bip));
bio_endio(bio);
return;
}
@@ -2680,7 +2680,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
r = submit_bio_wait(outgoing_bio);
if (unlikely(r != 0)) {
bio_put(outgoing_bio);
- bio->bi_status = errno_to_blk_status(r);
+ bio_set_errno(bio, r);
bio_endio(bio);
return;
}
diff --git a/drivers/md/dm-pcache/dm_pcache.c b/drivers/md/dm-pcache/dm_pcache.c
index e5f5936fa6f0..4acfaab91170 100644
--- a/drivers/md/dm-pcache/dm_pcache.c
+++ b/drivers/md/dm-pcache/dm_pcache.c
@@ -74,7 +74,7 @@ static void end_req(struct kref *ref)
pcache_req_get(pcache_req);
defer_req(pcache_req);
} else {
- bio->bi_status = errno_to_blk_status(ret);
+ bio_set_errno(bio, ret);
bio_endio(bio);
if (atomic_dec_and_test(&pcache->inflight_reqs))
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index c84149ba4e38..ad6b8b3c12dd 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -423,7 +423,7 @@ static void end_discard(struct discard_op *op, int r)
* need to wait for.
*/
if (r && !op->parent_bio->bi_status)
- op->parent_bio->bi_status = errno_to_blk_status(r);
+ bio_set_errno(op->parent_bio, r);
bio_endio(op->parent_bio);
}
diff --git a/drivers/md/dm-vdo/data-vio.c b/drivers/md/dm-vdo/data-vio.c
index 262e11581f2d..eaa435dd8e60 100644
--- a/drivers/md/dm-vdo/data-vio.c
+++ b/drivers/md/dm-vdo/data-vio.c
@@ -287,7 +287,7 @@ static void acknowledge_data_vio(struct data_vio *data_vio)
if (data_vio->is_partial)
vdo_count_bios(&vdo->stats.bios_acknowledged_partial, bio);
- bio->bi_status = errno_to_blk_status(error);
+ bio_set_errno(bio, error);
bio_endio(bio);
}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 14dcd5142eb4..9ac26d1f0764 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1665,7 +1665,7 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio)
split_size = stripe_size - remainder;
split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split);
if (IS_ERR(split)) {
- bio->bi_status = errno_to_blk_status(PTR_ERR(split));
+ bio_set_errno(bio, PTR_ERR(split));
bio_endio(bio);
return 0;
}
@@ -1682,7 +1682,7 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio)
split_size = bio_sectors(bio) - remainder;
split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split);
if (IS_ERR(split)) {
- bio->bi_status = errno_to_blk_status(PTR_ERR(split));
+ bio_set_errno(bio, PTR_ERR(split));
bio_endio(bio);
return 0;
}
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index a933db961ed7..14a8b7622b0d 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1468,7 +1468,7 @@ static void btt_submit_bio(struct bio *bio)
(op_is_write(bio_op(bio))) ? "WRITE" :
"READ",
(unsigned long long) iter.bi_sector, len);
- bio->bi_status = errno_to_blk_status(err);
+ bio_set_errno(bio, err);
break;
}
}
diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c
index 21df48e6c4fa..a0f55591fb90 100644
--- a/fs/btrfs/bio.c
+++ b/fs/btrfs/bio.c
@@ -540,7 +540,7 @@ static void run_one_async_start(struct btrfs_work *work)
ret = btrfs_bio_csum(async->bbio);
if (ret)
- async->bbio->bio.bi_status = errno_to_blk_status(ret);
+ bio_set_errno(&async->bbio->bio, ret);
}
/*
diff --git a/fs/btrfs/direct-io.c b/fs/btrfs/direct-io.c
index 802d4dbe5b38..d47c72abcdc3 100644
--- a/fs/btrfs/direct-io.c
+++ b/fs/btrfs/direct-io.c
@@ -738,7 +738,7 @@ static void btrfs_dio_submit_io(const struct iomap_iter *iter, struct bio *bio,
btrfs_finish_ordered_extent(dio_data->ordered, NULL,
file_offset, dip->bytes,
!ret);
- bio->bi_status = errno_to_blk_status(ret);
+ bio_set_errno(bio, ret);
iomap_dio_bio_end_io(bio);
return;
}
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 0135dceb7baa..ff802b6513af 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -1750,7 +1750,7 @@ void raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc)
rbio = alloc_rbio(fs_info, bioc);
if (IS_ERR(rbio)) {
- bio->bi_status = errno_to_blk_status(PTR_ERR(rbio));
+ bio_set_errno(bio, PTR_ERR(rbio));
bio_endio(bio);
return;
}
@@ -2148,7 +2148,7 @@ void raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
rbio = alloc_rbio(fs_info, bioc);
if (IS_ERR(rbio)) {
- bio->bi_status = errno_to_blk_status(PTR_ERR(rbio));
+ bio_set_errno(bio, PTR_ERR(rbio));
bio_endio(bio);
return;
}
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 5f5599020e94..96977fb5eb1d 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -39,7 +39,7 @@ bool fscrypt_decrypt_bio(struct bio *bio)
fi.offset);
if (err) {
- bio->bi_status = errno_to_blk_status(err);
+ bio_set_errno(bio, err);
return false;
}
}
diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c
index b7b3432a9882..0478243ca72e 100644
--- a/fs/erofs/fileio.c
+++ b/fs/erofs/fileio.c
@@ -33,7 +33,7 @@ static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret)
}
if (rq->bio.bi_end_io) {
if (ret < 0 && !rq->bio.bi_status)
- rq->bio.bi_status = errno_to_blk_status(ret);
+ bio_set_errno(&rq->bio, ret);
rq->bio.bi_end_io(&rq->bio);
} else {
bio_for_each_folio_all(fi, &rq->bio) {
diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c
index 362acf828279..dc0790d08510 100644
--- a/fs/erofs/fscache.c
+++ b/fs/erofs/fscache.c
@@ -184,7 +184,7 @@ static void erofs_fscache_bio_endio(void *priv, ssize_t transferred_or_error)
struct erofs_fscache_bio *io = priv;
if (IS_ERR_VALUE(transferred_or_error))
- io->bio.bi_status = errno_to_blk_status(transferred_or_error);
+ bio_set_errno(&io->bio, transferred_or_error);
io->bio.bi_end_io(&io->bio);
BUILD_BUG_ON(offsetof(struct erofs_fscache_bio, io) != 0);
erofs_fscache_io_put(&io->io);
@@ -215,7 +215,7 @@ void erofs_fscache_submit_bio(struct bio *bio)
erofs_fscache_io_put(&io->io);
if (!ret)
return;
- bio->bi_status = errno_to_blk_status(ret);
+ bio_set_errno(bio, ret);
bio->bi_end_io(bio);
}
diff --git a/fs/iomap/ioend.c b/fs/iomap/ioend.c
index b49fa75eab26..67cd48180fb2 100644
--- a/fs/iomap/ioend.c
+++ b/fs/iomap/ioend.c
@@ -87,7 +87,7 @@ int iomap_ioend_writeback_submit(struct iomap_writepage_ctx *wpc, int error)
error = -EIO;
if (error) {
- ioend->io_bio.bi_status = errno_to_blk_status(error);
+ bio_set_errno(&ioend->io_bio, error);
bio_endio(&ioend->io_bio);
return error;
}
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index a26f79815533..61368223a069 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -653,7 +653,7 @@ xfs_zoned_writeback_submit(
ioend->io_bio.bi_end_io = xfs_end_bio;
if (error) {
- ioend->io_bio.bi_status = errno_to_blk_status(error);
+ bio_set_errno(&ioend->io_bio, error);
bio_endio(&ioend->io_bio);
return error;
}
diff --git a/fs/xfs/xfs_zone_alloc.c b/fs/xfs/xfs_zone_alloc.c
index ef7a931ebde5..1381ba5a878e 100644
--- a/fs/xfs/xfs_zone_alloc.c
+++ b/fs/xfs/xfs_zone_alloc.c
@@ -896,7 +896,7 @@ xfs_zone_alloc_and_submit(
return;
out_split_error:
- ioend->io_bio.bi_status = errno_to_blk_status(PTR_ERR(split));
+ bio_set_errno(&ioend->io_bio, PTR_ERR(split));
out_error:
bio_io_error(&ioend->io_bio);
}
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 05/12] bio: add bio_set_status
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (3 preceding siblings ...)
2025-12-08 12:10 ` [RFC 04/12] bio: use bio_set_errno in more places Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-16 7:59 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 06/12] bio: don't check target->bi_status on error Andreas Gruenbacher
` (7 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
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 it isn't needed to prevent tearing
because a single-byte field like bi_status cannot tear.
Created with Coccinelle using the following semantic patch:
@@
struct bio *bio;
expression status;
@@
- if (status)
- bio->bi_status = status;
+ bio_set_status(bio, status);
@@
struct bio *bio;
expression status;
@@
- if (unlikely(status))
- bio->bi_status = status;
+ bio_set_status(bio, status);
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/blk-mq.c | 3 +--
drivers/md/dm.c | 3 +--
include/linux/bio.h | 6 ++++++
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/block/blk-mq.c b/block/blk-mq.c
index d626d32f6e57..bc837aa51daa 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -969,8 +969,7 @@ bool blk_update_request(struct request *req, blk_status_t error,
struct bio *bio = req->bio;
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;
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/include/linux/bio.h b/include/linux/bio.h
index 38ebf03036cb..bf4df0b15ee1 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -376,6 +376,12 @@ void submit_bio(struct bio *bio);
extern void bio_endio(struct bio *);
+static inline void bio_set_status(struct bio *bio, blk_status_t status)
+{
+ if (status)
+ WRITE_ONCE(bio->bi_status, status);
+}
+
static inline void bio_io_error(struct bio *bio)
{
bio->bi_status = BLK_STS_IOERR;
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 06/12] bio: don't check target->bi_status on error
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (4 preceding siblings ...)
2025-12-08 12:10 ` [RFC 05/12] bio: add bio_set_status Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-16 7:59 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 07/12] bio: use bio_set_status for BLK_STS_* status codes Andreas Gruenbacher
` (6 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
In a few places, target->bi_status is set to source->bi_status only if
source->bi_status is not 0 and target->bi_status is (still) 0. Here,
checking the value of target->bi_status before setting it is an
unnecessary micro optimization because we are already on an error path.
In addition, we can be racing with other execution contexts in the case
of chained bios, so there is no guarantee that target->bi_status won't
be set concurrently. We don't require atomic test-and-set semantics
here.
Created with Coccinelle using the following semantic patch:
@@
struct bio *source;
struct bio *target;
@@
- if (source->bi_status && !target->bi_status)
- target->bi_status = source->bi_status;
+ bio_set_status(target, source->bi_status);
@@
struct bio *source;
struct bio target;
@@
- if (source->bi_status && !target.bi_status)
- target.bi_status = source->bi_status;
+ bio_set_status(&target, source->bi_status);
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/bio.c | 3 +--
block/fops.c | 3 +--
drivers/md/md.c | 6 ++----
3 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/block/bio.c b/block/bio.c
index 3f408e1ba13f..5389321872f0 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -314,8 +314,7 @@ static struct bio *__bio_chain_endio(struct bio *bio)
{
struct bio *parent = bio->bi_private;
- if (bio->bi_status && !parent->bi_status)
- parent->bi_status = bio->bi_status;
+ bio_set_status(parent, bio->bi_status);
bio_put(bio);
return parent;
}
diff --git a/block/fops.c b/block/fops.c
index b4f911273289..a4a6972cbfbf 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -135,8 +135,7 @@ static void blkdev_bio_end_io(struct bio *bio)
bool should_dirty = dio->flags & DIO_SHOULD_DIRTY;
bool is_sync = dio->flags & DIO_IS_SYNC;
- if (bio->bi_status && !dio->bio.bi_status)
- dio->bio.bi_status = bio->bi_status;
+ bio_set_status(&dio->bio, bio->bi_status);
if (bio_integrity(bio))
bio_integrity_unmap_user(bio);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 41c476b40c7a..f6f1aab18a8b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9084,8 +9084,7 @@ static void md_end_clone_io(struct bio *bio)
if (bio_data_dir(orig_bio) == WRITE && md_bitmap_enabled(mddev, false))
md_bitmap_end(mddev, md_io_clone);
- if (bio->bi_status && !orig_bio->bi_status)
- orig_bio->bi_status = bio->bi_status;
+ bio_set_status(orig_bio, bio->bi_status);
if (md_io_clone->start_time)
bio_end_io_acct(orig_bio, md_io_clone->start_time);
@@ -9136,8 +9135,7 @@ void md_free_cloned_bio(struct bio *bio)
if (bio_data_dir(orig_bio) == WRITE && md_bitmap_enabled(mddev, false))
md_bitmap_end(mddev, md_io_clone);
- if (bio->bi_status && !orig_bio->bi_status)
- orig_bio->bi_status = bio->bi_status;
+ bio_set_status(orig_bio, bio->bi_status);
if (md_io_clone->start_time)
bio_end_io_acct(orig_bio, md_io_clone->start_time);
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 07/12] bio: use bio_set_status for BLK_STS_* status codes
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (5 preceding siblings ...)
2025-12-08 12:10 ` [RFC 06/12] bio: don't check target->bi_status on error Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 08/12] bio: use bio_set_status in some more places Andreas Gruenbacher
` (5 subsequent siblings)
12 siblings, 0 replies; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
Use bio_set_status(bio, status) in cases where status is a blk_status_t
constant other than BLK_STS_OK. In these cases, the compiler knows that
status != BLK_STS_OK, so it can optimize out the check in
bio_set_status() and effectively end up with identical code.
Created with Coccinelle using the following semantic patch:
@@
expression bio;
constant C != 0 && != BLK_STS_OK;
@@
- bio->bi_status = C;
+ bio_set_status(bio, C);
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/bio-integrity-auto.c | 2 +-
block/blk-core.c | 2 +-
block/blk-crypto-fallback.c | 16 ++++++++--------
block/blk-crypto-internal.h | 2 +-
block/blk-crypto.c | 4 ++--
block/blk-mq.c | 4 ++--
drivers/block/aoe/aoecmd.c | 8 ++++----
drivers/block/aoe/aoedev.c | 2 +-
drivers/block/drbd/drbd_req.c | 4 ++--
drivers/block/zram/zram_drv.c | 4 ++--
drivers/md/bcache/request.c | 2 +-
drivers/md/dm-cache-target.c | 5 +++--
drivers/md/dm-integrity.c | 12 ++++++------
drivers/md/dm-mpath.c | 2 +-
drivers/md/dm-raid1.c | 6 +++---
drivers/md/dm-thin.c | 2 +-
drivers/md/dm-writecache.c | 4 ++--
drivers/md/md.c | 2 +-
drivers/md/raid1-10.c | 2 +-
drivers/md/raid1.c | 2 +-
drivers/md/raid10.c | 10 +++++-----
drivers/md/raid5.c | 4 ++--
drivers/nvdimm/btt.c | 2 +-
fs/btrfs/bio.c | 2 +-
fs/f2fs/data.c | 6 +++---
fs/verity/verify.c | 2 +-
include/linux/bio.h | 4 ++--
27 files changed, 59 insertions(+), 58 deletions(-)
diff --git a/block/bio-integrity-auto.c b/block/bio-integrity-auto.c
index 687952f63bbb..736d53a7f699 100644
--- a/block/bio-integrity-auto.c
+++ b/block/bio-integrity-auto.c
@@ -190,7 +190,7 @@ bool bio_integrity_prep(struct bio *bio)
err_free_buf:
kfree(buf);
err_end_io:
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
bio_endio(bio);
return false;
}
diff --git a/block/blk-core.c b/block/blk-core.c
index 14ae73eebe0d..4f7b7cf50d23 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -640,7 +640,7 @@ static void __submit_bio(struct bio *bio)
if ((bio->bi_opf & REQ_POLLED) &&
!(disk->queue->limits.features & BLK_FEAT_POLL)) {
- bio->bi_status = BLK_STS_NOTSUPP;
+ bio_set_status(bio, BLK_STS_NOTSUPP);
bio_endio(bio);
} else {
disk->fops->submit_bio(bio);
diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
index 86b27f96051a..0e135ba26346 100644
--- a/block/blk-crypto-fallback.c
+++ b/block/blk-crypto-fallback.c
@@ -281,7 +281,7 @@ static bool blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr)
/* Allocate bounce bio for encryption */
enc_bio = blk_crypto_fallback_clone_bio(src_bio);
if (!enc_bio) {
- src_bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(src_bio, BLK_STS_RESOURCE);
return false;
}
@@ -298,7 +298,7 @@ static bool blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr)
/* and then allocate an skcipher_request for it */
if (!blk_crypto_fallback_alloc_cipher_req(slot, &ciph_req, &wait)) {
- src_bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(src_bio, BLK_STS_RESOURCE);
goto out_release_keyslot;
}
@@ -319,7 +319,7 @@ static bool blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr)
enc_bvec->bv_page = ciphertext_page;
if (!ciphertext_page) {
- src_bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(src_bio, BLK_STS_RESOURCE);
goto out_free_bounce_pages;
}
@@ -334,7 +334,7 @@ static bool blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr)
if (crypto_wait_req(crypto_skcipher_encrypt(ciph_req),
&wait)) {
i++;
- src_bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(src_bio, BLK_STS_IOERR);
goto out_free_bounce_pages;
}
bio_crypt_dun_increment(curr_dun, 1);
@@ -401,7 +401,7 @@ static void blk_crypto_fallback_decrypt_bio(struct work_struct *work)
/* and then allocate an skcipher_request for it */
if (!blk_crypto_fallback_alloc_cipher_req(slot, &ciph_req, &wait)) {
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
goto out;
}
@@ -421,7 +421,7 @@ static void blk_crypto_fallback_decrypt_bio(struct work_struct *work)
blk_crypto_dun_to_iv(curr_dun, &iv);
if (crypto_wait_req(crypto_skcipher_decrypt(ciph_req),
&wait)) {
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
goto out;
}
bio_crypt_dun_increment(curr_dun, 1);
@@ -492,13 +492,13 @@ bool blk_crypto_fallback_bio_prep(struct bio **bio_ptr)
if (WARN_ON_ONCE(!tfms_inited[bc->bc_key->crypto_cfg.crypto_mode])) {
/* User didn't call blk_crypto_start_using_key() first */
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
return false;
}
if (!__blk_crypto_cfg_supported(blk_crypto_fallback_profile,
&bc->bc_key->crypto_cfg)) {
- bio->bi_status = BLK_STS_NOTSUPP;
+ bio_set_status(bio, BLK_STS_NOTSUPP);
return false;
}
diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h
index ccf6dff6ff6b..fc606352a31a 100644
--- a/block/blk-crypto-internal.h
+++ b/block/blk-crypto-internal.h
@@ -235,7 +235,7 @@ blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num)
static inline bool blk_crypto_fallback_bio_prep(struct bio **bio_ptr)
{
pr_warn_once("crypto API fallback disabled; failing request.\n");
- (*bio_ptr)->bi_status = BLK_STS_NOTSUPP;
+ bio_set_status((*bio_ptr), BLK_STS_NOTSUPP);
return false;
}
diff --git a/block/blk-crypto.c b/block/blk-crypto.c
index 3e7bf1974cbd..cbba31cd4e58 100644
--- a/block/blk-crypto.c
+++ b/block/blk-crypto.c
@@ -287,12 +287,12 @@ bool __blk_crypto_bio_prep(struct bio **bio_ptr)
/* Error if bio has no data. */
if (WARN_ON_ONCE(!bio_has_data(bio))) {
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
goto fail;
}
if (!bio_crypt_check_alignment(bio)) {
- bio->bi_status = BLK_STS_INVAL;
+ bio_set_status(bio, BLK_STS_INVAL);
goto fail;
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index bc837aa51daa..4e13d9f9ea96 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -979,7 +979,7 @@ bool blk_update_request(struct request *req, blk_status_t error,
* as the BIO fragments may end up not being written
* sequentially.
*/
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
}
/* Completion has already been traced */
@@ -3164,7 +3164,7 @@ void blk_mq_submit_bio(struct bio *bio)
}
if ((bio->bi_opf & REQ_POLLED) && !blk_mq_can_poll(q)) {
- bio->bi_status = BLK_STS_NOTSUPP;
+ bio_set_status(bio, BLK_STS_NOTSUPP);
bio_endio(bio);
goto queue_exit;
}
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index a9affb7c264d..a5eb4912fb3e 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -1112,7 +1112,7 @@ ktiocomplete(struct frame *f)
ahout->cmdstat, ahin->cmdstat,
d->aoemajor, d->aoeminor);
noskb: if (buf)
- buf->bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(buf->bio, BLK_STS_IOERR);
goto out;
}
@@ -1125,7 +1125,7 @@ noskb: if (buf)
"aoe: runt data size in read from",
(long) d->aoemajor, d->aoeminor,
skb->len, n);
- buf->bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(buf->bio, BLK_STS_IOERR);
break;
}
if (n > f->iter.bi_size) {
@@ -1133,7 +1133,7 @@ noskb: if (buf)
"aoe: too-large data size in read from",
(long) d->aoemajor, d->aoeminor,
n, f->iter.bi_size);
- buf->bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(buf->bio, BLK_STS_IOERR);
break;
}
bvcpy(skb, f->buf->bio, f->iter, n);
@@ -1637,7 +1637,7 @@ aoe_failbuf(struct aoedev *d, struct buf *buf)
if (buf == NULL)
return;
buf->iter.bi_size = 0;
- buf->bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(buf->bio, BLK_STS_IOERR);
if (buf->nframesout == 0)
aoe_end_buf(d, buf);
}
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 3a240755045b..11320258d0ce 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -170,7 +170,7 @@ aoe_failip(struct aoedev *d)
req = blk_mq_rq_to_pdu(rq);
while ((bio = d->ip.nxbio)) {
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
d->ip.nxbio = bio->bi_next;
req->nr_bios--;
}
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index bd4bc882cc5a..95a58ad6fdcf 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1142,7 +1142,7 @@ static void drbd_process_discard_or_zeroes_req(struct drbd_request *req, int fla
int err = drbd_issue_discard_or_zero_out(req->device,
req->i.sector, req->i.size >> 9, flags);
if (err)
- req->private_bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(req->private_bio, BLK_STS_IOERR);
bio_endio(req->private_bio);
}
@@ -1210,7 +1210,7 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio)
/* only pass the error to the upper layers.
* if user cannot handle io errors, that's not our business. */
drbd_err(device, "could not kmalloc() req\n");
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
bio_endio(bio);
return ERR_PTR(-ENOMEM);
}
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index a43074657531..975757f01bb8 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -2341,7 +2341,7 @@ static void zram_bio_read(struct zram *zram, struct bio *bio)
if (zram_bvec_read(zram, &bv, index, offset, bio) < 0) {
atomic64_inc(&zram->stats.failed_reads);
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
break;
}
flush_dcache_page(bv.bv_page);
@@ -2372,7 +2372,7 @@ static void zram_bio_write(struct zram *zram, struct bio *bio)
if (zram_bvec_write(zram, &bv, index, offset, bio) < 0) {
atomic64_inc(&zram->stats.failed_writes);
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
break;
}
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index acccecd061ea..3ea67a8e252a 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -1120,7 +1120,7 @@ static void detached_dev_do_request(struct bcache_device *d, struct bio *bio,
*/
ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO);
if (!ddip) {
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
bio->bi_end_io(bio);
return;
}
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index a10d75a562db..82d748eeb9aa 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -1192,7 +1192,8 @@ static void mg_complete(struct dm_cache_migration *mg, bool success)
else if (mg->k.input)
mg->overwrite_bio->bi_status = mg->k.input;
else
- mg->overwrite_bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(mg->overwrite_bio,
+ BLK_STS_IOERR);
bio_endio(mg->overwrite_bio);
} else {
if (success)
@@ -1854,7 +1855,7 @@ static void requeue_deferred_bios(struct cache *cache)
bio_list_merge_init(&bios, &cache->deferred_bios);
while ((bio = bio_list_pop(&bios))) {
- bio->bi_status = BLK_STS_DM_REQUEUE;
+ bio_set_status(bio, BLK_STS_DM_REQUEUE);
bio_endio(bio);
cond_resched();
}
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 26e500730b3c..d2288b9f2b0d 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -2513,7 +2513,7 @@ static int dm_integrity_map_inline(struct dm_integrity_io *dio, bool from_map)
sector_t recalc_sector;
if (unlikely(bio_integrity(bio))) {
- bio->bi_status = BLK_STS_NOTSUPP;
+ bio_set_status(bio, BLK_STS_NOTSUPP);
bio_endio(bio);
return DM_MAPIO_SUBMITTED;
}
@@ -2535,7 +2535,7 @@ static int dm_integrity_map_inline(struct dm_integrity_io *dio, bool from_map)
if (dio->payload_len > x_size) {
unsigned sectors = ((x_size - extra_size) / ic->tuple_size) << ic->sb->log2_sectors_per_block;
if (WARN_ON(!sectors || sectors >= bio_sectors(bio))) {
- bio->bi_status = BLK_STS_NOTSUPP;
+ bio_set_status(bio, BLK_STS_NOTSUPP);
bio_endio(bio);
return DM_MAPIO_SUBMITTED;
}
@@ -2616,7 +2616,7 @@ static int dm_integrity_map_inline(struct dm_integrity_io *dio, bool from_map)
ret = bio_integrity_add_page(bio, virt_to_page(dio->integrity_payload),
dio->payload_len, offset_in_page(dio->integrity_payload));
if (unlikely(ret != dio->payload_len)) {
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
bio_endio(bio);
return DM_MAPIO_SUBMITTED;
}
@@ -2670,7 +2670,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
r = bio_integrity_add_page(outgoing_bio, virt_to_page(dio->integrity_payload), ic->tuple_size, 0);
if (unlikely(r != ic->tuple_size)) {
bio_put(outgoing_bio);
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
bio_endio(bio);
return;
}
@@ -2694,7 +2694,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
dm_audit_log_bio(DM_MSG_PREFIX, "integrity-checksum",
bio, dio->bio_details.bi_iter.bi_sector, 0);
- bio->bi_status = BLK_STS_PROTECTION;
+ bio_set_status(bio, BLK_STS_PROTECTION);
bio_endio(bio);
return;
}
@@ -2784,7 +2784,7 @@ static void integrity_bio_wait(struct work_struct *w)
int r = dm_integrity_map_inline(dio, false);
switch (r) {
case DM_MAPIO_KILL:
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
fallthrough;
case DM_MAPIO_REMAPPED:
submit_bio_noacct(bio);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 1424ef75d088..761e5e79d4a7 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -722,7 +722,7 @@ static void process_queued_bios(struct work_struct *work)
bio_io_error(bio);
break;
case DM_MAPIO_REQUEUE:
- bio->bi_status = BLK_STS_DM_REQUEUE;
+ bio_set_status(bio, BLK_STS_DM_REQUEUE);
bio_endio(bio);
break;
case DM_MAPIO_REMAPPED:
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 268f734ca9c3..c54995847db0 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -491,9 +491,9 @@ static void hold_bio(struct mirror_set *ms, struct bio *bio)
* If device is suspended, complete the bio.
*/
if (dm_noflush_suspending(ms->ti))
- bio->bi_status = BLK_STS_DM_REQUEUE;
+ bio_set_status(bio, BLK_STS_DM_REQUEUE);
else
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
bio_endio(bio);
return;
@@ -627,7 +627,7 @@ static void write_callback(unsigned long error, void *context)
* degrade the array.
*/
if (bio_op(bio) == REQ_OP_DISCARD) {
- bio->bi_status = BLK_STS_NOTSUPP;
+ bio_set_status(bio, BLK_STS_NOTSUPP);
bio_endio(bio);
return;
}
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index ad6b8b3c12dd..bd061a6bf016 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2731,7 +2731,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
thin_hook_bio(tc, bio);
if (tc->requeue_mode) {
- bio->bi_status = BLK_STS_DM_REQUEUE;
+ bio_set_status(bio, BLK_STS_DM_REQUEUE);
bio_endio(bio);
return DM_MAPIO_SUBMITTED;
}
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index 4f70e2673e4b..f615ff46cc41 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -1265,7 +1265,7 @@ static void bio_copy_block(struct dm_writecache *wc, struct bio *bio, void *data
flush_dcache_page(bio_page(bio));
if (unlikely(r)) {
writecache_error(wc, r, "hardware memory error when reading data: %d", r);
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
}
} else {
flush_dcache_page(bio_page(bio));
@@ -1312,7 +1312,7 @@ static int writecache_flush_thread(void *data)
writecache_flush(wc);
wc_unlock(wc);
if (writecache_has_error(wc))
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
bio_endio(bio);
}
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index f6f1aab18a8b..5afc6d63aa7b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -447,7 +447,7 @@ static void md_submit_bio(struct bio *bio)
if (mddev->ro == MD_RDONLY && unlikely(rw == WRITE)) {
if (bio_sectors(bio) != 0)
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
bio_endio(bio);
return;
}
diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c
index 521625756128..504730aba9df 100644
--- a/drivers/md/raid1-10.c
+++ b/drivers/md/raid1-10.c
@@ -104,7 +104,7 @@ static void md_bio_reset_resync_pages(struct bio *bio, struct resync_pages *rp,
int len = min_t(int, size, PAGE_SIZE);
if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
bio_endio(bio);
return;
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 592a40233004..923b6a762858 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -301,7 +301,7 @@ static void call_bio_endio(struct r1bio *r1_bio)
struct bio *bio = r1_bio->master_bio;
if (!test_bit(R1BIO_Uptodate, &r1_bio->state))
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
bio_endio(bio);
}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9ac26d1f0764..62d5bc9f7b3e 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -324,7 +324,7 @@ static void raid_end_bio_io(struct r10bio *r10_bio)
if (!test_and_set_bit(R10BIO_Returned, &r10_bio->state)) {
if (!test_bit(R10BIO_Uptodate, &r10_bio->state))
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
bio_endio(bio);
}
@@ -3600,7 +3600,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
r10_bio->devs[i].repl_bio->bi_end_io = NULL;
bio = r10_bio->devs[i].bio;
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
rdev = conf->mirrors[d].rdev;
if (rdev == NULL || test_bit(Faulty, &rdev->flags))
continue;
@@ -3637,7 +3637,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
/* Need to set up for writing to the replacement */
bio = r10_bio->devs[i].repl_bio;
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
sector = r10_bio->devs[i].addr;
bio->bi_next = biolist;
@@ -3683,7 +3683,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
struct resync_pages *rp = get_resync_pages(bio);
page = resync_fetch_page(rp, page_idx);
if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
bio_endio(bio);
goto giveup;
}
@@ -4865,7 +4865,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,
len = PAGE_SIZE;
for (bio = blist; bio ; bio = bio->bi_next) {
if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
- bio->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bio, BLK_STS_RESOURCE);
bio_endio(bio);
return sectors_done;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 24b32a0c95b4..fa84fadac2fd 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5974,7 +5974,7 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
sh = raid5_get_active_stripe(conf, ctx, new_sector, flags);
if (unlikely(!sh)) {
/* cannot get stripe, just give-up */
- bi->bi_status = BLK_STS_IOERR;
+ bio_set_status(bi, BLK_STS_IOERR);
return STRIPE_FAIL;
}
@@ -6037,7 +6037,7 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
raid5_release_stripe(sh);
out:
if (ret == STRIPE_SCHEDULE_AND_RETRY && reshape_interrupted(mddev)) {
- bi->bi_status = BLK_STS_RESOURCE;
+ bio_set_status(bi, BLK_STS_RESOURCE);
ret = STRIPE_WAIT_RESHAPE;
pr_err_ratelimited("dm-raid456: io across reshape position while reshape can't make progress");
}
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 14a8b7622b0d..a624bc9aa699 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1456,7 +1456,7 @@ static void btt_submit_bio(struct bio *bio)
len % btt->sector_size) {
dev_err_ratelimited(&btt->nd_btt->dev,
"unaligned bio segment (len: %d)\n", len);
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
break;
}
diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c
index a0f55591fb90..00a7a13fab0c 100644
--- a/fs/btrfs/bio.c
+++ b/fs/btrfs/bio.c
@@ -382,7 +382,7 @@ static void btrfs_orig_write_end_io(struct bio *bio)
* threshold.
*/
if (atomic_read(&bioc->error) > bioc->max_errors)
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
else
bio->bi_status = BLK_STS_OK;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 775aa4f63aa3..3b031d0391d3 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -188,7 +188,7 @@ static void f2fs_verify_bio(struct work_struct *work)
if (!f2fs_is_compressed_page(folio) &&
!fsverity_verify_page(&folio->page)) {
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
break;
}
}
@@ -286,7 +286,7 @@ static void f2fs_read_end_io(struct bio *bio)
ctx = bio->bi_private;
if (time_to_inject(sbi, FAULT_READ_IO))
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
if (bio->bi_status != BLK_STS_OK) {
f2fs_finish_read_bio(bio, intask);
@@ -323,7 +323,7 @@ static void f2fs_write_end_io(struct bio *bio)
sbi = bio->bi_private;
if (time_to_inject(sbi, FAULT_WRITE_IO))
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
bio_for_each_folio_all(fi, bio) {
struct folio *folio = fi.folio;
diff --git a/fs/verity/verify.c b/fs/verity/verify.c
index 86067c8b40cf..17a168744037 100644
--- a/fs/verity/verify.c
+++ b/fs/verity/verify.c
@@ -432,7 +432,7 @@ void fsverity_verify_bio(struct bio *bio)
ioerr:
fsverity_clear_pending_blocks(&ctx);
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
}
EXPORT_SYMBOL_GPL(fsverity_verify_bio);
#endif /* CONFIG_BLOCK */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index bf4df0b15ee1..ad70a88cef09 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -384,14 +384,14 @@ static inline void bio_set_status(struct bio *bio, blk_status_t status)
static inline void bio_io_error(struct bio *bio)
{
- bio->bi_status = BLK_STS_IOERR;
+ bio_set_status(bio, BLK_STS_IOERR);
bio_endio(bio);
}
static inline void bio_wouldblock_error(struct bio *bio)
{
bio_set_flag(bio, BIO_QUIET);
- bio->bi_status = BLK_STS_AGAIN;
+ bio_set_status(bio, BLK_STS_AGAIN);
bio_endio(bio);
}
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 08/12] bio: use bio_set_status in some more places
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (6 preceding siblings ...)
2025-12-08 12:10 ` [RFC 07/12] bio: use bio_set_status for BLK_STS_* status codes Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 09/12] bio: switch to bio_set_status in submit_bio_noacct Andreas Gruenbacher
` (4 subsequent siblings)
12 siblings, 0 replies; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
In these places, the status is known not to be BLK_STS_OK (0), so the
'status != BLK_STS_OK' check in bio_set_status() will be optimized out
and we end up with identical code.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/blk-crypto-fallback.c | 4 ++--
block/blk-mq.c | 2 +-
block/t10-pi.c | 2 +-
drivers/md/dm-cache-target.c | 3 ++-
drivers/md/dm-integrity.c | 2 +-
drivers/md/dm-zoned-target.c | 2 +-
drivers/nvdimm/pmem.c | 2 +-
fs/btrfs/bio.c | 4 ++--
8 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
index 0e135ba26346..8a2631b1e7e1 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 4e13d9f9ea96..503ca259429f 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -3205,7 +3205,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 82d748eeb9aa..d1dbd4ddaadb 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
bio_set_status(mg->overwrite_bio,
BLK_STS_IOERR);
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index d2288b9f2b0d..5220e15b6537 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -1617,7 +1617,7 @@ static void dec_in_flight(struct dm_integrity_io *dio)
bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
if (unlikely(dio->bi_status) && !bio->bi_status)
- bio->bi_status = dio->bi_status;
+ bio_set_status(bio, dio->bi_status);
if (likely(!bio->bi_status) && unlikely(bio_sectors(bio) != dio->range.n_sectors)) {
dio->range.logical_sector += dio->range.n_sectors;
bio_advance(bio, dio->range.n_sectors << SECTOR_SHIFT);
diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c
index 9da329078ea4..d0218a9f1c4f 100644
--- a/drivers/md/dm-zoned-target.c
+++ b/drivers/md/dm-zoned-target.c
@@ -78,7 +78,7 @@ static inline void dmz_bio_endio(struct bio *bio, blk_status_t status)
dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
if (status != BLK_STS_OK && bio->bi_status == BLK_STS_OK)
- bio->bi_status = status;
+ bio_set_status(bio, status);
if (bioctx->dev && bio->bi_status != BLK_STS_OK)
bioctx->dev->flags |= DMZ_CHECK_BDEV;
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index a2f8b5a85326..aa2a486522b5 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/fs/btrfs/bio.c b/fs/btrfs/bio.c
index 00a7a13fab0c..a63d69509d05 100644
--- a/fs/btrfs/bio.c
+++ b/fs/btrfs/bio.c
@@ -174,7 +174,7 @@ static void btrfs_end_repair_bio(struct btrfs_bio *repair_bbio,
mirror = next_repair_mirror(fbio, mirror);
if (mirror == fbio->bbio->mirror_num) {
btrfs_debug(fs_info, "no mirror left");
- fbio->bbio->bio.bi_status = BLK_STS_IOERR;
+ bio_set_status(&fbio->bbio->bio, BLK_STS_IOERR);
goto done;
}
@@ -225,7 +225,7 @@ static struct btrfs_failed_bio *repair_one_sector(struct btrfs_bio *failed_bbio,
num_copies = btrfs_num_copies(fs_info, logical, sectorsize);
if (num_copies == 1) {
btrfs_debug(fs_info, "no copy to repair from");
- failed_bbio->bio.bi_status = BLK_STS_IOERR;
+ bio_set_status(&failed_bbio->bio, BLK_STS_IOERR);
return fbio;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 09/12] bio: switch to bio_set_status in submit_bio_noacct
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (7 preceding siblings ...)
2025-12-08 12:10 ` [RFC 08/12] bio: use bio_set_status in some more places Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 10/12] bio: never set bi_status to BLK_STS_OK during completion Andreas Gruenbacher
` (3 subsequent siblings)
12 siblings, 0 replies; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
In submit_bio_noacct(), call bio_endio() and return directly when
successful. That way, bio_set_status(bio, status) will only be called
for actual errors and the compiler can optimize out the 'status !=
BLK_STS_OK' check inside bio_set_status().
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/blk-core.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c
index 4f7b7cf50d23..95cbb3ffcf9f 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -816,8 +816,8 @@ void submit_bio_noacct(struct bio *bio)
if (!bdev_write_cache(bdev)) {
bio->bi_opf &= ~(REQ_PREFLUSH | REQ_FUA);
if (!bio_sectors(bio)) {
- status = BLK_STS_OK;
- goto end_io;
+ bio_endio(bio);
+ return;
}
}
}
@@ -882,7 +882,7 @@ void submit_bio_noacct(struct bio *bio)
not_supported:
status = BLK_STS_NOTSUPP;
end_io:
- bio->bi_status = status;
+ bio_set_status(bio, status);
bio_endio(bio);
}
EXPORT_SYMBOL(submit_bio_noacct);
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 10/12] bio: never set bi_status to BLK_STS_OK during completion
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (8 preceding siblings ...)
2025-12-08 12:10 ` [RFC 09/12] bio: switch to bio_set_status in submit_bio_noacct Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 11/12] bio: add bio_endio_errno Andreas Gruenbacher
` (2 subsequent siblings)
12 siblings, 0 replies; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
In a few places in the code, we don't know if a bio has failed or
completed successfully, so use bio_set_status() instead of setting
bi_status directly. That way, bi_status will never be set to
BI_STS_OK (0) during completion.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/blk-crypto-fallback.c | 2 +-
drivers/block/ps3vram.c | 2 +-
drivers/md/dm-flakey.c | 2 +-
drivers/md/dm-verity-target.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
index 8a2631b1e7e1..7014f646e236 100644
--- a/block/blk-crypto-fallback.c
+++ b/block/blk-crypto-fallback.c
@@ -150,7 +150,7 @@ static void blk_crypto_fallback_encrypt_endio(struct bio *enc_bio)
mempool_free(enc_bio->bi_io_vec[i].bv_page,
blk_crypto_bounce_page_pool);
- src_bio->bi_status = enc_bio->bi_status;
+ bio_set_status(src_bio, enc_bio->bi_status);
bio_uninit(enc_bio);
kfree(enc_bio);
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index bdcf083b45e2..06844674c998 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -573,7 +573,7 @@ static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
next = bio_list_peek(&priv->list);
spin_unlock_irq(&priv->lock);
- bio->bi_status = error;
+ bio_set_status(bio, error);
bio_endio(bio);
return next;
}
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 08925aca838c..8dde47beb387 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -420,7 +420,7 @@ static void clone_free(struct bio *clone)
static void clone_endio(struct bio *clone)
{
struct bio *bio = clone->bi_private;
- bio->bi_status = clone->bi_status;
+ bio_set_status(bio, clone->bi_status);
clone_free(clone);
bio_endio(bio);
}
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index 66a00a8ccb39..4793bcf546ad 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -544,7 +544,7 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
bio->bi_end_io = io->orig_bi_end_io;
- bio->bi_status = status;
+ bio_set_status(bio, status);
if (!static_branch_unlikely(&use_bh_wq_enabled) || !io->in_bh)
verity_fec_finish_io(io);
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 11/12] bio: add bio_endio_errno
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (9 preceding siblings ...)
2025-12-08 12:10 ` [RFC 10/12] bio: never set bi_status to BLK_STS_OK during completion Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-16 8:00 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 12/12] bio: add bio_endio_status Andreas Gruenbacher
2025-12-08 19:37 ` [RFC 00/12] bio cleanups David Sterba
12 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
Add a bio_endio_errno() helper as a shortcut for calling bio_set_errno()
and bio_endio() in sequence. Use the new helper throughout the code.
Created with Coccinelle using the following semantic patch:
@@
expression bio, errno;
@@
- bio_set_errno(bio, errno);
- bio_endio(bio);
+ bio_endio_errno(bio, errno);
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/blk-merge.c | 6 ++----
drivers/block/drbd/drbd_req.c | 3 +--
drivers/md/dm-integrity.c | 9 +++------
drivers/md/dm-pcache/dm_pcache.c | 3 +--
drivers/md/dm-vdo/data-vio.c | 3 +--
drivers/md/raid10.c | 6 ++----
drivers/nvdimm/pmem.c | 4 +---
fs/btrfs/raid56.c | 6 ++----
fs/iomap/ioend.c | 3 +--
fs/xfs/xfs_aops.c | 3 +--
include/linux/bio.h | 6 ++++++
11 files changed, 21 insertions(+), 31 deletions(-)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 441013bf59d7..25057d57e9ac 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -122,8 +122,7 @@ struct bio *bio_submit_split_bioset(struct bio *bio, unsigned int split_sectors,
struct bio *split = bio_split(bio, split_sectors, GFP_NOIO, bs);
if (IS_ERR(split)) {
- bio_set_errno(bio, PTR_ERR(split));
- bio_endio(bio);
+ bio_endio_errno(bio, PTR_ERR(split));
return NULL;
}
@@ -143,8 +142,7 @@ EXPORT_SYMBOL_GPL(bio_submit_split_bioset);
static struct bio *bio_submit_split(struct bio *bio, int split_sectors)
{
if (unlikely(split_sectors < 0)) {
- bio_set_errno(bio, split_sectors);
- bio_endio(bio);
+ bio_endio_errno(bio, split_sectors);
return NULL;
}
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 95a58ad6fdcf..5bedc972b622 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -176,8 +176,7 @@ void start_new_tl_epoch(struct drbd_connection *connection)
void complete_master_bio(struct drbd_device *device,
struct bio_and_error *m)
{
- bio_set_errno(m->bio, m->error);
- bio_endio(m->bio);
+ bio_endio_errno(m->bio, m->error);
dec_ap_bio(device);
}
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 5220e15b6537..90780a112009 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -2594,8 +2594,7 @@ static int dm_integrity_map_inline(struct dm_integrity_io *dio, bool from_map)
bip = bio_integrity_alloc(bio, GFP_NOIO, 1);
if (IS_ERR(bip)) {
- bio_set_errno(bio, PTR_ERR(bip));
- bio_endio(bio);
+ bio_endio_errno(bio, PTR_ERR(bip));
return DM_MAPIO_SUBMITTED;
}
@@ -2662,8 +2661,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
bip = bio_integrity_alloc(outgoing_bio, GFP_NOIO, 1);
if (IS_ERR(bip)) {
bio_put(outgoing_bio);
- bio_set_errno(bio, PTR_ERR(bip));
- bio_endio(bio);
+ bio_endio_errno(bio, PTR_ERR(bip));
return;
}
@@ -2680,8 +2678,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
r = submit_bio_wait(outgoing_bio);
if (unlikely(r != 0)) {
bio_put(outgoing_bio);
- bio_set_errno(bio, r);
- bio_endio(bio);
+ bio_endio_errno(bio, r);
return;
}
bio_put(outgoing_bio);
diff --git a/drivers/md/dm-pcache/dm_pcache.c b/drivers/md/dm-pcache/dm_pcache.c
index 4acfaab91170..b3795e88f364 100644
--- a/drivers/md/dm-pcache/dm_pcache.c
+++ b/drivers/md/dm-pcache/dm_pcache.c
@@ -74,8 +74,7 @@ static void end_req(struct kref *ref)
pcache_req_get(pcache_req);
defer_req(pcache_req);
} else {
- bio_set_errno(bio, ret);
- bio_endio(bio);
+ bio_endio_errno(bio, ret);
if (atomic_dec_and_test(&pcache->inflight_reqs))
wake_up(&pcache->inflight_wq);
diff --git a/drivers/md/dm-vdo/data-vio.c b/drivers/md/dm-vdo/data-vio.c
index eaa435dd8e60..47827ea61d91 100644
--- a/drivers/md/dm-vdo/data-vio.c
+++ b/drivers/md/dm-vdo/data-vio.c
@@ -287,8 +287,7 @@ static void acknowledge_data_vio(struct data_vio *data_vio)
if (data_vio->is_partial)
vdo_count_bios(&vdo->stats.bios_acknowledged_partial, bio);
- bio_set_errno(bio, error);
- bio_endio(bio);
+ bio_endio_errno(bio, error);
}
static void copy_to_bio(struct bio *bio, char *data_ptr)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 62d5bc9f7b3e..7cc27819beb5 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1665,8 +1665,7 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio)
split_size = stripe_size - remainder;
split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split);
if (IS_ERR(split)) {
- bio_set_errno(bio, PTR_ERR(split));
- bio_endio(bio);
+ bio_endio_errno(bio, PTR_ERR(split));
return 0;
}
@@ -1682,8 +1681,7 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio)
split_size = bio_sectors(bio) - remainder;
split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split);
if (IS_ERR(split)) {
- bio_set_errno(bio, PTR_ERR(split));
- bio_endio(bio);
+ bio_endio_errno(bio, PTR_ERR(split));
return 0;
}
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index aa2a486522b5..ed763c1ec955 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -232,9 +232,7 @@ static void pmem_submit_bio(struct bio *bio)
if (bio->bi_opf & REQ_FUA)
ret = nvdimm_flush(nd_region, bio);
- bio_set_errno(bio, ret);
-
- bio_endio(bio);
+ bio_endio_errno(bio, ret);
}
/* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index ff802b6513af..bf45e8fd3aa1 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -1750,8 +1750,7 @@ void raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc)
rbio = alloc_rbio(fs_info, bioc);
if (IS_ERR(rbio)) {
- bio_set_errno(bio, PTR_ERR(rbio));
- bio_endio(bio);
+ bio_endio_errno(bio, PTR_ERR(rbio));
return;
}
rbio->operation = BTRFS_RBIO_WRITE;
@@ -2148,8 +2147,7 @@ void raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
rbio = alloc_rbio(fs_info, bioc);
if (IS_ERR(rbio)) {
- bio_set_errno(bio, PTR_ERR(rbio));
- bio_endio(bio);
+ bio_endio_errno(bio, PTR_ERR(rbio));
return;
}
diff --git a/fs/iomap/ioend.c b/fs/iomap/ioend.c
index 67cd48180fb2..d9e9659b55b3 100644
--- a/fs/iomap/ioend.c
+++ b/fs/iomap/ioend.c
@@ -87,8 +87,7 @@ int iomap_ioend_writeback_submit(struct iomap_writepage_ctx *wpc, int error)
error = -EIO;
if (error) {
- bio_set_errno(&ioend->io_bio, error);
- bio_endio(&ioend->io_bio);
+ bio_endio_errno(&ioend->io_bio, error);
return error;
}
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 61368223a069..4da13a15cb62 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -653,8 +653,7 @@ xfs_zoned_writeback_submit(
ioend->io_bio.bi_end_io = xfs_end_bio;
if (error) {
- bio_set_errno(&ioend->io_bio, error);
- bio_endio(&ioend->io_bio);
+ bio_endio_errno(&ioend->io_bio, error);
return error;
}
xfs_zone_alloc_and_submit(ioend, &XFS_ZWPC(wpc)->open_zone);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index ad70a88cef09..06fb8ae018c4 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -403,6 +403,12 @@ static inline void bio_set_errno(struct bio *bio, int errno)
WRITE_ONCE(bio->bi_status, errno_to_blk_status(errno));
}
+static inline void bio_endio_errno(struct bio *bio, int errno)
+{
+ bio_set_errno(bio, errno);
+ bio_endio(bio);
+}
+
/*
* Calculate number of bvec segments that should be allocated to fit data
* pointed by @iter. If @iter is backed by bvec it's going to be reused
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC 12/12] bio: add bio_endio_status
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (10 preceding siblings ...)
2025-12-08 12:10 ` [RFC 11/12] bio: add bio_endio_errno Andreas Gruenbacher
@ 2025-12-08 12:10 ` Andreas Gruenbacher
2025-12-16 8:01 ` Christoph Hellwig
2025-12-08 19:37 ` [RFC 00/12] bio cleanups David Sterba
12 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 12:10 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba
Cc: Andreas Gruenbacher, linux-block, linux-btrfs, linux-raid,
dm-devel, linux-kernel
Add a bio_endio_status() helper as a shortcut for calling
bio_set_status() and bio_endio() in sequence. Use the new helper
throughout the code.
Created with Coccinelle using the following semantic patch:
@@
expression bio, status;
@@
- bio_set_status(bio, status);
- bio_endio(bio);
+ bio_endio_status(bio, status);
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
block/bio-integrity-auto.c | 3 +--
block/blk-core.c | 6 ++----
block/blk-mq.c | 6 ++----
drivers/block/drbd/drbd_req.c | 3 +--
drivers/block/ps3vram.c | 3 +--
drivers/md/dm-cache-target.c | 3 +--
drivers/md/dm-integrity.c | 15 +++++----------
drivers/md/dm-mpath.c | 3 +--
drivers/md/dm-raid1.c | 3 +--
drivers/md/dm-thin.c | 3 +--
drivers/md/dm.c | 3 +--
drivers/md/raid1-10.c | 3 +--
drivers/md/raid10.c | 6 ++----
include/linux/bio.h | 12 ++++++++----
14 files changed, 28 insertions(+), 44 deletions(-)
diff --git a/block/bio-integrity-auto.c b/block/bio-integrity-auto.c
index 736d53a7f699..1185f6e15d86 100644
--- a/block/bio-integrity-auto.c
+++ b/block/bio-integrity-auto.c
@@ -190,8 +190,7 @@ bool bio_integrity_prep(struct bio *bio)
err_free_buf:
kfree(buf);
err_end_io:
- bio_set_status(bio, BLK_STS_RESOURCE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_RESOURCE);
return false;
}
EXPORT_SYMBOL(bio_integrity_prep);
diff --git a/block/blk-core.c b/block/blk-core.c
index 95cbb3ffcf9f..8b36674dc09a 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -640,8 +640,7 @@ static void __submit_bio(struct bio *bio)
if ((bio->bi_opf & REQ_POLLED) &&
!(disk->queue->limits.features & BLK_FEAT_POLL)) {
- bio_set_status(bio, BLK_STS_NOTSUPP);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_NOTSUPP);
} else {
disk->fops->submit_bio(bio);
}
@@ -882,8 +881,7 @@ void submit_bio_noacct(struct bio *bio)
not_supported:
status = BLK_STS_NOTSUPP;
end_io:
- bio_set_status(bio, status);
- bio_endio(bio);
+ bio_endio_status(bio, status);
}
EXPORT_SYMBOL(submit_bio_noacct);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 503ca259429f..10933de73205 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -3164,8 +3164,7 @@ void blk_mq_submit_bio(struct bio *bio)
}
if ((bio->bi_opf & REQ_POLLED) && !blk_mq_can_poll(q)) {
- bio_set_status(bio, BLK_STS_NOTSUPP);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_NOTSUPP);
goto queue_exit;
}
@@ -3205,8 +3204,7 @@ void blk_mq_submit_bio(struct bio *bio)
ret = blk_crypto_rq_get_keyslot(rq);
if (ret != BLK_STS_OK) {
- bio_set_status(bio, ret);
- bio_endio(bio);
+ bio_endio_status(bio, ret);
blk_mq_free_request(rq);
return;
}
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 5bedc972b622..41dbf8bbcd61 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1209,8 +1209,7 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio)
/* only pass the error to the upper layers.
* if user cannot handle io errors, that's not our business. */
drbd_err(device, "could not kmalloc() req\n");
- bio_set_status(bio, BLK_STS_RESOURCE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_RESOURCE);
return ERR_PTR(-ENOMEM);
}
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 06844674c998..8b8bdfa50c97 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -573,8 +573,7 @@ static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
next = bio_list_peek(&priv->list);
spin_unlock_irq(&priv->lock);
- bio_set_status(bio, error);
- bio_endio(bio);
+ bio_endio_status(bio, error);
return next;
}
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index d1dbd4ddaadb..da1b1eb29bb8 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -1856,8 +1856,7 @@ static void requeue_deferred_bios(struct cache *cache)
bio_list_merge_init(&bios, &cache->deferred_bios);
while ((bio = bio_list_pop(&bios))) {
- bio_set_status(bio, BLK_STS_DM_REQUEUE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_DM_REQUEUE);
cond_resched();
}
}
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 90780a112009..06e5cdfdec7d 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -2513,8 +2513,7 @@ static int dm_integrity_map_inline(struct dm_integrity_io *dio, bool from_map)
sector_t recalc_sector;
if (unlikely(bio_integrity(bio))) {
- bio_set_status(bio, BLK_STS_NOTSUPP);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_NOTSUPP);
return DM_MAPIO_SUBMITTED;
}
@@ -2535,8 +2534,7 @@ static int dm_integrity_map_inline(struct dm_integrity_io *dio, bool from_map)
if (dio->payload_len > x_size) {
unsigned sectors = ((x_size - extra_size) / ic->tuple_size) << ic->sb->log2_sectors_per_block;
if (WARN_ON(!sectors || sectors >= bio_sectors(bio))) {
- bio_set_status(bio, BLK_STS_NOTSUPP);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_NOTSUPP);
return DM_MAPIO_SUBMITTED;
}
dm_accept_partial_bio(bio, sectors);
@@ -2615,8 +2613,7 @@ static int dm_integrity_map_inline(struct dm_integrity_io *dio, bool from_map)
ret = bio_integrity_add_page(bio, virt_to_page(dio->integrity_payload),
dio->payload_len, offset_in_page(dio->integrity_payload));
if (unlikely(ret != dio->payload_len)) {
- bio_set_status(bio, BLK_STS_RESOURCE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_RESOURCE);
return DM_MAPIO_SUBMITTED;
}
@@ -2668,8 +2665,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
r = bio_integrity_add_page(outgoing_bio, virt_to_page(dio->integrity_payload), ic->tuple_size, 0);
if (unlikely(r != ic->tuple_size)) {
bio_put(outgoing_bio);
- bio_set_status(bio, BLK_STS_RESOURCE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_RESOURCE);
return;
}
@@ -2691,8 +2687,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
dm_audit_log_bio(DM_MSG_PREFIX, "integrity-checksum",
bio, dio->bio_details.bi_iter.bi_sector, 0);
- bio_set_status(bio, BLK_STS_PROTECTION);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_PROTECTION);
return;
}
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 761e5e79d4a7..1097ffb05b00 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -722,8 +722,7 @@ static void process_queued_bios(struct work_struct *work)
bio_io_error(bio);
break;
case DM_MAPIO_REQUEUE:
- bio_set_status(bio, BLK_STS_DM_REQUEUE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_DM_REQUEUE);
break;
case DM_MAPIO_REMAPPED:
submit_bio_noacct(bio);
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index c54995847db0..1f53b125b333 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -627,8 +627,7 @@ static void write_callback(unsigned long error, void *context)
* degrade the array.
*/
if (bio_op(bio) == REQ_OP_DISCARD) {
- bio_set_status(bio, BLK_STS_NOTSUPP);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_NOTSUPP);
return;
}
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index bd061a6bf016..ae8850a3e728 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2731,8 +2731,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
thin_hook_bio(tc, bio);
if (tc->requeue_mode) {
- bio_set_status(bio, BLK_STS_DM_REQUEUE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_DM_REQUEUE);
return DM_MAPIO_SUBMITTED;
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index cbc64377fa96..1743042db9f6 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 */
- bio_set_status(bio, io_error);
- bio_endio(bio);
+ bio_endio_status(bio, io_error);
}
}
diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c
index 504730aba9df..53903bb91408 100644
--- a/drivers/md/raid1-10.c
+++ b/drivers/md/raid1-10.c
@@ -104,8 +104,7 @@ static void md_bio_reset_resync_pages(struct bio *bio, struct resync_pages *rp,
int len = min_t(int, size, PAGE_SIZE);
if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
- bio_set_status(bio, BLK_STS_RESOURCE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_RESOURCE);
return;
}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 7cc27819beb5..7750d6577b83 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -3681,8 +3681,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
struct resync_pages *rp = get_resync_pages(bio);
page = resync_fetch_page(rp, page_idx);
if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
- bio_set_status(bio, BLK_STS_RESOURCE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_RESOURCE);
goto giveup;
}
}
@@ -4863,8 +4862,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,
len = PAGE_SIZE;
for (bio = blist; bio ; bio = bio->bi_next) {
if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
- bio_set_status(bio, BLK_STS_RESOURCE);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_RESOURCE);
return sectors_done;
}
}
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 06fb8ae018c4..8f6ac5fa0a12 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -382,17 +382,21 @@ static inline void bio_set_status(struct bio *bio, blk_status_t status)
WRITE_ONCE(bio->bi_status, status);
}
-static inline void bio_io_error(struct bio *bio)
+static inline void bio_endio_status(struct bio *bio, blk_status_t status)
{
- bio_set_status(bio, BLK_STS_IOERR);
+ bio_set_status(bio, status);
bio_endio(bio);
}
+static inline void bio_io_error(struct bio *bio)
+{
+ bio_endio_status(bio, BLK_STS_IOERR);
+}
+
static inline void bio_wouldblock_error(struct bio *bio)
{
bio_set_flag(bio, BIO_QUIET);
- bio_set_status(bio, BLK_STS_AGAIN);
- bio_endio(bio);
+ bio_endio_status(bio, BLK_STS_AGAIN);
}
blk_status_t errno_to_blk_status(int errno);
--
2.51.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [RFC 00/12] bio cleanups
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
` (11 preceding siblings ...)
2025-12-08 12:10 ` [RFC 12/12] bio: add bio_endio_status Andreas Gruenbacher
@ 2025-12-08 19:37 ` David Sterba
2025-12-08 21:16 ` Andreas Gruenbacher
12 siblings, 1 reply; 27+ messages in thread
From: David Sterba @ 2025-12-08 19:37 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
Satya Tangirala, linux-block, linux-btrfs, linux-raid, dm-devel,
linux-kernel
On Mon, Dec 08, 2025 at 12:10:07PM +0000, Andreas Gruenbacher wrote:
> Hello,
>
> we are not quite careful enough about setting bio->bi_status in all
> places (see BACKGROUND below). This patch queue tries to fix this by
> systematically eliminating the direct assignments to bi_status sprinkled
> all throughout the code. Please comment.
>
>
> The first patch ("bio: rename bio_chain arguments") is an loosely
> related cleanup. The remaining changes are:
>
> - Use bio_io_error() in more places.
>
> - Add a bio_set_errno() helper for setting bi_status based on an errno.
> Use this helper throughout the code.
>
> - Add a bio_set_status() helper for setting bi_status to a blk_status_t
> status code. Use this helper in places in the code where it's
> necessary, or at least useful without adding any overhead.
>
> And on top of that, we have two more cleanups:
>
> - Add a bio_endio_errno() helper that combines bio_set_errno() and
> bio_endio().
>
> - Add a bio_endio_status() helper that combines bio_set_status() and
> bio_endio().
>
> The patches are currently based on v6.18.
>
> GIT tree:
> https://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/log/?h=bio-cleanups
>
> With these changes, only a few direct assignments to bio->bi_status
> remain, in BTRFS and in MD, and SOME OF THOSE MAY BE UNSAFE. Could the
> maintainers of those subsystems please have a look?
The btrfs bits look good to me, we expect the same semantics, ie. not
overwrite existing error with 0. If there are racing writes to the
status like in btrfs_bio_end_io() we use cmpxchg() so we don't overwrite
it.
> Once the remaining direct assignments to bi_status are gone, we may want
> to think about "write protecting" bi_status to prevent unintended new
> direct assignments from creeping back in.
This makes sense, though I'm not sure if this takes into account the
mentioned cmpxchg pattern:
if (status != BLK_STS_OK)
cmpxchg(&bbio->status, BLK_STS_OK, status);
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 00/12] bio cleanups
2025-12-08 19:37 ` [RFC 00/12] bio cleanups David Sterba
@ 2025-12-08 21:16 ` Andreas Gruenbacher
0 siblings, 0 replies; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-08 21:16 UTC (permalink / raw)
To: dsterba
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
Satya Tangirala, linux-block, linux-btrfs, linux-raid, dm-devel,
linux-kernel
On Mon, Dec 8, 2025 at 8:43 PM David Sterba <dsterba@suse.cz> wrote:
> On Mon, Dec 08, 2025 at 12:10:07PM +0000, Andreas Gruenbacher wrote:
> > With these changes, only a few direct assignments to bio->bi_status
> > remain, in BTRFS and in MD, and SOME OF THOSE MAY BE UNSAFE. Could the
> > maintainers of those subsystems please have a look?
>
> The btrfs bits look good to me, we expect the same semantics, ie. not
> overwrite existing error with 0. If there are racing writes to the
> status like in btrfs_bio_end_io() we use cmpxchg() so we don't overwrite
> it.
Really? I'm not talking about the status field in struct btrfs_bio but
about the bi_status field in struct bio. The first mention of
bi_status I can find in the btrfs code is right at the beginning of
btrfs_bio_end_io():
bbio->bio.bi_status = status;
If status is ever BLK_STS_OK (0) here and bbio->bio is a chained bio,
things are already not great.
I believe we should eliminate all direct assignments to bi_status and
use bio_set_status() instead. I'm not familiar enough with the btrfs
code to make that replacement for you, though.
A cursory look at struct btrfs_bio suggests that those objects cannot
be chained like plain old bios (bio_chain()). This means that
cmpxchg() may actually work for catching the first error that occurs.
For chained regular bios, cmpxchg() won't catch the first error, at
least not if the length of the chain is greater than two.
Thanks,
Andreas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 01/12] bio: rename bio_chain arguments
2025-12-08 12:10 ` [RFC 01/12] bio: rename bio_chain arguments Andreas Gruenbacher
@ 2025-12-16 7:57 ` Christoph Hellwig
0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-16 7:57 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 02/12] bio: use bio_io_error more often
2025-12-08 12:10 ` [RFC 02/12] bio: use bio_io_error more often Andreas Gruenbacher
@ 2025-12-16 7:57 ` Christoph Hellwig
0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-16 7:57 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 03/12] bio: add bio_set_errno
2025-12-08 12:10 ` [RFC 03/12] bio: add bio_set_errno Andreas Gruenbacher
@ 2025-12-16 7:58 ` Christoph Hellwig
0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-16 7:58 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
On Mon, Dec 08, 2025 at 12:10:10PM +0000, Andreas Gruenbacher wrote:
> Add a bio_set_errno(bio, errno) helper that sets bio->bi_status to
> errno_to_blk_status(errno) if errno != 0. Replace instances of this
> pattern in the code with a call to the new helper.
>
> The WRITE_ONCE() in bio_set_errno() ensures that the compiler won't
> reorder things in a weird way, but it isn't needed to prevent tearing
> because a single-byte field like bi_status cannot tear.
Not a fan of this. We should not be doing that very often (and as
seen by the diff don't), so don't add a helper for it that makes
people do it more often.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 06/12] bio: don't check target->bi_status on error
2025-12-08 12:10 ` [RFC 06/12] bio: don't check target->bi_status on error Andreas Gruenbacher
@ 2025-12-16 7:59 ` Christoph Hellwig
2025-12-16 8:41 ` Andreas Gruenbacher
0 siblings, 1 reply; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-16 7:59 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
On Mon, Dec 08, 2025 at 12:10:13PM +0000, Andreas Gruenbacher wrote:
> In a few places, target->bi_status is set to source->bi_status only if
> source->bi_status is not 0 and target->bi_status is (still) 0. Here,
> checking the value of target->bi_status before setting it is an
> unnecessary micro optimization because we are already on an error path.
What is source and target here? I have a hard time trying to follow
what this is trying to do.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 05/12] bio: add bio_set_status
2025-12-08 12:10 ` [RFC 05/12] bio: add bio_set_status Andreas Gruenbacher
@ 2025-12-16 7:59 ` Christoph Hellwig
0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-16 7:59 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
On Mon, Dec 08, 2025 at 12:10:12PM +0000, Andreas Gruenbacher wrote:
> 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.
Why? Also the name suggest it is the canonical way to set a
status, and not just a helper to set it conditionally.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 11/12] bio: add bio_endio_errno
2025-12-08 12:10 ` [RFC 11/12] bio: add bio_endio_errno Andreas Gruenbacher
@ 2025-12-16 8:00 ` Christoph Hellwig
0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-16 8:00 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
Please push out usage of errno from block code instead of making
this more easy.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 12/12] bio: add bio_endio_status
2025-12-08 12:10 ` [RFC 12/12] bio: add bio_endio_status Andreas Gruenbacher
@ 2025-12-16 8:01 ` Christoph Hellwig
0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-16 8:01 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
On Mon, Dec 08, 2025 at 12:10:19PM +0000, Andreas Gruenbacher wrote:
> Add a bio_endio_status() helper as a shortcut for calling
> bio_set_status() and bio_endio() in sequence. Use the new helper
> throughout the code.
Looks fine, although you probably want to either feed the users through
the subsystems or did a scripted one right after the next -rc1.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 06/12] bio: don't check target->bi_status on error
2025-12-16 7:59 ` Christoph Hellwig
@ 2025-12-16 8:41 ` Andreas Gruenbacher
2025-12-16 10:44 ` Christoph Hellwig
0 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-16 8:41 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, Chris Mason, David Sterba, linux-block, linux-btrfs,
linux-raid, dm-devel, linux-kernel
On Tue, Dec 16, 2025 at 8:59 AM Christoph Hellwig <hch@infradead.org> wrote:
> On Mon, Dec 08, 2025 at 12:10:13PM +0000, Andreas Gruenbacher wrote:
> > In a few places, target->bi_status is set to source->bi_status only if
> > source->bi_status is not 0 and target->bi_status is (still) 0. Here,
> > checking the value of target->bi_status before setting it is an
> > unnecessary micro optimization because we are already on an error path.
>
> What is source and target here? I have a hard time trying to follow
> what this is trying to do.
Not sure, what would you suggest instead?
Thanks,
Andreas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 06/12] bio: don't check target->bi_status on error
2025-12-16 8:41 ` Andreas Gruenbacher
@ 2025-12-16 10:44 ` Christoph Hellwig
2025-12-16 11:20 ` Andreas Gruenbacher
0 siblings, 1 reply; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-16 10:44 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
On Tue, Dec 16, 2025 at 09:41:49AM +0100, Andreas Gruenbacher wrote:
> On Tue, Dec 16, 2025 at 8:59 AM Christoph Hellwig <hch@infradead.org> wrote:
> > On Mon, Dec 08, 2025 at 12:10:13PM +0000, Andreas Gruenbacher wrote:
> > > In a few places, target->bi_status is set to source->bi_status only if
> > > source->bi_status is not 0 and target->bi_status is (still) 0. Here,
> > > checking the value of target->bi_status before setting it is an
> > > unnecessary micro optimization because we are already on an error path.
> >
> > What is source and target here? I have a hard time trying to follow
> > what this is trying to do.
>
> Not sure, what would you suggest instead?
I still don't understand what you're saying here at all, or what this is
trying to fix or optimize.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 06/12] bio: don't check target->bi_status on error
2025-12-16 10:44 ` Christoph Hellwig
@ 2025-12-16 11:20 ` Andreas Gruenbacher
2025-12-18 8:47 ` Christoph Hellwig
0 siblings, 1 reply; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-16 11:20 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, Chris Mason, David Sterba, linux-block, linux-btrfs,
linux-raid, dm-devel, linux-kernel
On Tue, Dec 16, 2025 at 11:44 AM Christoph Hellwig <hch@infradead.org> wrote:
> On Tue, Dec 16, 2025 at 09:41:49AM +0100, Andreas Gruenbacher wrote:
> > On Tue, Dec 16, 2025 at 8:59 AM Christoph Hellwig <hch@infradead.org> wrote:
> > > On Mon, Dec 08, 2025 at 12:10:13PM +0000, Andreas Gruenbacher wrote:
> > > > In a few places, target->bi_status is set to source->bi_status only if
> > > > source->bi_status is not 0 and target->bi_status is (still) 0. Here,
> > > > checking the value of target->bi_status before setting it is an
> > > > unnecessary micro optimization because we are already on an error path.
> > >
> > > What is source and target here? I have a hard time trying to follow
> > > what this is trying to do.
> >
> > Not sure, what would you suggest instead?
>
> I still don't understand what you're saying here at all, or what this is
> trying to fix or optimize.
When we have this construct in the code and we know that status is not 0:
if (!bio->bi_status)
bio->bi_status = status;
we can just do this instead:
bio>bi_status = status;
Andreas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 06/12] bio: don't check target->bi_status on error
2025-12-16 11:20 ` Andreas Gruenbacher
@ 2025-12-18 8:47 ` Christoph Hellwig
2025-12-19 20:14 ` Andreas Gruenbacher
0 siblings, 1 reply; 27+ messages in thread
From: Christoph Hellwig @ 2025-12-18 8:47 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Christoph Hellwig, Jens Axboe, Chris Mason, David Sterba,
linux-block, linux-btrfs, linux-raid, dm-devel, linux-kernel
On Tue, Dec 16, 2025 at 12:20:07PM +0100, Andreas Gruenbacher wrote:
> > I still don't understand what you're saying here at all, or what this is
> > trying to fix or optimize.
>
> When we have this construct in the code and we know that status is not 0:
>
> if (!bio->bi_status)
> bio->bi_status = status;
>
> we can just do this instead:
>
> bio>bi_status = status;
But this now overrides the previous status instead of preserving the
first error?
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 06/12] bio: don't check target->bi_status on error
2025-12-18 8:47 ` Christoph Hellwig
@ 2025-12-19 20:14 ` Andreas Gruenbacher
0 siblings, 0 replies; 27+ messages in thread
From: Andreas Gruenbacher @ 2025-12-19 20:14 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, Chris Mason, David Sterba, linux-block, linux-btrfs,
linux-raid, dm-devel, linux-kernel
On Thu, Dec 18, 2025 at 10:08 AM Christoph Hellwig <hch@infradead.org> wrote:
> On Tue, Dec 16, 2025 at 12:20:07PM +0100, Andreas Gruenbacher wrote:
> > > I still don't understand what you're saying here at all, or what this is
> > > trying to fix or optimize.
> >
> > When we have this construct in the code and we know that status is not 0:
> >
> > if (!bio->bi_status)
> > bio->bi_status = status;
> >
> > we can just do this instead:
> >
> > bio>bi_status = status;
>
> But this now overrides the previous status instead of preserving the
> first error?
This is exactly my point: we already don't preserve the first error,
it only looks like we do. Here are the possible cases:
(1) A single bio A: there are no competing completions. A->bi_status
is set before calling bio_endio(), and it can be set to any value
including BLK_STS_OK (0) with a simple assignment.
(2) An A -> B chain: there are two competing completions, and
B->bi_status is the resulting status of the bio chain. Both
completions will immediately update B->bi_status. When B->bi_status is
updated, it must not be set to BLK_STS_OK (0) or else a previous
non-zero status code could be wiped out. But for such a non-zero
status code, a construct like 'if (B->status != BLK_STS_OK) B->status
= status' is no better than a simple 'B->status = status' because the
if is not atomic. But we only care about preserving an error code, not
the first error code that occurred, so that's fine.
(3) An A -> B -> C chain: There are three competing completions, and
C->bi_status is the resulting status of the bio chain. Not all
completions will immediately update C->bi_status, but if at least one
of the completions fails, we know that we will always end up with a
non-zero error code in C->bi_status eventually.
And again, switching to cmpxchg() would not always preserve the first
error, either: for example, in case (3), if the bios complete in the
order A, C, B and they all fail, C->bi_status would end up with the
error code of C instead of A even though A completed before C.
This could be fixed by chaining all consecutive bios to bio A (the
first one) and reversing the pointer direction so that all cmpxchg()
operations will target A->bi_status. But again, I don't think
preserving the first error is actually needed. And it certainly isn't
being done today.
Thanks,
Andreas
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2025-12-19 20:14 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-08 12:10 [RFC 00/12] bio cleanups Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 01/12] bio: rename bio_chain arguments Andreas Gruenbacher
2025-12-16 7:57 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 02/12] bio: use bio_io_error more often Andreas Gruenbacher
2025-12-16 7:57 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 03/12] bio: add bio_set_errno Andreas Gruenbacher
2025-12-16 7:58 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 04/12] bio: use bio_set_errno in more places Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 05/12] bio: add bio_set_status Andreas Gruenbacher
2025-12-16 7:59 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 06/12] bio: don't check target->bi_status on error Andreas Gruenbacher
2025-12-16 7:59 ` Christoph Hellwig
2025-12-16 8:41 ` Andreas Gruenbacher
2025-12-16 10:44 ` Christoph Hellwig
2025-12-16 11:20 ` Andreas Gruenbacher
2025-12-18 8:47 ` Christoph Hellwig
2025-12-19 20:14 ` Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 07/12] bio: use bio_set_status for BLK_STS_* status codes Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 08/12] bio: use bio_set_status in some more places Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 09/12] bio: switch to bio_set_status in submit_bio_noacct Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 10/12] bio: never set bi_status to BLK_STS_OK during completion Andreas Gruenbacher
2025-12-08 12:10 ` [RFC 11/12] bio: add bio_endio_errno Andreas Gruenbacher
2025-12-16 8:00 ` Christoph Hellwig
2025-12-08 12:10 ` [RFC 12/12] bio: add bio_endio_status Andreas Gruenbacher
2025-12-16 8:01 ` Christoph Hellwig
2025-12-08 19:37 ` [RFC 00/12] bio cleanups David Sterba
2025-12-08 21:16 ` Andreas Gruenbacher
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).