bcachefs: Kill bkey_type_successor
authorKent Overstreet <kent.overstreet@gmail.com>
Tue, 7 Jan 2020 18:29:32 +0000 (13:29 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:37 +0000 (17:08 -0400)
Previously, BTREE_ID_INODES was special - inodes were indexed by the
inode field, which meant the offset field of struct bpos wasn't used,
which led to special cases in e.g. the btree iterator code.

Now, inodes in the inodes btree are indexed by the offset field.

Also: prevously min_key was special for extents btrees, min_key for
extents would equal max_key for the previous node. Now, min_key =
bkey_successor() of the previous node, same as non extent btrees.

This means we can completely get rid of
btree_type_sucessor/predecessor.

Also make some improvements to the metadata IO validate/compat code.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
17 files changed:
fs/bcachefs/bcachefs_format.h
fs/bcachefs/bkey_methods.c
fs/bcachefs/bkey_methods.h
fs/bcachefs/btree_cache.c
fs/bcachefs/btree_gc.c
fs/bcachefs/btree_io.c
fs/bcachefs/btree_io.h
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_iter.h
fs/bcachefs/btree_update_interior.c
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/extent_update.c
fs/bcachefs/extents.c
fs/bcachefs/extents.h
fs/bcachefs/fsck.c
fs/bcachefs/inode.c
fs/bcachefs/journal_io.c

index 6f74fda1f21d1b30bbb5fd4c51f1bc9397b2b649..f0f8964a98b12501510be62e93e165313e20144a 100644 (file)
@@ -1160,7 +1160,8 @@ enum bcachefs_metadata_version {
        bcachefs_metadata_version_min                   = 9,
        bcachefs_metadata_version_new_versioning        = 10,
        bcachefs_metadata_version_bkey_renumber         = 10,
-       bcachefs_metadata_version_max                   = 11,
+       bcachefs_metadata_version_inode_btree_change    = 11,
+       bcachefs_metadata_version_max                   = 12,
 };
 
 #define bcachefs_metadata_version_current      (bcachefs_metadata_version_max - 1)
index 0aa3d3b9a281c7fad15df4914b7f007861e3cad0..c97e1e9002cb6efa42e817d4da532644098ddcd7 100644 (file)
@@ -273,3 +273,59 @@ void bch2_bkey_renumber(enum btree_node_type btree_node_type,
                        break;
                }
 }
+
+void __bch2_bkey_compat(unsigned level, enum btree_id btree_id,
+                       unsigned version, unsigned big_endian,
+                       int write,
+                       struct bkey_format *f,
+                       struct bkey_packed *k)
+{
+       const struct bkey_ops *ops;
+       struct bkey uk;
+       struct bkey_s u;
+
+       if (big_endian != CPU_BIG_ENDIAN)
+               bch2_bkey_swab_key(f, k);
+
+       if (version < bcachefs_metadata_version_bkey_renumber)
+               bch2_bkey_renumber(__btree_node_type(level, btree_id), k, write);
+
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_id == BTREE_ID_INODES) {
+               if (!bkey_packed(k)) {
+                       struct bkey_i *u = packed_to_bkey(k);
+                       swap(u->k.p.inode, u->k.p.offset);
+               } else if (f->bits_per_field[BKEY_FIELD_INODE] &&
+                          f->bits_per_field[BKEY_FIELD_OFFSET]) {
+                       struct bkey_format tmp = *f, *in = f, *out = &tmp;
+
+                       swap(tmp.bits_per_field[BKEY_FIELD_INODE],
+                            tmp.bits_per_field[BKEY_FIELD_OFFSET]);
+                       swap(tmp.field_offset[BKEY_FIELD_INODE],
+                            tmp.field_offset[BKEY_FIELD_OFFSET]);
+
+                       if (!write)
+                               swap(in, out);
+
+                       uk = __bch2_bkey_unpack_key(in, k);
+                       swap(uk.p.inode, uk.p.offset);
+                       BUG_ON(!bch2_bkey_pack_key(k, &uk, out));
+               }
+       }
+
+       if (!bkey_packed(k)) {
+               u = bkey_i_to_s(packed_to_bkey(k));
+       } else {
+               uk = __bch2_bkey_unpack_key(f, k);
+               u.k = &uk;
+               u.v = bkeyp_val(f, k);
+       }
+
+       if (big_endian != CPU_BIG_ENDIAN)
+               bch2_bkey_swab_val(u);
+
+       ops = &bch2_bkey_ops[k->type];
+
+       if (ops->compat)
+               ops->compat(btree_id, version, big_endian, write, u);
+}
index d36468b752237eb8935a4dae7774cc6c54ac6bee..0bca725ae3b8c5d3d719cc878c07bb1812cc6802 100644 (file)
@@ -33,6 +33,9 @@ struct bkey_ops {
        bool            (*key_normalize)(struct bch_fs *, struct bkey_s);
        enum merge_result (*key_merge)(struct bch_fs *,
                                       struct bkey_s, struct bkey_s);
+       void            (*compat)(enum btree_id id, unsigned version,
+                                 unsigned big_endian, int write,
+                                 struct bkey_s);
 };
 
 const char *bch2_bkey_val_invalid(struct bch_fs *, struct bkey_s_c);
@@ -60,4 +63,20 @@ enum merge_result bch2_bkey_merge(struct bch_fs *,
 
 void bch2_bkey_renumber(enum btree_node_type, struct bkey_packed *, int);
 
+void __bch2_bkey_compat(unsigned, enum btree_id, unsigned, unsigned,
+                       int, struct bkey_format *, struct bkey_packed *);
+
+static inline void bch2_bkey_compat(unsigned level, enum btree_id btree_id,
+                              unsigned version, unsigned big_endian,
+                              int write,
+                              struct bkey_format *f,
+                              struct bkey_packed *k)
+{
+       if (version < bcachefs_metadata_version_current ||
+           big_endian != CPU_BIG_ENDIAN)
+               __bch2_bkey_compat(level, btree_id, version,
+                                  big_endian, write, f, k);
+
+}
+
 #endif /* _BCACHEFS_BKEY_METHODS_H */
index 0711bde8d68c0f05e2685f2d2cc0d0a2f313bb41..4ff57925fb2ccc581c45d43ad3ee41e7c78b30f7 100644 (file)
@@ -924,8 +924,7 @@ out:
                if (sib != btree_prev_sib)
                        swap(n1, n2);
 
-               BUG_ON(bkey_cmp(btree_type_successor(n1->c.btree_id,
-                                                    n1->key.k.p),
+               BUG_ON(bkey_cmp(bkey_successor(n1->key.k.p),
                                n2->data->min_key));
        }
 
index ee5eafdb1222c87e866914232a28ab27a553b6b0..8a832e92b6a2cef7c314207cad5e5ba0ea0b33c5 100644 (file)
@@ -74,7 +74,7 @@ static void btree_node_range_checks(struct bch_fs *c, struct btree *b,
        struct range_level *l = &r->l[b->c.level];
 
        struct bpos expected_min = bkey_cmp(l->min, l->max)
-               ? btree_type_successor(b->c.btree_id, l->max)
+               ? bkey_successor(l->max)
                : l->max;
 
        bch2_fs_inconsistent_on(bkey_cmp(b->data->min_key, expected_min), c,
@@ -105,8 +105,7 @@ static void btree_node_range_checks(struct bch_fs *c, struct btree *b,
 
                if (bkey_cmp(b->data->max_key, POS_MAX))
                        l->min = l->max =
-                               btree_type_successor(b->c.btree_id,
-                                                    b->data->max_key);
+                               bkey_successor(b->data->max_key);
        }
 }
 
@@ -987,9 +986,7 @@ static void bch2_coalesce_nodes(struct bch_fs *c, struct btree_iter *iter,
                        n1->key.k.p = n1->data->max_key =
                                bkey_unpack_pos(n1, last);
 
-                       n2->data->min_key =
-                               btree_type_successor(iter->btree_id,
-                                                    n1->data->max_key);
+                       n2->data->min_key = bkey_successor(n1->data->max_key);
 
                        memcpy_u64s(vstruct_last(s1),
                                    s2->start, u64s);
index 85a17225a68e9ea5a0b95f0c085a45c01d88aaa8..04537eb06e4aa459462f08ca04451c994a282fa1 100644 (file)
@@ -709,83 +709,107 @@ out:                                                                     \
 
 static int validate_bset(struct bch_fs *c, struct btree *b,
                         struct bset *i, unsigned sectors,
-                        unsigned *whiteout_u64s, int write,
-                        bool have_retry)
+                        int write, bool have_retry)
 {
-       struct bkey_packed *k, *prev = NULL;
-       bool seen_non_whiteout = false;
-       unsigned version;
+       unsigned version = le16_to_cpu(i->version);
        const char *err;
        int ret = 0;
 
+       btree_err_on((version != BCH_BSET_VERSION_OLD &&
+                     version < bcachefs_metadata_version_min) ||
+                    version >= bcachefs_metadata_version_max,
+                    BTREE_ERR_FATAL, c, b, i,
+                    "unsupported bset version");
+
+       if (btree_err_on(b->written + sectors > c->opts.btree_node_size,
+                        BTREE_ERR_FIXABLE, c, b, i,
+                        "bset past end of btree node")) {
+               i->u64s = 0;
+               return 0;
+       }
+
+       btree_err_on(b->written && !i->u64s,
+                    BTREE_ERR_FIXABLE, c, b, i,
+                    "empty bset");
+
        if (!b->written) {
+               struct btree_node *bn =
+                       container_of(i, struct btree_node, keys);
                /* These indicate that we read the wrong btree node: */
-               btree_err_on(BTREE_NODE_ID(b->data) != b->c.btree_id,
+               btree_err_on(BTREE_NODE_ID(bn) != b->c.btree_id,
                             BTREE_ERR_MUST_RETRY, c, b, i,
                             "incorrect btree id");
 
-               btree_err_on(BTREE_NODE_LEVEL(b->data) != b->c.level,
+               btree_err_on(BTREE_NODE_LEVEL(bn) != b->c.level,
                             BTREE_ERR_MUST_RETRY, c, b, i,
                             "incorrect level");
 
                if (BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN) {
-                       u64 *p = (u64 *) &b->data->ptr;
+                       u64 *p = (u64 *) &bn->ptr;
 
                        *p = swab64(*p);
-                       bch2_bpos_swab(&b->data->min_key);
-                       bch2_bpos_swab(&b->data->max_key);
                }
 
+               if (!write)
+                       compat_btree_node(b->c.level, b->c.btree_id, version,
+                                         BSET_BIG_ENDIAN(i), write, bn);
+
                if (b->key.k.type == KEY_TYPE_btree_ptr_v2) {
                        struct bch_btree_ptr_v2 *bp =
                                &bkey_i_to_btree_ptr_v2(&b->key)->v;
 
                        btree_err_on(bkey_cmp(b->data->min_key, bp->min_key),
                                     BTREE_ERR_MUST_RETRY, c, b, NULL,
-                                    "incorrect min_key");
+                                    "incorrect min_key: got %llu:%llu should be %llu:%llu",
+                                    b->data->min_key.inode,
+                                    b->data->min_key.offset,
+                                    bp->min_key.inode,
+                                    bp->min_key.offset);
                }
 
-               btree_err_on(bkey_cmp(b->data->max_key, b->key.k.p),
+               btree_err_on(bkey_cmp(bn->max_key, b->key.k.p),
                             BTREE_ERR_MUST_RETRY, c, b, i,
                             "incorrect max key");
 
+               if (write)
+                       compat_btree_node(b->c.level, b->c.btree_id, version,
+                                         BSET_BIG_ENDIAN(i), write, bn);
+
                /* XXX: ideally we would be validating min_key too */
 #if 0
                /*
                 * not correct anymore, due to btree node write error
                 * handling
                 *
-                * need to add b->data->seq to btree keys and verify
+                * need to add bn->seq to btree keys and verify
                 * against that
                 */
                btree_err_on(!extent_contains_ptr(bkey_i_to_s_c_extent(&b->key),
-                                                 b->data->ptr),
+                                                 bn->ptr),
                             BTREE_ERR_FATAL, c, b, i,
                             "incorrect backpointer");
 #endif
-               err = bch2_bkey_format_validate(&b->data->format);
+               err = bch2_bkey_format_validate(&bn->format);
                btree_err_on(err,
                             BTREE_ERR_FATAL, c, b, i,
                             "invalid bkey format: %s", err);
-       }
-
-       version = le16_to_cpu(i->version);
-       btree_err_on((version != BCH_BSET_VERSION_OLD &&
-                     version < bcachefs_metadata_version_min) ||
-                    version >= bcachefs_metadata_version_max,
-                    BTREE_ERR_FATAL, c, b, i,
-                    "unsupported bset version");
 
-       if (btree_err_on(b->written + sectors > c->opts.btree_node_size,
-                        BTREE_ERR_FIXABLE, c, b, i,
-                        "bset past end of btree node")) {
-               i->u64s = 0;
-               return 0;
+               compat_bformat(b->c.level, b->c.btree_id, version,
+                              BSET_BIG_ENDIAN(i), write,
+                              &bn->format);
        }
+fsck_err:
+       return ret;
+}
 
-       btree_err_on(b->written && !i->u64s,
-                    BTREE_ERR_FIXABLE, c, b, i,
-                    "empty bset");
+static int validate_bset_keys(struct bch_fs *c, struct btree *b,
+                        struct bset *i, unsigned *whiteout_u64s,
+                        int write, bool have_retry)
+{
+       unsigned version = le16_to_cpu(i->version);
+       struct bkey_packed *k, *prev = NULL;
+       bool seen_non_whiteout = false;
+       int ret = 0;
 
        if (!BSET_SEPARATE_WHITEOUTS(i)) {
                seen_non_whiteout = true;
@@ -814,18 +838,14 @@ static int validate_bset(struct bch_fs *c, struct btree *b,
                        continue;
                }
 
-               if (BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN)
-                       bch2_bkey_swab_key(&b->format, k);
-
-               if (!write &&
-                   version < bcachefs_metadata_version_bkey_renumber)
-                       bch2_bkey_renumber(btree_node_type(b), k, write);
+               /* XXX: validate k->u64s */
+               if (!write)
+                       bch2_bkey_compat(b->c.level, b->c.btree_id, version,
+                                   BSET_BIG_ENDIAN(i), write,
+                                   &b->format, k);
 
                u = __bkey_disassemble(b, k, &tmp);
 
-               if (BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN)
-                       bch2_bkey_swab_val(u);
-
                invalid = __bch2_bkey_invalid(c, u.s_c, btree_node_type(b)) ?:
                        bch2_bkey_in_btree_node(b, u.s_c) ?:
                        (write ? bch2_bkey_val_invalid(c, u.s_c) : NULL);
@@ -842,9 +862,10 @@ static int validate_bset(struct bch_fs *c, struct btree *b,
                        continue;
                }
 
-               if (write &&
-                   version < bcachefs_metadata_version_bkey_renumber)
-                       bch2_bkey_renumber(btree_node_type(b), k, write);
+               if (write)
+                       bch2_bkey_compat(b->c.level, b->c.btree_id, version,
+                                   BSET_BIG_ENDIAN(i), write,
+                                   &b->format, k);
 
                /*
                 * with the separate whiteouts thing (used for extents), the
@@ -875,8 +896,6 @@ static int validate_bset(struct bch_fs *c, struct btree *b,
                prev = k;
                k = bkey_next_skip_noops(k, vstruct_last(i));
        }
-
-       SET_BSET_BIG_ENDIAN(i, CPU_BIG_ENDIAN);
 fsck_err:
        return ret;
 }
@@ -944,8 +963,6 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct btree *b, bool have_retry
                                set_btree_node_old_extent_overwrite(b);
 
                        sectors = vstruct_sectors(b->data, c->block_bits);
-
-                       btree_node_set_format(b, b->data->format);
                } else {
                        bne = write_block(b);
                        i = &bne->keys;
@@ -969,11 +986,21 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct btree *b, bool have_retry
                        sectors = vstruct_sectors(bne, c->block_bits);
                }
 
-               ret = validate_bset(c, b, i, sectors, &whiteout_u64s,
+               ret = validate_bset(c, b, i, sectors,
                                    READ, have_retry);
                if (ret)
                        goto fsck_err;
 
+               if (!b->written)
+                       btree_node_set_format(b, b->data->format);
+
+               ret = validate_bset_keys(c, b, i, &whiteout_u64s,
+                                   READ, have_retry);
+               if (ret)
+                       goto fsck_err;
+
+               SET_BSET_BIG_ENDIAN(i, CPU_BIG_ENDIAN);
+
                b->written += sectors;
 
                blacklisted = bch2_journal_seq_is_blacklisted(c,
@@ -1416,7 +1443,8 @@ static int validate_bset_for_write(struct bch_fs *c, struct btree *b,
        if (bch2_bkey_invalid(c, bkey_i_to_s_c(&b->key), BKEY_TYPE_BTREE))
                return -1;
 
-       ret = validate_bset(c, b, i, sectors, &whiteout_u64s, WRITE, false);
+       ret = validate_bset(c, b, i, sectors, WRITE, false) ?:
+               validate_bset_keys(c, b, i, &whiteout_u64s, WRITE, false);
        if (ret)
                bch2_inconsistent_error(c);
 
@@ -1566,8 +1594,7 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b,
                validate_before_checksum = true;
 
        /* validate_bset will be modifying: */
-       if (le16_to_cpu(i->version) <
-           bcachefs_metadata_version_bkey_renumber)
+       if (le16_to_cpu(i->version) < bcachefs_metadata_version_max)
                validate_before_checksum = true;
 
        /* if we're going to be encrypting, check metadata validity first: */
index a02e261c2eb21ba6fe668de5e230b001ffcc76cb..fa996fdc547423952b747b83762e5b766ea5d25e 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef _BCACHEFS_BTREE_IO_H
 #define _BCACHEFS_BTREE_IO_H
 
+#include "bkey_methods.h"
 #include "bset.h"
 #include "btree_locking.h"
 #include "extents.h"
@@ -140,4 +141,50 @@ void bch2_btree_flush_all_writes(struct bch_fs *);
 void bch2_btree_verify_flushed(struct bch_fs *);
 ssize_t bch2_dirty_btree_nodes_print(struct bch_fs *, char *);
 
+static inline void compat_bformat(unsigned level, enum btree_id btree_id,
+                                unsigned version, unsigned big_endian,
+                                int write, struct bkey_format *f)
+{
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_id == BTREE_ID_INODES) {
+               swap(f->bits_per_field[BKEY_FIELD_INODE],
+                    f->bits_per_field[BKEY_FIELD_OFFSET]);
+               swap(f->field_offset[BKEY_FIELD_INODE],
+                    f->field_offset[BKEY_FIELD_OFFSET]);
+       }
+}
+
+static inline void compat_bpos(unsigned level, enum btree_id btree_id,
+                              unsigned version, unsigned big_endian,
+                              int write, struct bpos *p)
+{
+       if (big_endian != CPU_BIG_ENDIAN)
+               bch2_bpos_swab(p);
+
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_id == BTREE_ID_INODES)
+               swap(p->inode, p->offset);
+}
+
+static inline void compat_btree_node(unsigned level, enum btree_id btree_id,
+                                    unsigned version, unsigned big_endian,
+                                    int write,
+                                    struct btree_node *bn)
+{
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_node_type_is_extents(btree_id) &&
+           bkey_cmp(bn->min_key, POS_MIN) &&
+           write)
+               bn->min_key = bkey_predecessor(bn->min_key);
+
+       compat_bpos(level, btree_id, version, big_endian, write, &bn->min_key);
+       compat_bpos(level, btree_id, version, big_endian, write, &bn->max_key);
+
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_node_type_is_extents(btree_id) &&
+           bkey_cmp(bn->min_key, POS_MIN) &&
+           !write)
+               bn->min_key = bkey_successor(bn->min_key);
+}
+
 #endif /* _BCACHEFS_BTREE_IO_H */
index 8b1395ef4d0e453724c3996041479ccc57fa0e13..4ce6a66edcd51da4cfe0779c009ddbf2509dcb47 100644 (file)
@@ -39,7 +39,7 @@ static inline struct bpos btree_iter_search_key(struct btree_iter *iter)
 static inline bool btree_iter_pos_before_node(struct btree_iter *iter,
                                              struct btree *b)
 {
-       return bkey_cmp(iter->pos, b->data->min_key) < 0;
+       return bkey_cmp(btree_iter_search_key(iter), b->data->min_key) < 0;
 }
 
 static inline bool btree_iter_pos_after_node(struct btree_iter *iter,
@@ -1284,10 +1284,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter)
                if (btree_node_read_locked(iter, iter->level))
                        btree_node_unlock(iter, iter->level);
 
-               /* ick: */
-               iter->pos       = iter->btree_id == BTREE_ID_INODES
-                       ? btree_type_successor(iter->btree_id, iter->pos)
-                       : bkey_successor(iter->pos);
+               iter->pos       = bkey_successor(iter->pos);
                iter->level     = iter->min_depth;
 
                btree_iter_set_dirty(iter, BTREE_ITER_NEED_TRAVERSE);
@@ -1395,8 +1392,8 @@ static inline bool btree_iter_set_pos_to_next_leaf(struct btree_iter *iter)
        iter->k.p = iter->pos = l->b->key.k.p;
 
        ret = bkey_cmp(iter->pos, POS_MAX) != 0;
-       if (ret)
-               iter->k.p = iter->pos = btree_type_successor(iter->btree_id, iter->pos);
+       if (ret && !(iter->flags & BTREE_ITER_IS_EXTENTS))
+               iter->k.p = iter->pos = bkey_successor(iter->pos);
 
        btree_iter_pos_changed(iter, 1);
        return ret;
@@ -1412,8 +1409,12 @@ static inline bool btree_iter_set_pos_to_prev_leaf(struct btree_iter *iter)
        iter->uptodate  = BTREE_ITER_NEED_TRAVERSE;
 
        ret = bkey_cmp(iter->pos, POS_MIN) != 0;
-       if (ret)
-               iter->k.p = iter->pos = btree_type_predecessor(iter->btree_id, iter->pos);
+       if (ret) {
+               iter->k.p = iter->pos = bkey_predecessor(iter->pos);
+
+               if (iter->flags & BTREE_ITER_IS_EXTENTS)
+                       iter->k.p = iter->pos = bkey_predecessor(iter->pos);
+       }
 
        btree_iter_pos_changed(iter, -1);
        return ret;
@@ -1500,7 +1501,9 @@ struct bkey_s_c bch2_btree_iter_next(struct btree_iter *iter)
                return bkey_s_c_null;
 
        bch2_btree_iter_set_pos(iter,
-               btree_type_successor(iter->btree_id, iter->k.p));
+               (iter->flags & BTREE_ITER_IS_EXTENTS)
+               ? iter->k.p
+               : bkey_successor(iter->k.p));
 
        return bch2_btree_iter_peek(iter);
 }
