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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox