From: Kent Overstreet <kent.overstreet@linux.dev>
To: linux-bcachefs@vger.kernel.org
Cc: Kent Overstreet <kent.overstreet@linux.dev>
Subject: [PATCH 09/14] bcachefs: __bch2_read() now takes a btree_trans
Date: Tue, 11 Mar 2025 16:15:11 -0400 [thread overview]
Message-ID: <20250311201518.3573009-10-kent.overstreet@linux.dev> (raw)
In-Reply-To: <20250311201518.3573009-1-kent.overstreet@linux.dev>
Next patch will be checking if the extent we're reading from matches the
IO failure we saw before marking the failure.
For this to work, __bch2_read() needs to take the same transaction
context that bch2_rbio_retry() uses to do that check.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
---
fs/bcachefs/io_read.c | 90 ++++++++++++++++++++++++++++++++++---------
fs/bcachefs/io_read.h | 12 +++---
2 files changed, 79 insertions(+), 23 deletions(-)
diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c
index 40a23e779e6c..b5bcd08fc983 100644
--- a/fs/bcachefs/io_read.c
+++ b/fs/bcachefs/io_read.c
@@ -416,13 +416,53 @@ static void bch2_rbio_done(struct bch_read_bio *rbio)
bio_endio(&rbio->bio);
}
-static noinline int bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio,
- struct bvec_iter bvec_iter,
- struct bch_io_failures *failed,
- unsigned flags)
+static struct bkey_s_c get_rbio_extent(struct btree_trans *trans,
+ struct bch_read_bio *rbio,
+ struct btree_iter *iter)
+{
+ if (rbio->flags & BCH_READ_data_update) {
+ struct data_update *u = container_of(rbio, struct data_update, rbio);
+
+ return bch2_bkey_get_iter(trans, iter,
+ u->btree_id, bkey_start_pos(&u->k.k->k), 0);
+ } else {
+ struct bpos pos = rbio->read_pos;
+ int ret = bch2_subvolume_get_snapshot(trans, rbio->subvol, &pos.snapshot);
+ if (ret)
+ return bkey_s_c_err(ret);
+
+ return bch2_bkey_get_iter(trans, iter, BTREE_ID_extents, pos, 0);
+ }
+}
+
+static void mark_io_failure_if_current_extent_matches(struct btree_trans *trans,
+ struct bch_read_bio *rbio,
+ struct bch_io_failures *failed)
+{
+ struct btree_iter iter = {};
+ struct bkey_s_c k;
+ int ret = lockrestart_do(trans,
+ bkey_err(k = get_rbio_extent(trans, rbio, &iter)));
+
+ if (!ret) {
+ struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
+
+ bkey_for_each_ptr(ptrs, ptr)
+ if (bch2_extent_ptr_eq(*ptr, rbio->pick.ptr))
+ bch2_mark_io_failure(failed, &rbio->pick,
+ rbio->ret == -BCH_ERR_data_read_retry_csum_err);
+ }
+
+ bch2_trans_iter_exit(trans, &iter);
+}
+
+static noinline int bch2_read_retry_nodecode(struct btree_trans *trans,
+ struct bch_read_bio *rbio,
+ struct bvec_iter bvec_iter,
+ struct bch_io_failures *failed,
+ unsigned flags)
{
struct data_update *u = container_of(rbio, struct data_update, rbio);
- struct btree_trans *trans = bch2_trans_get(c);
retry:
bch2_trans_begin(trans);
@@ -458,8 +498,6 @@ static noinline int bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_b
}
BUG_ON(atomic_read(&rbio->bio.__bi_remaining) != 1);
- bch2_trans_put(trans);
-
return ret;
}
@@ -475,14 +513,14 @@ static void bch2_rbio_retry(struct work_struct *work)
.inum = rbio->read_pos.inode,
};
struct bch_io_failures failed = { .nr = 0 };
+ struct btree_trans *trans = bch2_trans_get(c);
trace_io_read_retry(&rbio->bio);
this_cpu_add(c->counters[BCH_COUNTER_io_read_retry],
bvec_iter_sectors(rbio->bvec_iter));
if (bch2_err_matches(rbio->ret, BCH_ERR_data_read_retry_avoid))
- bch2_mark_io_failure(&failed, &rbio->pick,
- rbio->ret == -BCH_ERR_data_read_retry_csum_err);
+ mark_io_failure_if_current_extent_matches(trans, rbio, &failed);
if (!rbio->split) {
rbio->bio.bi_status = 0;
@@ -500,8 +538,8 @@ static void bch2_rbio_retry(struct work_struct *work)
flags |= BCH_READ_must_clone;
int ret = flags & BCH_READ_data_update
- ? bch2_read_retry_nodecode(c, rbio, iter, &failed, flags)
- : __bch2_read(c, rbio, iter, inum, &failed, flags);
+ ? bch2_read_retry_nodecode(trans, rbio, iter, &failed, flags)
+ : __bch2_read(trans, rbio, iter, inum, &failed, flags);
if (ret) {
rbio->ret = ret;
@@ -509,7 +547,7 @@ static void bch2_rbio_retry(struct work_struct *work)
} else {
struct printbuf buf = PRINTBUF;
- bch2_trans_do(c,
+ lockrestart_do(trans,
bch2_inum_offset_err_msg_trans(trans, &buf,
(subvol_inum) { subvol, read_pos.inode },
read_pos.offset << 9));
@@ -522,6 +560,7 @@ static void bch2_rbio_retry(struct work_struct *work)
}
bch2_rbio_done(rbio);
+ bch2_trans_put(trans);
}
static void bch2_rbio_error(struct bch_read_bio *rbio,
@@ -1241,11 +1280,11 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
return 0;
}
-int __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
- struct bvec_iter bvec_iter, subvol_inum inum,
- struct bch_io_failures *failed, unsigned flags)
+int __bch2_read(struct btree_trans *trans, struct bch_read_bio *rbio,
+ struct bvec_iter bvec_iter, subvol_inum inum,
+ struct bch_io_failures *failed, unsigned flags)
{
- struct btree_trans *trans = bch2_trans_get(c);
+ struct bch_fs *c = trans->c;
struct btree_iter iter;
struct bkey_buf sk;
struct bkey_s_c k;
@@ -1278,6 +1317,23 @@ int __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
if (ret)
goto err;
+ if (unlikely(flags & BCH_READ_in_retry)) {
+ struct data_update *u = flags & BCH_READ_data_update
+ ? container_of(rbio, struct data_update, rbio)
+ : NULL;
+
+ if (u &&
+ !bkey_and_val_eq(k, bkey_i_to_s_c(u->k.k))) {
+ /* extent we wanted to read no longer exists: */
+ ret = -BCH_ERR_data_read_key_overwritten;
+ goto err;
+ }
+
+ if (!bkey_deleted(&sk.k->k) &&
+ !bkey_and_val_eq(k, bkey_i_to_s_c(sk.k)))
+ failed->nr = 0;
+ }
+
s64 offset_into_extent = iter.pos.offset -
bkey_start_offset(k.k);
unsigned sectors = k.k->size - offset_into_extent;
@@ -1342,9 +1398,7 @@ int __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
bch2_rbio_done(rbio);
}
- bch2_trans_put(trans);
bch2_bkey_buf_exit(&sk, c);
-
return ret;
}
diff --git a/fs/bcachefs/io_read.h b/fs/bcachefs/io_read.h
index 42a22985d789..edcf50a4418c 100644
--- a/fs/bcachefs/io_read.h
+++ b/fs/bcachefs/io_read.h
@@ -3,6 +3,7 @@
#define _BCACHEFS_IO_READ_H
#include "bkey_buf.h"
+#include "btree_iter.h"
#include "reflink.h"
struct bch_read_bio {
@@ -140,7 +141,7 @@ static inline void bch2_read_extent(struct btree_trans *trans,
data_btree, k, offset_into_extent, NULL, flags, -1);
}
-int __bch2_read(struct bch_fs *, struct bch_read_bio *, struct bvec_iter,
+int __bch2_read(struct btree_trans *, struct bch_read_bio *, struct bvec_iter,
subvol_inum, struct bch_io_failures *, unsigned flags);
static inline void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
@@ -150,10 +151,11 @@ static inline void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
rbio->subvol = inum.subvol;
- __bch2_read(c, rbio, rbio->bio.bi_iter, inum, NULL,
- BCH_READ_retry_if_stale|
- BCH_READ_may_promote|
- BCH_READ_user_mapped);
+ bch2_trans_run(c,
+ __bch2_read(trans, rbio, rbio->bio.bi_iter, inum, NULL,
+ BCH_READ_retry_if_stale|
+ BCH_READ_may_promote|
+ BCH_READ_user_mapped));
}
static inline struct bch_read_bio *rbio_init_fragment(struct bio *bio,
--
2.47.2
next prev parent reply other threads:[~2025-03-11 20:15 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-11 20:15 [PATCH 00/14] better handling of checksum errors/bitrot Kent Overstreet
2025-03-11 20:15 ` [PATCH 01/14] bcachefs: Convert read path to standard error codes Kent Overstreet
2025-03-11 20:15 ` [PATCH 02/14] bcachefs: Fix BCH_ERR_data_read_csum_err_maybe_userspace in retry path Kent Overstreet
2025-03-11 20:15 ` [PATCH 03/14] bcachefs: Read error message now indicates if it was for an internal move Kent Overstreet
2025-03-11 20:15 ` [PATCH 04/14] bcachefs: BCH_ERR_data_read_buffer_too_small Kent Overstreet
2025-03-11 20:15 ` [PATCH 05/14] bcachefs: Return errors to top level bch2_rbio_retry() Kent Overstreet
2025-03-11 20:15 ` [PATCH 06/14] bcachefs: Print message on successful read retry Kent Overstreet
2025-03-11 20:15 ` [PATCH 07/14] bcachefs: Don't create bch_io_failures unless it's needed Kent Overstreet
2025-03-11 20:15 ` [PATCH 08/14] bcachefs: Checksum errors get additional retries Kent Overstreet
2025-03-11 20:15 ` Kent Overstreet [this message]
2025-03-11 20:15 ` [PATCH 10/14] bcachefs: Poison extents that can't be read due to checksum errors Kent Overstreet
2025-03-11 20:15 ` [PATCH 11/14] bcachefs: Data move can read from poisoned extents Kent Overstreet
2025-03-11 20:15 ` [PATCH 12/14] bcachefs: Debug params for data corruption injection Kent Overstreet
2025-03-11 20:15 ` [PATCH 13/14] block: Allow REQ_FUA|REQ_READ Kent Overstreet
2025-03-15 16:47 ` Jens Axboe
2025-03-15 17:01 ` Kent Overstreet
2025-03-15 17:03 ` Jens Axboe
2025-03-15 17:27 ` Kent Overstreet
2025-03-15 17:43 ` Jens Axboe
2025-03-15 18:07 ` Kent Overstreet
2025-03-15 18:32 ` Jens Axboe
2025-03-15 18:41 ` Kent Overstreet
2025-03-17 6:00 ` Christoph Hellwig
2025-03-17 12:15 ` Kent Overstreet
2025-03-17 14:13 ` Keith Busch
2025-03-17 14:49 ` Kent Overstreet
2025-03-17 15:15 ` Keith Busch
2025-03-17 15:22 ` Kent Overstreet
2025-03-17 15:30 ` Martin K. Petersen
2025-03-17 15:43 ` Kent Overstreet
2025-03-17 17:57 ` Martin K. Petersen
2025-03-17 18:21 ` Kent Overstreet
2025-03-17 19:24 ` Keith Busch
2025-03-17 19:40 ` Kent Overstreet
2025-03-17 20:39 ` Keith Busch
2025-03-17 21:13 ` Bart Van Assche
2025-03-18 1:06 ` Kent Overstreet
2025-03-18 6:16 ` Christoph Hellwig
2025-03-18 17:49 ` Bart Van Assche
2025-03-18 18:00 ` Kent Overstreet
2025-03-18 18:10 ` Keith Busch
2025-03-18 18:13 ` Kent Overstreet
2025-03-20 5:40 ` Christoph Hellwig
2025-03-20 10:28 ` Kent Overstreet
2025-03-18 0:27 ` Kent Overstreet
2025-03-18 6:11 ` Christoph Hellwig
2025-03-18 21:33 ` Kent Overstreet
2025-03-17 17:32 ` Keith Busch
2025-03-18 6:19 ` Christoph Hellwig
2025-03-18 6:01 ` Christoph Hellwig
2025-03-11 20:15 ` [PATCH 14/14] bcachefs: Read retries are after checksum errors now REQ_FUA Kent Overstreet
2025-03-17 20:55 ` [PATCH 00/14] better handling of checksum errors/bitrot John Stoffel
2025-03-17 21:12 ` errors compiling bcachefs-tools v1.20.0 on debian 12 John Stoffel
2025-03-17 21:48 ` Malte Schröder
2025-03-17 23:10 ` John Stoffel
2025-03-18 21:04 ` John Stoffel
2025-03-18 21:32 ` Malte Schröder
2025-03-19 14:16 ` John Stoffel
2025-03-24 15:25 ` Krzysztof Hajdamowicz
2025-03-26 13:45 ` John Stoffel
2025-03-18 1:15 ` [PATCH 00/14] better handling of checksum errors/bitrot Kent Overstreet
2025-03-18 14:47 ` John Stoffel
2025-03-20 17:15 ` Kent Overstreet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250311201518.3573009-10-kent.overstreet@linux.dev \
--to=kent.overstreet@linux.dev \
--cc=linux-bcachefs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.