@@ -1553,7 +1556,9 @@ struct bkey_s_c bch2_btree_iter_peek_with_updates(struct btree_iter *iter)
 
                if (k.k && bkey_deleted(k.k)) {
                        bch2_btree_iter_set_pos(iter,
-                               btree_type_successor(iter->btree_id, iter->k.p));
+                               (iter->flags & BTREE_ITER_IS_EXTENTS)
+                               ? iter->k.p
+                               : bkey_successor(iter->k.p));
                        continue;
                }
 
@@ -1582,7 +1587,9 @@ struct bkey_s_c bch2_btree_iter_next_with_updates(struct btree_iter *iter)
                return bkey_s_c_null;
 
        bch2_btree_iter_set_pos(iter,
-               btree_type_successor(iter->btree_id, iter->k.p));
+               (iter->flags & BTREE_ITER_IS_EXTENTS)
+               ? iter->k.p
+               : bkey_successor(iter->k.p));
 
        return bch2_btree_iter_peek_with_updates(iter);
 }
@@ -1749,7 +1756,9 @@ struct bkey_s_c bch2_btree_iter_next_slot(struct btree_iter *iter)
                return bkey_s_c_null;
 
        bch2_btree_iter_set_pos(iter,
-               btree_type_successor(iter->btree_id, iter->k.p));
+               (iter->flags & BTREE_ITER_IS_EXTENTS)
+               ? iter->k.p
+               : bkey_successor(iter->k.p));
 
        return bch2_btree_iter_peek_slot(iter);
 }
