]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: Finish bch2_account_io_completion() conversions
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 28 Feb 2025 19:38:47 +0000 (14:38 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 15 Mar 2025 01:02:16 +0000 (21:02 -0400)
More prep work for automatically kicking devices out after too many IO
errors.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_io.c
fs/bcachefs/btree_node_scan.c
fs/bcachefs/ec.c
fs/bcachefs/errcode.h
fs/bcachefs/error.h
fs/bcachefs/io_write.c
fs/bcachefs/journal_io.c
fs/bcachefs/journal_types.h
fs/bcachefs/super-io.c

index 18413b4f22a310f2bfe04294017b6edf5e749748..cd792fee7ee3ff51b328c018b9f5692b9869ebfe 100644 (file)
@@ -1329,6 +1329,7 @@ static void btree_node_read_work(struct work_struct *work)
                bch_info(c, "retrying read");
                ca = bch2_dev_get_ioref(c, rb->pick.ptr.dev, READ);
                rb->have_ioref          = ca != NULL;
+               rb->start_time          = local_clock();
                bio_reset(bio, NULL, REQ_OP_READ|REQ_SYNC|REQ_META);
                bio->bi_iter.bi_sector  = rb->pick.ptr.offset;
                bio->bi_iter.bi_size    = btree_buf_bytes(b);
@@ -1339,12 +1340,17 @@ static void btree_node_read_work(struct work_struct *work)
                } else {
                        bio->bi_status = BLK_STS_REMOVED;
                }
+
+               bch2_account_io_completion(ca, BCH_MEMBER_ERROR_read,
+                                          rb->start_time, !bio->bi_status);
 start:
                printbuf_reset(&buf);
                bch2_btree_pos_to_text(&buf, c, b);
-               bch2_dev_io_err_on(ca && bio->bi_status, ca, BCH_MEMBER_ERROR_read,
-                                  "btree read error %s for %s",
-                                  bch2_blk_status_to_str(bio->bi_status), buf.buf);
+
+               if (ca && bio->bi_status)
+                       bch_err_dev_ratelimited(ca,
+                                       "btree read error %s for %s",
+                                       bch2_blk_status_to_str(bio->bi_status), buf.buf);
                if (rb->have_ioref)
                        percpu_ref_put(&ca->io_ref);
                rb->have_ioref = false;
@@ -1401,12 +1407,11 @@ static void btree_node_read_endio(struct bio *bio)
        struct btree_read_bio *rb =
                container_of(bio, struct btree_read_bio, bio);
        struct bch_fs *c        = rb->c;
+       struct bch_dev *ca      = rb->have_ioref
+               ? bch2_dev_have_ref(c, rb->pick.ptr.dev) : NULL;
 
-       if (rb->have_ioref) {
-               struct bch_dev *ca = bch2_dev_have_ref(c, rb->pick.ptr.dev);
-
-               bch2_latency_acct(ca, rb->start_time, READ);
-       }
+       bch2_account_io_completion(ca, BCH_MEMBER_ERROR_read,
+                                  rb->start_time, !bio->bi_status);
 
        queue_work(c->btree_read_complete_wq, &rb->work);
 }
@@ -2126,16 +2131,17 @@ static void btree_node_write_endio(struct bio *bio)
        struct bch_fs *c                = wbio->c;
        struct btree *b                 = wbio->bio.bi_private;
        struct bch_dev *ca              = wbio->have_ioref ? bch2_dev_have_ref(c, wbio->dev) : NULL;
-       unsigned long flags;
 
-       if (wbio->have_ioref)
-               bch2_latency_acct(ca, wbio->submit_time, WRITE);
+       bch2_account_io_completion(ca, BCH_MEMBER_ERROR_write,
+                                  wbio->submit_time, !bio->bi_status);
+
+       if (ca && bio->bi_status)
+               bch_err_dev_ratelimited(ca,
+                                  "btree write error: %s",
+                                  bch2_blk_status_to_str(bio->bi_status));
 
