]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: btrfs_log_dev_io_error() on all bio errors
authorBoris Burkov <boris@bur.io>
Mon, 6 Apr 2026 16:15:15 +0000 (09:15 -0700)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 Apr 2026 18:00:29 +0000 (20:00 +0200)
As far as I can tell, we never intentionally constrained ourselves to
these status codes, and it is misleading and surprising to lack the
bdev error logging when we get a different error code from the block
layer. This can lead to jumping to a wrong conclusion like "this
system didn't see any bio failures but aborted with EIO".

For example on nvme devices, I observe many failures coming back as
BLK_STS_MEDIUM. It is apparent that the nvme driver returns a variety of
BLK_STS_* status values in nvme_error_status().

So handle the known expected errors and make some noise on the rest
which we expect won't really happen.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Anand Jain <asj@kernel.org>
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/bio.c

index 2a2a21aec8178cbbaccb96739d0e313ef7b1d251..cc0bd03048bae645da52a9823813c1cfb8043687 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2022 Christoph Hellwig.
  */
 
+#include <linux/blk_types.h>
 #include <linux/bio.h>
 #include "bio.h"
 #include "ctree.h"
@@ -350,11 +351,18 @@ static void btrfs_check_read_bio(struct btrfs_bio *bbio, struct btrfs_device *de
 
 static void btrfs_log_dev_io_error(const struct bio *bio, struct btrfs_device *dev)
 {
+       blk_status_t sts = bio->bi_status;
+
        if (!dev || !dev->bdev)
                return;
-       if (bio->bi_status != BLK_STS_IOERR && bio->bi_status != BLK_STS_TARGET)
+       if (unlikely(sts == BLK_STS_OK))
                return;
-
+       if (unlikely(sts != BLK_STS_IOERR && sts != BLK_STS_TARGET &&
+                    sts != BLK_STS_MEDIUM && sts != BLK_STS_PROTECTION)) {
+               btrfs_warn_rl(dev->fs_info, "bdev %s unexpected block io error: %d",
+                             btrfs_dev_name(dev), sts);
+               return;
+       }
        if (btrfs_op(bio) == BTRFS_MAP_WRITE)
                btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
        else if (!(bio->bi_opf & REQ_RAHEAD))