index 1177bf118dbcc062e3058c69b75c252cb5f18ccb..60baca62a596c350c2c47bd91049dbfabd863dd5 100644 (file)
@@ -172,32 +172,6 @@ void bch2_btree_iter_set_pos_same_leaf(struct btree_iter *, struct bpos);
 void __bch2_btree_iter_set_pos(struct btree_iter *, struct bpos, bool);
 void bch2_btree_iter_set_pos(struct btree_iter *, struct bpos);
 
-static inline struct bpos btree_type_successor(enum btree_id id,
-                                              struct bpos pos)
-{
-       if (id == BTREE_ID_INODES) {
-               pos.inode++;
-               pos.offset = 0;
-       } else if (!btree_node_type_is_extents(id)) {
-               pos = bkey_successor(pos);
-       }
-
-       return pos;
-}
-
-static inline struct bpos btree_type_predecessor(enum btree_id id,
-                                              struct bpos pos)
-{
-       if (id == BTREE_ID_INODES) {
-               --pos.inode;
-               pos.offset = 0;
-       } else {
-               pos = bkey_predecessor(pos);
-       }
-
-       return pos;
-}
-
 static inline int __btree_iter_cmp(enum btree_id id,
                                   struct bpos pos,
                                   const struct btree_iter *r)
index 3f9605f2f1f478538dcf32aaae854772ae9978e2..f09423c83c4a8573f8b1b35a6edba7b6f202fdf7 100644 (file)
@@ -1193,7 +1193,7 @@ static struct btree *__btree_split_node(struct btree_update *as,
        BUG_ON(!prev);
 
        btree_set_max(n1, bkey_unpack_pos(n1, prev));
-       btree_set_min(n2, btree_type_successor(n1->c.btree_id, n1->key.k.p));
+       btree_set_min(n2, bkey_successor(n1->key.k.p));
 
        set2->u64s = cpu_to_le16((u64 *) vstruct_end(set1) - (u64 *) k);
        set1->u64s = cpu_to_le16(le16_to_cpu(set1->u64s) - le16_to_cpu(set2->u64s));
index 06e735fc69ecdd64553ba73622d3b47011f19f33..1e6675f68b4ac5047ae7eba657372dc1f0905106 100644 (file)
@@ -58,8 +58,11 @@ bool bch2_btree_bset_insert_key(struct btree_iter *iter,
        EBUG_ON(btree_node_just_written(b));
        EBUG_ON(bset_written(b, btree_bset_last(b)));
        EBUG_ON(bkey_deleted(&insert->k) && bkey_val_u64s(&insert->k));
-       EBUG_ON(bkey_cmp(bkey_start_pos(&insert->k), b->data->min_key) < 0 ||
-               bkey_cmp(insert->k.p, b->data->max_key) > 0);
+       EBUG_ON(bkey_cmp(b->data->min_key, POS_MIN) &&
+               bkey_cmp(bkey_start_pos(&insert->k),
+                        bkey_predecessor(b->data->min_key)) < 0);
+       EBUG_ON(bkey_cmp(insert->k.p, b->data->min_key) < 0);
+       EBUG_ON(bkey_cmp(insert->k.p, b->data->max_key) > 0);
        EBUG_ON(insert->k.u64s >
                bch_btree_keys_u64s_remaining(iter->trans->c, b));
        EBUG_ON(iter->flags & BTREE_ITER_IS_EXTENTS);
index 8e5070d5a39b4d72ddba9fcb8fa932c46fa57aa9..2a7d913bdda3f053d6df6612f9a37ecc7408a404 100644 (file)
@@ -115,7 +115,9 @@ int bch2_extent_atomic_end(struct btree_iter *iter,
        b = iter->l[0].b;
        node_iter = iter->l[0].iter;
 
-       BUG_ON(bkey_cmp(bkey_start_pos(&insert->k), b->data->min_key) < 0);
+       BUG_ON(bkey_cmp(b->data->min_key, POS_MIN) &&
+              bkey_cmp(bkey_start_pos(&insert->k),
+                       bkey_predecessor(b->data->min_key)) < 0);
 
        *end = bpos_min(insert->k.p, b->key.k.p);
 
index 1ac4f0522043ea098527af26a070fdab25853520..3c28f3aa9df748bda9b561f66c7932eb3cbd9fc9 100644 (file)
@@ -9,6 +9,7 @@
 #include "bcachefs.h"
 #include "bkey_methods.h"
 #include "btree_gc.h"
+#include "btree_io.h"
 #include "btree_iter.h"
 #include "buckets.h"
 #include "checksum.h"
@@ -213,6 +214,22 @@ void bch2_btree_ptr_to_text(struct printbuf *out, struct bch_fs *c,
        bch2_bkey_ptrs_to_text(out, c, k);
 }
 
+void bch2_btree_ptr_v2_compat(enum btree_id btree_id, unsigned version,
+                             unsigned big_endian, int write,
+                             struct bkey_s k)
+{
+       struct bkey_s_btree_ptr_v2 bp = bkey_s_to_btree_ptr_v2(k);
+
+       compat_bpos(0, btree_id, version, big_endian, write, &bp.v->min_key);
+
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_node_type_is_extents(btree_id) &&
+           bkey_cmp(bp.v->min_key, POS_MIN))
+               bp.v->min_key = write
+                       ? bkey_predecessor(bp.v->min_key)
+                       : bkey_successor(bp.v->min_key);
+}
+
 /* KEY_TYPE_extent: */
 
 const char *bch2_extent_invalid(const struct bch_fs *c, struct bkey_s_c k)
index 70b7d70269dc14af02bd76c52100d42a4c9d6104..8ff2eac3ee2b1c1476c0f875e379634e8919f416 100644 (file)
@@ -371,6 +371,8 @@ const char *bch2_btree_ptr_invalid(const struct bch_fs *, struct bkey_s_c);
 void bch2_btree_ptr_debugcheck(struct bch_fs *, struct bkey_s_c);
 void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *,
                            struct bkey_s_c);
+void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned,
+                             int, struct bkey_s);
 
 #define bch2_bkey_ops_btree_ptr (struct bkey_ops) {            \
        .key_invalid    = bch2_btree_ptr_invalid,               \
