bcachefs: BCH_COMPAT_bformat_overflow_done no longer required
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 6 Aug 2023 14:04:37 +0000 (10:04 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:10:09 +0000 (17:10 -0400)
Awhile back, we changed bkey_format generation to ensure that the packed
representation could never represent fields larger than the unpacked
representation.

This was to ensure that bkey_packed_successor() always gave a sensible
result, but in the current code bkey_packed_successor() is only used in
a debug assertion - not for anything important.

This kills the requirement that we've gotten rid of those weird bkey
formats, and instead changes the assertion to check if we're dealing
with an old weird bkey format.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bkey.c
fs/bcachefs/bkey.h
fs/bcachefs/bkey_methods.h
fs/bcachefs/btree_io.c
fs/bcachefs/recovery.c
fs/bcachefs/super.c

index 67f205992629e19233afac48d2e973df9ac89fe1..d6960e259c804897137220f3f26ad734a087b35f 100644 (file)
@@ -424,6 +424,24 @@ static bool bkey_packed_successor(struct bkey_packed *out,
 
        return false;
 }
+
+static bool bkey_format_has_too_big_fields(const struct bkey_format *f)
+{
+       for (unsigned i = 0; i < f->nr_fields; i++) {
+               unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
+               u64 unpacked_max = ~((~0ULL << 1) << (unpacked_bits - 1));
+               u64 packed_max = f->bits_per_field[i]
+                       ? ~((~0ULL << 1) << (f->bits_per_field[i] - 1))
+                       : 0;
+               u64 field_offset = le64_to_cpu(f->field_offset[i]);
+
+               if (packed_max + field_offset < packed_max ||
+                   packed_max + field_offset > unpacked_max)
+                       return true;
+       }
+
+       return false;
+}
 #endif
 
 /*
@@ -504,7 +522,8 @@ enum bkey_pack_pos_ret bch2_bkey_pack_pos_lossy(struct bkey_packed *out,
 
                BUG_ON(bkey_cmp_left_packed(b, out, &orig) >= 0);
                BUG_ON(bkey_packed_successor(&successor, b, *out) &&
-                      bkey_cmp_left_packed(b, &successor, &orig) < 0);
+                      bkey_cmp_left_packed(b, &successor, &orig) < 0 &&
+                      !bkey_format_has_too_big_fields(f));
        }
 #endif
 
@@ -597,14 +616,17 @@ struct bkey_format bch2_bkey_format_done(struct bkey_format_state *s)
        {
                struct printbuf buf = PRINTBUF;
 
-               BUG_ON(bch2_bkey_format_validate(&ret, &buf));
+               BUG_ON(bch2_bkey_format_invalid(NULL, &ret, 0, &buf));
                printbuf_exit(&buf);
        }
 #endif
        return ret;
 }
 
-int bch2_bkey_format_validate(struct bkey_format *f, struct printbuf *err)
+int bch2_bkey_format_invalid(struct bch_fs *c,
+                            struct bkey_format *f,
+                            enum bkey_invalid_flags flags,
+                            struct printbuf *err)
 {
        unsigned i, bits = KEY_PACKED_BITS_START;
 
@@ -619,18 +641,20 @@ int bch2_bkey_format_validate(struct bkey_format *f, struct printbuf *err)
         * unpacked format:
         */
        for (i = 0; i < f->nr_fields; i++) {
-               unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
-               u64 unpacked_max = ~((~0ULL << 1) << (unpacked_bits - 1));
-               u64 packed_max = f->bits_per_field[i]
-                       ? ~((~0ULL << 1) << (f->bits_per_field[i] - 1))
-                       : 0;
-               u64 field_offset = le64_to_cpu(f->field_offset[i]);
-
-               if (packed_max + field_offset < packed_max ||
-                   packed_max + field_offset > unpacked_max) {
-                       prt_printf(err, "field %u too large: %llu + %llu > %llu",
-                                  i, packed_max, field_offset, unpacked_max);
-                       return -BCH_ERR_invalid;
+               if (!c || c->sb.version_min >= bcachefs_metadata_version_snapshot) {
+                       unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
+                       u64 unpacked_max = ~((~0ULL << 1) << (unpacked_bits - 1));
+                       u64 packed_max = f->bits_per_field[i]
+                               ? ~((~0ULL << 1) << (f->bits_per_field[i] - 1))
+                               : 0;
+                       u64 field_offset = le64_to_cpu(f->field_offset[i]);
+
+                       if (packed_max + field_offset < packed_max ||
+                           packed_max + field_offset > unpacked_max) {
+                               prt_printf(err, "field %u too large: %llu + %llu > %llu",
+                                          i, packed_max, field_offset, unpacked_max);
+                               return -BCH_ERR_invalid;
+                       }
                }
 
                bits += f->bits_per_field[i];
index 644caa2b2b25a0d4e46154e19cf4be202b9bfc8b..51969a46265e124233028dfbf6b3e39137cb383a 100644 (file)
@@ -9,6 +9,12 @@
 #include "util.h"
 #include "vstructs.h"
 
+enum bkey_invalid_flags {
+       BKEY_INVALID_WRITE              = (1U << 0),
+       BKEY_INVALID_COMMIT             = (1U << 1),
+       BKEY_INVALID_JOURNAL            = (1U << 2),
+};
+
 #if 0
 
 /*
@@ -769,7 +775,8 @@ static inline void bch2_bkey_format_add_key(struct bkey_format_state *s, const s
 
 void bch2_bkey_format_add_pos(struct bkey_format_state *, struct bpos);
 struct bkey_format bch2_bkey_format_done(struct bkey_format_state *);
-int bch2_bkey_format_validate(struct bkey_format *, struct printbuf *);
+int bch2_bkey_format_invalid(struct bch_fs *, struct bkey_format *,
+                            enum bkey_invalid_flags, struct printbuf *);
 void bch2_bkey_format_to_text(struct printbuf *, const struct bkey_format *);
 
 #endif /* _BCACHEFS_BKEY_H */
index d7b63769068c7464e709d1724d4a53c39c3bc4f4..668f595e2fcfeadf29547bd33d46448bad6dc7e3 100644 (file)
@@ -13,12 +13,6 @@ enum btree_node_type;
 extern const char * const bch2_bkey_types[];
 extern const struct bkey_ops bch2_bkey_null_ops;
 
-enum bkey_invalid_flags {
-       BKEY_INVALID_WRITE              = (1U << 0),
-       BKEY_INVALID_COMMIT             = (1U << 1),
-       BKEY_INVALID_JOURNAL            = (1U << 2),
-};
-
 /*
  * key_invalid: checks validity of @k, returns 0 if good or -EINVAL if bad. If
  * invalid, entire key will be deleted.
index a3da5b4bcd21e68a6342f5e6ccff363b699c2e2d..cba3c081b1d0722d24fdb9a080796fbf584492ed 100644 (file)
@@ -779,7 +779,7 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
                        compat_btree_node(b->c.level, b->c.btree_id, version,
                                          BSET_BIG_ENDIAN(i), write, bn);
 
-               btree_err_on(bch2_bkey_format_validate(&bn->format, &buf1),
+               btree_err_on(bch2_bkey_format_invalid(c, &bn->format, write, &buf1),
                             -BCH_ERR_btree_node_read_err_bad_node, c, ca, b, i,
                             "invalid bkey format: %s\n  %s", buf1.buf,
                             (printbuf_reset(&buf2),
index edc9830d816344da48545e033a1757175258ca4e..35b67c544a6af69e8738fcff506db96cf210f360 100644 (file)
@@ -1322,12 +1322,6 @@ int bch2_fs_recovery(struct bch_fs *c)
                goto err;
        }
 
-       if (!(c->sb.compat & (1ULL << BCH_COMPAT_bformat_overflow_done))) {
-               bch_err(c, "filesystem may have incompatible bkey formats; run fsck from the compat branch to fix");
-               ret = -EINVAL;
-               goto err;
-       }
-
        if (c->opts.fsck || !(c->opts.nochanges && c->opts.norecovery))
                check_version_upgrade(c);
 
@@ -1527,7 +1521,6 @@ use_clean:
        mutex_unlock(&c->sb_lock);
 
        if (!(c->sb.compat & (1ULL << BCH_COMPAT_extents_above_btree_updates_done)) ||
-           !(c->sb.compat & (1ULL << BCH_COMPAT_bformat_overflow_done)) ||
            c->sb.version_min < bcachefs_metadata_version_btree_ptr_sectors_written) {
                struct bch_move_stats stats;
 
index c17fdcd0839040e3d879266b221e54b9f6456563..7ec22631cdd3d2d6f75195090bc36692e03a4ef9 100644 (file)
@@ -1996,6 +1996,7 @@ err:
 BCH_DEBUG_PARAMS()
 #undef BCH_DEBUG_PARAM
 
+__maybe_unused
 static unsigned bch2_metadata_version = bcachefs_metadata_version_current;
 module_param_named(version, bch2_metadata_version, uint, 0400);