bcachefs: BSET_OFFSET()
authorKent Overstreet <kent.overstreet@gmail.com>
Fri, 16 Jul 2021 16:57:27 +0000 (12:57 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:09 +0000 (17:09 -0400)
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>
fs/bcachefs/bcachefs_format.h
fs/bcachefs/btree_io.c

index 659bcfe09fb4b16d49459eb8a8db9d37f0fe557e..156198850b670b71e94d9e5d6c1c746cde5b562b 100644 (file)
@@ -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;
index b99e4198bdbeaea0e98df17f105cc2c71d71cbfc..e42ade7cbc4b7faf6d1aa3460790edddc0331fb6 100644 (file)
@@ -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)))