bcachefs: bkey_format helper improvements
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 3 Aug 2023 18:42:37 +0000 (14:42 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:10:09 +0000 (17:10 -0400)
 - add a to_text() method for bkey_format

 - convert bch2_bkey_format_validate() to modern error message style,
   where we pass a printbuf for the error string instead of returning a
   static string

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

index ee7ba700e75f4ee3afbac3ab241c7d6d9b1278c3..b7b77f4597240090c350c262498899f2a897d4b8 100644 (file)
@@ -608,12 +608,15 @@ struct bkey_format bch2_bkey_format_done(struct bkey_format_state *s)
        return ret;
 }
 
-const char *bch2_bkey_format_validate(struct bkey_format *f)
+int bch2_bkey_format_validate(struct bkey_format *f, struct printbuf *err)
 {
        unsigned i, bits = KEY_PACKED_BITS_START;
 
-       if (f->nr_fields != BKEY_NR_FIELDS)
-               return "incorrect number of fields";
+       if (f->nr_fields != BKEY_NR_FIELDS) {
+               prt_printf(err, "incorrect number of fields: got %u, should be %u",
+                          f->nr_fields, BKEY_NR_FIELDS);
+               return -BCH_ERR_invalid;
+       }
 
        /*
         * Verify that the packed format can't represent fields larger than the
@@ -628,16 +631,35 @@ const char *bch2_bkey_format_validate(struct bkey_format *f)
                u64 field_offset = le64_to_cpu(f->field_offset[i]);
 
                if (packed_max + field_offset < packed_max ||
-                   packed_max + field_offset > unpacked_max)
-                       return "field too large";
+                   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];
        }
 
-       if (f->key_u64s != DIV_ROUND_UP(bits, 64))
-               return "incorrect key_u64s";
+       if (f->key_u64s != DIV_ROUND_UP(bits, 64)) {
+               prt_printf(err, "incorrect key_u64s: got %u, should be %u",
+                          f->key_u64s, DIV_ROUND_UP(bits, 64));
+               return -BCH_ERR_invalid;
+       }
+
+       return 0;
+}
 
-       return NULL;
+void bch2_bkey_format_to_text(struct printbuf *out, const struct bkey_format *f)
+{
+       prt_printf(out, "u64s %u fields ", f->key_u64s);
+
+       for (unsigned i = 0; i < ARRAY_SIZE(f->bits_per_field); i++) {
+               if (i)
+                       prt_str(out, ", ");
+               prt_printf(out, "%u:%llu",
+                          f->bits_per_field[i],
+                          le64_to_cpu(f->field_offset[i]));
+       }
 }
 
 /*
index e81fb3e00c602dfca2e544ac85de7b4584c5b92d..644caa2b2b25a0d4e46154e19cf4be202b9bfc8b 100644 (file)
@@ -769,6 +769,7 @@ 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 *);
-const char *bch2_bkey_format_validate(struct bkey_format *);
+int bch2_bkey_format_validate(struct bkey_format *, struct printbuf *);
+void bch2_bkey_format_to_text(struct printbuf *, const struct bkey_format *);
 
 #endif /* _BCACHEFS_BKEY_H */
index 346bfaf99460c537e9162852a4d6d03ef16f675a..245ddd92b2d1d3029239065e905067995e7af364 100644 (file)
@@ -1165,7 +1165,6 @@ wait_on_io:
 void bch2_btree_node_to_text(struct printbuf *out, struct bch_fs *c,
                             const struct btree *b)
 {
-       const struct bkey_format *f = &b->format;
        struct bset_stats stats;
 
        memset(&stats, 0, sizeof(stats));
@@ -1179,9 +1178,13 @@ void bch2_btree_node_to_text(struct printbuf *out, struct bch_fs *c,
        prt_printf(out, ":\n"
               "    ptrs: ");
        bch2_val_to_text(out, c, bkey_i_to_s_c(&b->key));
+       prt_newline(out);
 
-       prt_printf(out, "\n"
-              "    format: u64s %u fields %u %u %u %u %u\n"
+       prt_printf(out,
+              "    format: ");
+       bch2_bkey_format_to_text(out, &b->format);
+
+       prt_printf(out,
               "    unpack fn len: %u\n"
               "    bytes used %zu/%zu (%zu%% full)\n"
               "    sib u64s: %u, %u (merge threshold %u)\n"
@@ -1189,12 +1192,6 @@ void bch2_btree_node_to_text(struct printbuf *out, struct bch_fs *c,
               "    nr unpacked keys %u\n"
               "    floats %zu\n"
               "    failed unpacked %zu\n",
-              f->key_u64s,
-              f->bits_per_field[0],
-              f->bits_per_field[1],
-              f->bits_per_field[2],
-              f->bits_per_field[3],
-              f->bits_per_field[4],
               b->unpack_fn_len,
               b->nr.live_u64s * sizeof(u64),
               btree_bytes(c) - sizeof(struct btree_node),
index 7bfb8b8d4cb540e0806a0bb7de11344c56e1a2d0..2339395e0bd2f123b0451032e34411058fab801c 100644 (file)
@@ -694,7 +694,6 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
                         int write, bool have_retry, bool *saw_error)
 {
        unsigned version = le16_to_cpu(i->version);
-       const char *err;
        struct printbuf buf1 = PRINTBUF;
        struct printbuf buf2 = PRINTBUF;
        int ret = 0;
@@ -802,10 +801,12 @@ 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);
 
-               err = bch2_bkey_format_validate(&bn->format);
-               btree_err_on(err,
+               btree_err_on(bch2_bkey_format_validate(&bn->format, &buf1),
                             BTREE_ERR_BAD_NODE, c, ca, b, i,
-                            "invalid bkey format: %s", err);
+                            "invalid bkey format: %s\n  %s", buf1.buf,
+                            (printbuf_reset(&buf2),
+                             bch2_bkey_format_to_text(&buf2, &bn->format), buf2.buf));
+               printbuf_reset(&buf1);
 
                compat_bformat(b->c.level, b->c.btree_id, version,
                               BSET_BIG_ENDIAN(i), write,