summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-07-16 12:57:27 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:09 -0400
commite719fc34f00004813f98c8c3f8f3f364b1d77afc (patch)
tree45814bc7e6b9e45beafff64d146fc7e048d7c202
parent47924527e643e6160c6726669b90cad8aeb6d977 (diff)
downloadlwn-e719fc34f00004813f98c8c3f8f3f364b1d77afc.tar.gz
lwn-e719fc34f00004813f98c8c3f8f3f364b1d77afc.zip
bcachefs: BSET_OFFSET()
Add a field to struct bset for the sector offset within the btree node where it was written. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/bcachefs_format.h3
-rw-r--r--fs/bcachefs/btree_io.c19
2 files changed, 16 insertions, 6 deletions
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h
index 659bcfe09fb4..156198850b67 100644
--- a/fs/bcachefs/bcachefs_format.h
+++ b/fs/bcachefs/bcachefs_format.h
@@ -1749,6 +1749,9 @@ LE32_BITMASK(BSET_BIG_ENDIAN, struct bset, flags, 4, 5);
LE32_BITMASK(BSET_SEPARATE_WHITEOUTS,
struct bset, flags, 5, 6);
+/* Sector offset within the btree node: */
+LE32_BITMASK(BSET_OFFSET, struct bset, flags, 16, 32);
+
struct btree_node {
struct bch_csum csum;
__le64 magic;
diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c
index b99e4198bdbe..e42ade7cbc4b 100644
--- a/fs/bcachefs/btree_io.c
+++ b/fs/bcachefs/btree_io.c
@@ -651,7 +651,8 @@ void bch2_btree_node_drop_keys_outside_node(struct btree *b)
static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
struct btree *b, struct bset *i,
- unsigned sectors, int write, bool have_retry)
+ unsigned offset, unsigned sectors,
+ int write, bool have_retry)
{
unsigned version = le16_to_cpu(i->version);
const char *err;
@@ -689,18 +690,23 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
BTREE_ERR_FATAL, c, ca, b, i,
"BSET_SEPARATE_WHITEOUTS no longer supported");
- if (btree_err_on(b->written + sectors > c->opts.btree_node_size,
+ if (btree_err_on(offset + sectors > c->opts.btree_node_size,
BTREE_ERR_FIXABLE, c, ca, b, i,
"bset past end of btree node")) {
i->u64s = 0;
return 0;
}
- btree_err_on(b->written && !i->u64s,
+ btree_err_on(offset && !i->u64s,
BTREE_ERR_FIXABLE, c, ca, b, i,
"empty bset");
- if (!b->written) {
+ btree_err_on(BSET_OFFSET(i) &&
+ BSET_OFFSET(i) != offset,
+ BTREE_ERR_WANT_RETRY, c, ca, b, i,
+ "bset at wrong sector offset");
+
+ if (!offset) {
struct btree_node *bn =
container_of(i, struct btree_node, keys);
/* These indicate that we read the wrong btree node: */
@@ -954,7 +960,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
b->version_ondisk = min(b->version_ondisk,
le16_to_cpu(i->version));
- ret = validate_bset(c, ca, b, i, sectors,
+ ret = validate_bset(c, ca, b, i, b->written, sectors,
READ, have_retry);
if (ret)
goto fsck_err;
@@ -1713,7 +1719,7 @@ static int validate_bset_for_write(struct bch_fs *c, struct btree *b,
return -1;
ret = validate_bset_keys(c, b, i, &whiteout_u64s, WRITE, false) ?:
- validate_bset(c, NULL, b, i, sectors, WRITE, false);
+ validate_bset(c, NULL, b, i, b->written, sectors, WRITE, false);
if (ret) {
bch2_inconsistent_error(c);
dump_stack();
@@ -1876,6 +1882,7 @@ do_write:
i->version = c->sb.version < bcachefs_metadata_version_new_versioning
? cpu_to_le16(BCH_BSET_VERSION_OLD)
: cpu_to_le16(c->sb.version);
+ SET_BSET_OFFSET(i, b->written);
SET_BSET_CSUM_TYPE(i, bch2_meta_checksum_type(c));
if (bch2_csum_type_is_encryption(BSET_CSUM_TYPE(i)))