bcachefs: bch2_journal_entry_to_text()

This adds a _to_text() pretty printer for journal entries - including
every subtype - which will shortly be used by the 'bcachefs
list_journal' subcommand.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
Kent Overstreet 2021-12-31 17:06:29 -05:00 committed by Kent Overstreet
parent fb64f3fdac
commit 528b18e6d1
7 changed files with 169 additions and 27 deletions

View File

@ -76,6 +76,7 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/uuid.h> #include <linux/uuid.h>
#include "vstructs.h"
#ifdef __KERNEL__ #ifdef __KERNEL__
typedef uuid_t __uuid_t; typedef uuid_t __uuid_t;
@ -1699,11 +1700,16 @@ struct jset_entry_blacklist_v2 {
__le64 end; __le64 end;
}; };
#define BCH_FS_USAGE_TYPES() \
x(reserved, 0) \
x(inodes, 1) \
x(key_version, 2)
enum { enum {
FS_USAGE_RESERVED = 0, #define x(f, nr) BCH_FS_USAGE_##f = nr,
FS_USAGE_INODES = 1, BCH_FS_USAGE_TYPES()
FS_USAGE_KEY_VERSION = 2, #undef x
FS_USAGE_NR = 3 BCH_FS_USAGE_NR
}; };
struct jset_entry_usage { struct jset_entry_usage {
@ -1741,6 +1747,12 @@ struct jset_entry_dev_usage {
struct jset_entry_dev_usage_type d[]; struct jset_entry_dev_usage_type d[];
} __attribute__((packed)); } __attribute__((packed));
static inline unsigned jset_entry_dev_usage_nr_types(struct jset_entry_dev_usage *u)
{
return (vstruct_bytes(&u->entry) - sizeof(struct jset_entry_dev_usage)) /
sizeof(struct jset_entry_dev_usage_type);
}
struct jset_entry_log { struct jset_entry_log {
struct jset_entry entry; struct jset_entry entry;
u8 d[]; u8 d[];

View File

@ -273,7 +273,7 @@ fsck_err:
return ret; return ret;
} }
static int journal_entry_validate_btree_keys(struct bch_fs *c, static int journal_entry_btree_keys_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -294,7 +294,18 @@ static int journal_entry_validate_btree_keys(struct bch_fs *c,
return 0; return 0;
} }
static int journal_entry_validate_btree_root(struct bch_fs *c, static void journal_entry_btree_keys_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct bkey_i *k;
pr_buf(out, "btree=%s l=%u ", bch2_btree_ids[entry->btree_id], entry->level);
vstruct_for_each(entry, k)
bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(k));
}
static int journal_entry_btree_root_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -322,7 +333,13 @@ fsck_err:
return ret; return ret;
} }
static int journal_entry_validate_prio_ptrs(struct bch_fs *c, static void journal_entry_btree_root_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
journal_entry_btree_keys_to_text(out, c, entry);
}
static int journal_entry_prio_ptrs_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -331,7 +348,12 @@ static int journal_entry_validate_prio_ptrs(struct bch_fs *c,
return 0; return 0;
} }
static int journal_entry_validate_blacklist(struct bch_fs *c, static void journal_entry_prio_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
}
static int journal_entry_blacklist_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -346,7 +368,16 @@ fsck_err:
return ret; return ret;
} }
static int journal_entry_validate_blacklist_v2(struct bch_fs *c, static void journal_entry_blacklist_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct jset_entry_blacklist *bl =
container_of(entry, struct jset_entry_blacklist, entry);
pr_buf(out, "seq=%llu", le64_to_cpu(bl->seq));
}
static int journal_entry_blacklist_v2_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -372,7 +403,18 @@ fsck_err:
return ret; return ret;
} }
static int journal_entry_validate_usage(struct bch_fs *c, static void journal_entry_blacklist_v2_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct jset_entry_blacklist_v2 *bl =
container_of(entry, struct jset_entry_blacklist_v2, entry);
pr_buf(out, "start=%llu end=%llu",
le64_to_cpu(bl->start),
le64_to_cpu(bl->end));
}
static int journal_entry_usage_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -393,7 +435,18 @@ fsck_err:
return ret; return ret;
} }
static int journal_entry_validate_data_usage(struct bch_fs *c, static void journal_entry_usage_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct jset_entry_usage *u =
container_of(entry, struct jset_entry_usage, entry);
pr_buf(out, "type=%s v=%llu",
bch2_fs_usage_types[u->entry.btree_id],
le64_to_cpu(u->v));
}
static int journal_entry_data_usage_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -415,7 +468,17 @@ fsck_err:
return ret; return ret;
} }
static int journal_entry_validate_clock(struct bch_fs *c, static void journal_entry_data_usage_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct jset_entry_data_usage *u =
container_of(entry, struct jset_entry_data_usage, entry);
bch2_replicas_entry_to_text(out, &u->r);
pr_buf(out, "=%llu", le64_to_cpu(u->v));
}
static int journal_entry_clock_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -441,7 +504,16 @@ fsck_err:
return ret; return ret;
} }
static int journal_entry_validate_dev_usage(struct bch_fs *c, static void journal_entry_clock_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct jset_entry_clock *clock =
container_of(entry, struct jset_entry_clock, entry);
pr_buf(out, "%s=%llu", clock->rw ? "write" : "read", le64_to_cpu(clock->time));
}
static int journal_entry_dev_usage_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -478,7 +550,32 @@ fsck_err:
return ret; return ret;
} }
static int journal_entry_validate_log(struct bch_fs *c, static void journal_entry_dev_usage_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct jset_entry_dev_usage *u =
container_of(entry, struct jset_entry_dev_usage, entry);
unsigned i, nr_types = jset_entry_dev_usage_nr_types(u);
pr_buf(out, "dev=%u", le32_to_cpu(u->dev));
for (i = 0; i < nr_types; i++) {
if (i < BCH_DATA_NR)
pr_buf(out, " %s", bch2_data_types[i]);
else
pr_buf(out, " (unknown data type %u)", i);
pr_buf(out, ": buckets=%llu sectors=%llu fragmented=%llu",
le64_to_cpu(u->d[i].buckets),
le64_to_cpu(u->d[i].sectors),
le64_to_cpu(u->d[i].fragmented));
}
pr_buf(out, " buckets_ec: %llu buckets_unavailable: %llu",
le64_to_cpu(u->buckets_ec),
le64_to_cpu(u->buckets_unavailable));
}
static int journal_entry_log_validate(struct bch_fs *c,
const char *where, const char *where,
struct jset_entry *entry, struct jset_entry *entry,
unsigned version, int big_endian, int write) unsigned version, int big_endian, int write)
@ -486,15 +583,26 @@ static int journal_entry_validate_log(struct bch_fs *c,
return 0; return 0;
} }
static void journal_entry_log_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct jset_entry_log *l = container_of(entry, struct jset_entry_log, entry);
unsigned bytes = vstruct_bytes(entry) - offsetof(struct jset_entry_log, d);
bch_scnmemcpy(out, l->d, strnlen(l->d, bytes));
}
struct jset_entry_ops { struct jset_entry_ops {
int (*validate)(struct bch_fs *, const char *, int (*validate)(struct bch_fs *, const char *,
struct jset_entry *, unsigned, int, int); struct jset_entry *, unsigned, int, int);
void (*to_text)(struct printbuf *, struct bch_fs *, struct jset_entry *);
}; };
static const struct jset_entry_ops bch2_jset_entry_ops[] = { static const struct jset_entry_ops bch2_jset_entry_ops[] = {
#define x(f, nr) \ #define x(f, nr) \
[BCH_JSET_ENTRY_##f] = (struct jset_entry_ops) { \ [BCH_JSET_ENTRY_##f] = (struct jset_entry_ops) { \
.validate = journal_entry_validate_##f, \ .validate = journal_entry_##f##_validate, \
.to_text = journal_entry_##f##_to_text, \
}, },
BCH_JSET_ENTRY_TYPES() BCH_JSET_ENTRY_TYPES()
#undef x #undef x
@ -510,6 +618,17 @@ int bch2_journal_entry_validate(struct bch_fs *c, const char *where,
: 0; : 0;
} }
void bch2_journal_entry_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
if (entry->type < BCH_JSET_ENTRY_NR) {
pr_buf(out, "%s: ", bch2_jset_entry_types[entry->type]);
bch2_jset_entry_ops[entry->type].to_text(out, c, entry);
} else {
pr_buf(out, "(unknown type %u)", entry->type);
}
}
static int jset_validate_entries(struct bch_fs *c, struct jset *jset, static int jset_validate_entries(struct bch_fs *c, struct jset *jset,
int write) int write)
{ {

View File

@ -40,8 +40,10 @@ static inline struct jset_entry *__jset_entry_type_next(struct jset *jset,
for_each_jset_entry_type(entry, jset, BCH_JSET_ENTRY_btree_keys) \ for_each_jset_entry_type(entry, jset, BCH_JSET_ENTRY_btree_keys) \
vstruct_for_each_safe(entry, k, _n) vstruct_for_each_safe(entry, k, _n)
int bch2_journal_entry_validate(struct bch_fs *, const char *, struct jset_entry *, int bch2_journal_entry_validate(struct bch_fs *, const char *,
unsigned, int, int); struct jset_entry *, unsigned, int, int);
void bch2_journal_entry_to_text(struct printbuf *, struct bch_fs *,
struct jset_entry *);
int bch2_journal_read(struct bch_fs *, struct list_head *, u64 *, u64 *); int bch2_journal_read(struct bch_fs *, struct list_head *, u64 *, u64 *);

View File

@ -71,6 +71,16 @@ const char * const bch2_member_states[] = {
NULL NULL
}; };
const char * const bch2_jset_entry_types[] = {
BCH_JSET_ENTRY_TYPES()
NULL
};
const char * const bch2_fs_usage_types[] = {
BCH_FS_USAGE_TYPES()
NULL
};
#undef x #undef x
const char * const bch2_d_types[BCH_DT_MAX] = { const char * const bch2_d_types[BCH_DT_MAX] = {

View File

@ -20,6 +20,8 @@ extern const char * const bch2_str_hash_types[];
extern const char * const bch2_str_hash_opts[]; extern const char * const bch2_str_hash_opts[];
extern const char * const bch2_data_types[]; extern const char * const bch2_data_types[];
extern const char * const bch2_member_states[]; extern const char * const bch2_member_states[];
extern const char * const bch2_jset_entry_types[];
extern const char * const bch2_fs_usage_types[];
extern const char * const bch2_d_types[]; extern const char * const bch2_d_types[];
static inline const char *bch2_d_type_str(unsigned d_type) static inline const char *bch2_d_type_str(unsigned d_type)

View File

@ -714,15 +714,15 @@ static int journal_replay_entry_early(struct bch_fs *c,
container_of(entry, struct jset_entry_usage, entry); container_of(entry, struct jset_entry_usage, entry);
switch (entry->btree_id) { switch (entry->btree_id) {
case FS_USAGE_RESERVED: case BCH_FS_USAGE_reserved:
if (entry->level < BCH_REPLICAS_MAX) if (entry->level < BCH_REPLICAS_MAX)
c->usage_base->persistent_reserved[entry->level] = c->usage_base->persistent_reserved[entry->level] =
le64_to_cpu(u->v); le64_to_cpu(u->v);
break; break;
case FS_USAGE_INODES: case BCH_FS_USAGE_inodes:
c->usage_base->nr_inodes = le64_to_cpu(u->v); c->usage_base->nr_inodes = le64_to_cpu(u->v);
break; break;
case FS_USAGE_KEY_VERSION: case BCH_FS_USAGE_key_version:
atomic64_set(&c->key_version, atomic64_set(&c->key_version,
le64_to_cpu(u->v)); le64_to_cpu(u->v));
break; break;
@ -742,10 +742,7 @@ static int journal_replay_entry_early(struct bch_fs *c,
struct jset_entry_dev_usage *u = struct jset_entry_dev_usage *u =
container_of(entry, struct jset_entry_dev_usage, entry); container_of(entry, struct jset_entry_dev_usage, entry);
struct bch_dev *ca = bch_dev_bkey_exists(c, le32_to_cpu(u->dev)); struct bch_dev *ca = bch_dev_bkey_exists(c, le32_to_cpu(u->dev));
unsigned bytes = jset_u64s(le16_to_cpu(entry->u64s)) * sizeof(u64); unsigned i, nr_types = jset_entry_dev_usage_nr_types(u);
unsigned nr_types = (bytes - sizeof(struct jset_entry_dev_usage)) /
sizeof(struct jset_entry_dev_usage_type);
unsigned i;
ca->usage_base->buckets_ec = le64_to_cpu(u->buckets_ec); ca->usage_base->buckets_ec = le64_to_cpu(u->buckets_ec);
ca->usage_base->buckets_unavailable = le64_to_cpu(u->buckets_unavailable); ca->usage_base->buckets_unavailable = le64_to_cpu(u->buckets_unavailable);

View File

@ -1029,7 +1029,7 @@ void bch2_journal_super_entries_add_common(struct bch_fs *c,
struct jset_entry_usage, entry); struct jset_entry_usage, entry);
u->entry.type = BCH_JSET_ENTRY_usage; u->entry.type = BCH_JSET_ENTRY_usage;
u->entry.btree_id = FS_USAGE_INODES; u->entry.btree_id = BCH_FS_USAGE_inodes;
u->v = cpu_to_le64(c->usage_base->nr_inodes); u->v = cpu_to_le64(c->usage_base->nr_inodes);
} }
@ -1039,7 +1039,7 @@ void bch2_journal_super_entries_add_common(struct bch_fs *c,
struct jset_entry_usage, entry); struct jset_entry_usage, entry);
u->entry.type = BCH_JSET_ENTRY_usage; u->entry.type = BCH_JSET_ENTRY_usage;
u->entry.btree_id = FS_USAGE_KEY_VERSION; u->entry.btree_id = BCH_FS_USAGE_key_version;
u->v = cpu_to_le64(atomic64_read(&c->key_version)); u->v = cpu_to_le64(atomic64_read(&c->key_version));
} }
@ -1049,7 +1049,7 @@ void bch2_journal_super_entries_add_common(struct bch_fs *c,
struct jset_entry_usage, entry); struct jset_entry_usage, entry);
u->entry.type = BCH_JSET_ENTRY_usage; u->entry.type = BCH_JSET_ENTRY_usage;
u->entry.btree_id = FS_USAGE_RESERVED; u->entry.btree_id = BCH_FS_USAGE_reserved;
u->entry.level = i; u->entry.level = i;
u->v = cpu_to_le64(c->usage_base->persistent_reserved[i]); u->v = cpu_to_le64(c->usage_base->persistent_reserved[i]);
} }