-       if (!ca ||
-           bch2_dev_io_err_on(bio->bi_status, ca, BCH_MEMBER_ERROR_write,
-                              "btree write error: %s",
-                              bch2_blk_status_to_str(bio->bi_status)) ||
-           bch2_meta_write_fault("btree")) {
+       if (bio->bi_status) {
+               unsigned long flags;
                spin_lock_irqsave(&c->btree_write_error_lock, flags);
                bch2_dev_list_add_dev(&orig->failed, wbio->dev);
                spin_unlock_irqrestore(&c->btree_write_error_lock, flags);
index a7f06deee13c34c56b0fd05d655e05e8fa01762b..fb73ec77c099f2b15c9875ad3a010ed3873b026d 100644 (file)
@@ -166,11 +166,17 @@ static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca,
        bio->bi_iter.bi_sector  = offset;
        bch2_bio_map(bio, bn, PAGE_SIZE);
 
+       u64 submit_time = local_clock();
        submit_bio_wait(bio);
-       if (bch2_dev_io_err_on(bio->bi_status, ca, BCH_MEMBER_ERROR_read,
-                              "IO error in try_read_btree_node() at %llu: %s",
-                              offset, bch2_blk_status_to_str(bio->bi_status)))
+
+       bch2_account_io_completion(ca, BCH_MEMBER_ERROR_read, submit_time, !bio->bi_status);
+
+       if (bio->bi_status) {
+               bch_err_dev_ratelimited(ca,
+                               "IO error in try_read_btree_node() at %llu: %s",
+                               offset, bch2_blk_status_to_str(bio->bi_status));
                return;
+       }
 
        if (le64_to_cpu(bn->magic) != bset_magic(c))
                return;
index 1090cdb7d5cce70f49c9a8c4d04ab4d504400877..8c7a9addafae2c053e7626b7e1e0425d9b30f156 100644 (file)
@@ -105,6 +105,7 @@ struct ec_bio {
        struct bch_dev          *ca;
        struct ec_stripe_buf    *buf;
        size_t                  idx;
+       u64                     submit_time;
        struct bio              bio;
 };
 
@@ -748,14 +749,15 @@ static void ec_block_endio(struct bio *bio)
        struct bch_dev *ca = ec_bio->ca;
        struct closure *cl = bio->bi_private;
 
-       if (bch2_dev_io_err_on(bio->bi_status, ca,
-                              bio_data_dir(bio)
-                              ? BCH_MEMBER_ERROR_write
-                              : BCH_MEMBER_ERROR_read,
-                              "erasure coding %s error: %s",
+       bch2_account_io_completion(ca, bio_data_dir(bio),
+                                  ec_bio->submit_time, !bio->bi_status);
+
+       if (bio->bi_status) {
+               bch_err_dev_ratelimited(ca, "erasure coding %s error: %s",
                               str_write_read(bio_data_dir(bio)),
-                              bch2_blk_status_to_str(bio->bi_status)))
+                              bch2_blk_status_to_str(bio->bi_status));
                clear_bit(ec_bio->idx, ec_bio->buf->valid);
+       }
 
        int stale = dev_ptr_stale(ca, ptr);
        if (stale) {
@@ -818,6 +820,7 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
                ec_bio->ca                      = ca;
                ec_bio->buf                     = buf;
                ec_bio->idx                     = idx;
+               ec_bio->submit_time             = local_clock();
 
                ec_bio->bio.bi_iter.bi_sector   = ptr->offset + buf->offset + (offset >> 9);
                ec_bio->bio.bi_end_io           = ec_block_endio;
index ed4214e9bebaef6e40c6b5198da07bd083a6afd8..d45ef03abc91a283b16c139d4bd2cce7055cab5a 100644 (file)
        x(EIO,                          no_encryption_key)                      \
        x(EIO,                          insufficient_journal_devices)           \
        x(EIO,                          device_offline)                         \
+       x(EIO,                          EIO_fault_injected)                     \
        x(BCH_ERR_btree_node_read_err,  btree_node_read_err_fixable)            \
        x(BCH_ERR_btree_node_read_err,  btree_node_read_err_want_retry)         \
        x(BCH_ERR_btree_node_read_err,  btree_node_read_err_must_retry)         \
index e055b606fb6f68754823fbfb4f371acf20aad828..a57b9f18d0602ad71b7a20e22253f4b91372843b 100644 (file)
@@ -222,6 +222,14 @@ void bch2_latency_acct(struct bch_dev *, u64, int);
 static inline void bch2_latency_acct(struct bch_dev *ca, u64 submit_time, int rw) {}
 #endif
 
+static inline void bch2_account_io_success_fail(struct bch_dev *ca,
+                                               enum bch_member_error_type type,
+                                               bool success)
+{
+       if (!success)
+               bch2_io_error(ca, type);
+}
+
 static inline void bch2_account_io_completion(struct bch_dev *ca,
                                              enum bch_member_error_type type,
                                              u64 submit_time, bool success)
@@ -232,32 +240,9 @@ static inline void bch2_account_io_completion(struct bch_dev *ca,
        if (type != BCH_MEMBER_ERROR_checksum)
                bch2_latency_acct(ca, submit_time, type);
 
-       if (!success)
-               bch2_io_error(ca, type);
+       bch2_account_io_success_fail(ca, type, success);
 }
 
-#define bch2_dev_io_err_on(cond, ca, _type, ...)                       \
-({                                                                     \
-       bool _ret = (cond);                                             \
-                                                                       \
-       if (_ret) {                                                     \
-               bch_err_dev_ratelimited(ca, __VA_ARGS__);               \
-               bch2_io_error(ca, _type);                               \
-       }                                                               \
-       _ret;                                                           \
-})
-
-#define bch2_dev_inum_io_err_on(cond, ca, _type, ...)                  \
-({                                                                     \
-       bool _ret = (cond);                                             \
-                                                                       \
-       if (_ret) {                                                     \
-               bch_err_inum_offset_ratelimited(ca, __VA_ARGS__);       \
-               bch2_io_error(ca, _type);                               \
-       }                                                               \
-       _ret;                                                           \
-})
-
 int bch2_inum_offset_err_msg_trans(struct btree_trans *, struct printbuf *, subvol_inum, u64);
 
 void bch2_inum_offset_err_msg(struct bch_fs *, struct printbuf *, subvol_inum, u64);
index 738bdbfbdb149bf886fd7e7c5b6c6d33dabb2cf5..dbfcb28f003d2e82f496389d95964545ba52677b 100644 (file)
@@ -716,11 +716,15 @@ static void bch2_write_endio(struct bio *bio)
                ? bch2_dev_have_ref(c, wbio->dev)
                : NULL;
 
-       if (bch2_dev_inum_io_err_on(bio->bi_status, ca, BCH_MEMBER_ERROR_write,
+       bch2_account_io_completion(ca, BCH_MEMBER_ERROR_write,
+                                  wbio->submit_time, !bio->bi_status);
+
+       if (bio->bi_status) {
+               bch_err_inum_offset_ratelimited(ca,
                                    op->pos.inode,
                                    wbio->inode_offset << 9,
                                    "data write error: %s",
-                                   bch2_blk_status_to_str(bio->bi_status))) {
+                                   bch2_blk_status_to_str(bio->bi_status));
                set_bit(wbio->dev, op->failed.d);
                op->flags |= BCH_WRITE_io_error;
        }
@@ -732,10 +736,8 @@ static void bch2_write_endio(struct bio *bio)
                set_bit(wbio->dev, op->devs_need_flush->d);
        }
 
-       if (wbio->have_ioref) {
-               bch2_latency_acct(ca, wbio->submit_time, WRITE);
+       if (wbio->have_ioref)
                percpu_ref_put(&ca->io_ref);
-       }
 
        if (wbio->bounce)
                bch2_bio_free_pages_pool(c, bio);
index 7d59ccc073154f67c7a4b66e32e58a6e902b9300..c12d9f9bd5368f08051b6b2167f59b194c76ae87 100644 (file)
@@ -1041,13 +1041,19 @@ reread:
                        bio->bi_iter.bi_sector = offset;
                        bch2_bio_map(bio, buf->data, sectors_read << 9);
 
+                       u64 submit_time = local_clock();
                        ret = submit_bio_wait(bio);
                        kfree(bio);
 
-                       if (bch2_dev_io_err_on(ret, ca, BCH_MEMBER_ERROR_read,
-                                              "journal read error: sector %llu",
-                                              offset) ||
-                           bch2_meta_read_fault("journal")) {
+                       if (!ret && bch2_meta_read_fault("journal"))
+                               ret = -BCH_ERR_EIO_fault_injected;
+
+                       bch2_account_io_completion(ca, BCH_MEMBER_ERROR_read,
+                                                  submit_time, !ret);
+
+                       if (ret) {
+                               bch_err_dev_ratelimited(ca,
+                                       "journal read error: sector %llu", offset);
                                /*
                                 * We don't error out of the recovery process
                                 * here, since the relevant journal entry may be
@@ -1110,13 +1116,16 @@ reread:
                struct bch_csum csum;
                csum_good = jset_csum_good(c, j, &csum);
 
-               if (bch2_dev_io_err_on(!csum_good, ca, BCH_MEMBER_ERROR_checksum,
-                                      "%s",
-                                      (printbuf_reset(&err),
-                                       prt_str(&err, "journal "),
-                                       bch2_csum_err_msg(&err, csum_type, j->csum, csum),
-                                       err.buf)))
+               bch2_account_io_completion(ca, BCH_MEMBER_ERROR_checksum, 0, csum_good);
+
+               if (!csum_good) {
+                       bch_err_dev_ratelimited(ca, "%s",
+                               (printbuf_reset(&err),
+                                prt_str(&err, "journal "),
+                                bch2_csum_err_msg(&err, csum_type, j->csum, csum),
+                                err.buf));
                        saw_bad = true;
+               }
 
                ret = bch2_encrypt(c, JSET_CSUM_TYPE(j), journal_nonce(j),
                             j->encrypted_start,
@@ -1727,13 +1736,16 @@ static void journal_write_endio(struct bio *bio)
        struct journal *j = &ca->fs->journal;
        struct journal_buf *w = j->buf + jbio->buf_idx;
 
-       if (bch2_dev_io_err_on(bio->bi_status, ca, BCH_MEMBER_ERROR_write,
+       bch2_account_io_completion(ca, BCH_MEMBER_ERROR_write,
+                                  jbio->submit_time, !bio->bi_status);
+
+       if (bio->bi_status) {
+               bch_err_dev_ratelimited(ca,
                               "error writing journal entry %llu: %s",
                               le64_to_cpu(w->data->seq),
-                              bch2_blk_status_to_str(bio->bi_status)) ||
-           bch2_meta_write_fault("journal")) {
-               unsigned long flags;
+                              bch2_blk_status_to_str(bio->bi_status));
 
+               unsigned long flags;
                spin_lock_irqsave(&j->err_lock, flags);
                bch2_dev_list_drop_dev(&w->devs_written, ca->dev_idx);
                spin_unlock_irqrestore(&j->err_lock, flags);
@@ -1762,7 +1774,11 @@ static CLOSURE_CALLBACK(journal_write_submit)
                             sectors);
 
                struct journal_device *ja = &ca->journal;
-               struct bio *bio = &ja->bio[w->idx]->bio;
+               struct journal_bio *jbio = ja->bio[w->idx];
+               struct bio *bio = &jbio->bio;
+
+               jbio->submit_time       = local_clock();
+
                bio_reset(bio, ca->disk_sb.bdev, REQ_OP_WRITE|REQ_SYNC|REQ_META);
                bio->bi_iter.bi_sector  = ptr->offset;
                bio->bi_end_io          = journal_write_endio;
index a0b17c6ed83e56e13b7305dc4806f0eedec2e022..fd82f5d80355a74d5c4e5ab8bdb3c0a9fdc8aa0a 100644 (file)
@@ -175,6 +175,7 @@ typedef DARRAY(u64)         darray_u64;
 struct journal_bio {
        struct bch_dev          *ca;
        unsigned                buf_idx;
+       u64                     submit_time;
 
        struct bio              bio;
 };
index 9a204baa3ab977d49dec4069bec6a8f9683168e8..2fef285cfc1ac5c702245f4a6629ddd15105c7f9 100644 (file)
@@ -911,16 +911,16 @@ static void write_super_endio(struct bio *bio)
 {
        struct bch_dev *ca = bio->bi_private;
 
+       bch2_account_io_success_fail(ca, bio_data_dir(bio), !bio->bi_status);
+
        /* XXX: return errors directly */
 
-       if (bch2_dev_io_err_on(bio->bi_status, ca,
-                              bio_data_dir(bio)
-                              ? BCH_MEMBER_ERROR_write
-                              : BCH_MEMBER_ERROR_read,
-                              "superblock %s error: %s",
+       if (bio->bi_status) {
+               bch_err_dev_ratelimited(ca, "superblock %s error: %s",
                               str_write_read(bio_data_dir(bio)),
-                              bch2_blk_status_to_str(bio->bi_status)))
+                              bch2_blk_status_to_str(bio->bi_status));
                ca->sb_write_error = 1;
+       }
 
        closure_put(&ca->fs->sb_write);
        percpu_ref_put(&ca->io_ref);