@@ -384,6 +386,7 @@ void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *,
        .key_debugcheck = bch2_btree_ptr_debugcheck,            \
        .val_to_text    = bch2_btree_ptr_to_text,               \
        .swab           = bch2_ptr_swab,                        \
+       .compat         = bch2_btree_ptr_v2_compat,             \
 }
 
 /* KEY_TYPE_extent: */
index 822541e6adfc8b999adbb42c079442d50995c1bc..c7508e81188c84eece59ca597daa86849a674d1d 100644 (file)
@@ -1038,12 +1038,12 @@ retry:
                if (!ret)
                        continue;
 
-               if (fsck_err_on(!inode_bitmap_test(&dirs_done, k.k->p.inode), c,
+               if (fsck_err_on(!inode_bitmap_test(&dirs_done, k.k->p.offset), c,
                                "unreachable directory found (inum %llu)",
-                               k.k->p.inode)) {
+                               k.k->p.offset)) {
                        bch2_trans_unlock(&trans);
 
-                       ret = reattach_inode(c, lostfound_inode, k.k->p.inode);
+                       ret = reattach_inode(c, lostfound_inode, k.k->p.offset);
                        if (ret) {
                                goto err;
                        }
index c40ff6fc7ae29b7f388dc843e372612971ccbdd3..758eda5266743ae10a1d8c975470528cd17a5359 100644 (file)
@@ -98,7 +98,7 @@ void bch2_inode_pack(struct bkey_inode_buf *packed,
        unsigned bytes;
 
        bkey_inode_init(&packed->inode.k_i);
-       packed->inode.k.p.inode         = inode->bi_inum;
+       packed->inode.k.p.offset        = inode->bi_inum;
        packed->inode.v.bi_hash_seed    = inode->bi_hash_seed;
        packed->inode.v.bi_flags        = cpu_to_le32(inode->bi_flags);
        packed->inode.v.bi_mode         = cpu_to_le16(inode->bi_mode);
@@ -149,7 +149,7 @@ int bch2_inode_unpack(struct bkey_s_c_inode inode,
        unsigned fieldnr = 0, field_bits;
        int ret;
 
-       unpacked->bi_inum       = inode.k->p.inode;
+       unpacked->bi_inum       = inode.k->p.offset;
        unpacked->bi_hash_seed  = inode.v->bi_hash_seed;
        unpacked->bi_flags      = le32_to_cpu(inode.v->bi_flags);
        unpacked->bi_mode       = le16_to_cpu(inode.v->bi_mode);
@@ -188,7 +188,7 @@ struct btree_iter *bch2_inode_peek(struct btree_trans *trans,
        struct bkey_s_c k;
        int ret;
 
-       iter = bch2_trans_get_iter(trans, BTREE_ID_INODES, POS(inum, 0),
+       iter = bch2_trans_get_iter(trans, BTREE_ID_INODES, POS(0, inum),
                                   BTREE_ITER_SLOTS|flags);
        if (IS_ERR(iter))
                return iter;
@@ -232,13 +232,13 @@ const char *bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k)
                struct bkey_s_c_inode inode = bkey_s_c_to_inode(k);
                struct bch_inode_unpacked unpacked;
 
-       if (k.k->p.offset)
-               return "nonzero offset";
+       if (k.k->p.inode)
+               return "nonzero k.p.inode";
 
        if (bkey_val_bytes(k.k) < sizeof(struct bch_inode))
                return "incorrect value size";
 
-       if (k.k->p.inode < BLOCKDEV_INODE_MAX)
+       if (k.k->p.offset < BLOCKDEV_INODE_MAX)
                return "fs inode in blockdev range";
 
        if (INODE_STR_HASH(inode.v) >= BCH_STR_HASH_NR)
@@ -280,8 +280,8 @@ void bch2_inode_to_text(struct printbuf *out, struct bch_fs *c,
 const char *bch2_inode_generation_invalid(const struct bch_fs *c,
                                          struct bkey_s_c k)
 {
-       if (k.k->p.offset)
-               return "nonzero offset";
+       if (k.k->p.inode)
+               return "nonzero k.p.inode";
 
        if (bkey_val_bytes(k.k) != sizeof(struct bch_inode_generation))
                return "incorrect value size";
@@ -383,9 +383,9 @@ int bch2_inode_create(struct btree_trans *trans,
        if (IS_ERR(inode_p))
                return PTR_ERR(inode_p);
 again:
-       for_each_btree_key(trans, iter, BTREE_ID_INODES, POS(start, 0),
+       for_each_btree_key(trans, iter, BTREE_ID_INODES, POS(0, start),
                           BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
-               if (iter->pos.inode > max)
+               if (bkey_cmp(iter->pos, POS(0, max)) > 0)
                        break;
 
                if (k.k->type != KEY_TYPE_inode)
@@ -405,8 +405,8 @@ again:
 
        return -ENOSPC;
 found_slot:
-       *hint                   = k.k->p.inode;
-       inode_u->bi_inum        = k.k->p.inode;
+       *hint                   = k.k->p.offset;
+       inode_u->bi_inum        = k.k->p.offset;
        inode_u->bi_generation  = bkey_generation(k);
 
        bch2_inode_pack(inode_p, inode_u);
@@ -443,7 +443,7 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
 
        bch2_trans_init(&trans, c, 0, 0);
 
-       iter = bch2_trans_get_iter(&trans, BTREE_ID_INODES, POS(inode_nr, 0),
+       iter = bch2_trans_get_iter(&trans, BTREE_ID_INODES, POS(0, inode_nr),
                                   BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
        do {
                struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
@@ -475,10 +475,10 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
 
                if (!bi_generation) {
                        bkey_init(&delete.k);
-                       delete.k.p.inode = inode_nr;
+                       delete.k.p.offset = inode_nr;
                } else {
                        bkey_inode_generation_init(&delete.k_i);
-                       delete.k.p.inode = inode_nr;
+                       delete.k.p.offset = inode_nr;
                        delete.v.bi_generation = cpu_to_le32(bi_generation);
                }
 
@@ -500,7 +500,7 @@ int bch2_inode_find_by_inum_trans(struct btree_trans *trans, u64 inode_nr,
        int ret;
 
        iter = bch2_trans_get_iter(trans, BTREE_ID_INODES,
-                       POS(inode_nr, 0), BTREE_ITER_SLOTS);
+                       POS(0, inode_nr), BTREE_ITER_SLOTS);
        if (IS_ERR(iter))
                return PTR_ERR(iter);
 
index fc36385c7830ab3f7ad5f00753a52b234e70d183..421fde39ac0ef31990860d8e95996ec145a9aa4c 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "bcachefs.h"
 #include "alloc_foreground.h"
+#include "btree_io.h"
 #include "buckets.h"
 #include "checksum.h"
 #include "error.h"
@@ -137,7 +138,8 @@ static void journal_entry_null_range(void *start, void *end)
 
 static int journal_validate_key(struct bch_fs *c, struct jset *jset,
                                struct jset_entry *entry,
-                               struct bkey_i *k, enum btree_node_type key_type,
+                               unsigned level, enum btree_id btree_id,
+                               struct bkey_i *k,
                                const char *type, int write)
 {
        void *next = vstruct_next(entry);
@@ -170,16 +172,13 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset,
                return 0;
        }
 
-       if (JSET_BIG_ENDIAN(jset) != CPU_BIG_ENDIAN) {
-               bch2_bkey_swab_key(NULL, bkey_to_packed(k));
-               bch2_bkey_swab_val(bkey_i_to_s(k));
-       }
-
-       if (!write &&
-           version < bcachefs_metadata_version_bkey_renumber)
-               bch2_bkey_renumber(key_type, bkey_to_packed(k), write);
+       if (!write)
+               bch2_bkey_compat(level, btree_id, version,
+                           JSET_BIG_ENDIAN(jset), write,
+                           NULL, bkey_to_packed(k));
 
-       invalid = bch2_bkey_invalid(c, bkey_i_to_s_c(k), key_type);
+       invalid = bch2_bkey_invalid(c, bkey_i_to_s_c(k),
+                                   __btree_node_type(level, btree_id));
        if (invalid) {
                char buf[160];
 
@@ -193,9 +192,10 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset,
                return 0;
        }
 
-       if (write &&
-           version < bcachefs_metadata_version_bkey_renumber)
-               bch2_bkey_renumber(key_type, bkey_to_packed(k), write);
+       if (write)
+               bch2_bkey_compat(level, btree_id, version,
+                           JSET_BIG_ENDIAN(jset), write,
+                           NULL, bkey_to_packed(k));
 fsck_err:
        return ret;
 }
@@ -208,10 +208,10 @@ static int journal_entry_validate_btree_keys(struct bch_fs *c,
        struct bkey_i *k;
 
        vstruct_for_each(entry, k) {
-               int ret = journal_validate_key(c, jset, entry, k,
-                               __btree_node_type(entry->level,
-                                                 entry->btree_id),
-                               "key", write);
+               int ret = journal_validate_key(c, jset, entry,
+                                              entry->level,
+                                              entry->btree_id,
+                                              k, "key", write);
                if (ret)
                        return ret;
        }
@@ -241,7 +241,7 @@ static int journal_entry_validate_btree_root(struct bch_fs *c,
                return 0;
        }
 
-       return journal_validate_key(c, jset, entry, k, BKEY_TYPE_BTREE,
+       return journal_validate_key(c, jset, entry, 1, entry->btree_id, k,
                                    "btree root", write);
 fsck_err:
        return ret;
@@ -1017,8 +1017,7 @@ void bch2_journal_write(struct closure *cl)
        if (bch2_csum_type_is_encryption(JSET_CSUM_TYPE(jset)))
                validate_before_checksum = true;
 
-       if (le32_to_cpu(jset->version) <
-           bcachefs_metadata_version_bkey_renumber)
+       if (le32_to_cpu(jset->version) < bcachefs_metadata_version_max)
                validate_before_checksum = true;
 
        if (validate_before_checksum &&