bcachefs: jset_entry_datetime

This gives us a way to record the date and time every journal entry was
written - useful for debugging.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-01-27 10:16:15 -05:00
parent 3d3d23b341
commit 52f7d75e7d
4 changed files with 67 additions and 17 deletions

View File

@ -1275,7 +1275,8 @@ static inline __u64 __bset_magic(struct bch_sb *sb)
x(dev_usage, 8) \ x(dev_usage, 8) \
x(log, 9) \ x(log, 9) \
x(overwrite, 10) \ x(overwrite, 10) \
x(write_buffer_keys, 11) x(write_buffer_keys, 11) \
x(datetime, 12)
enum { enum {
#define x(f, nr) BCH_JSET_ENTRY_##f = nr, #define x(f, nr) BCH_JSET_ENTRY_##f = nr,
@ -1376,6 +1377,11 @@ struct jset_entry_log {
u8 d[]; u8 d[];
} __packed __aligned(8); } __packed __aligned(8);
struct jset_entry_datetime {
struct jset_entry entry;
__le64 seconds;
} __packed __aligned(8);
/* /*
* On disk format for a journal entry: * On disk format for a journal entry:
* seq is monotonically increasing; every journal entry has its own unique * seq is monotonically increasing; every journal entry has its own unique

View File

@ -39,6 +39,14 @@ static void bch2_journal_replay_to_text(struct printbuf *out, struct bch_fs *c,
prt_printf(out, "seq %llu ", le64_to_cpu(j->j.seq)); prt_printf(out, "seq %llu ", le64_to_cpu(j->j.seq));
bch2_journal_ptrs_to_text(out, c, j); bch2_journal_ptrs_to_text(out, c, j);
struct jset_entry *entry;
for_each_jset_entry_type(entry, &j->j, BCH_JSET_ENTRY_datetime) {
struct jset_entry_datetime *datetime =
container_of(entry, struct jset_entry_datetime, entry);
bch2_prt_datetime(out, le64_to_cpu(datetime->seconds));
break;
}
} }
static struct nonce journal_nonce(const struct jset *jset) static struct nonce journal_nonce(const struct jset *jset)
@ -754,6 +762,37 @@ static void journal_entry_write_buffer_keys_to_text(struct printbuf *out, struct
journal_entry_btree_keys_to_text(out, c, entry); journal_entry_btree_keys_to_text(out, c, entry);
} }
static int journal_entry_datetime_validate(struct bch_fs *c,
struct jset *jset,
struct jset_entry *entry,
unsigned version, int big_endian,
enum bkey_invalid_flags flags)
{
unsigned bytes = vstruct_bytes(entry);
unsigned expected = 16;
int ret = 0;
if (journal_entry_err_on(vstruct_bytes(entry) < expected,
c, version, jset, entry,
journal_entry_dev_usage_bad_size,
"bad size (%u < %u)",
bytes, expected)) {
journal_entry_null_range(entry, vstruct_next(entry));
return ret;
}
fsck_err:
return ret;
}
static void journal_entry_datetime_to_text(struct printbuf *out, struct bch_fs *c,
struct jset_entry *entry)
{
struct jset_entry_datetime *datetime =
container_of(entry, struct jset_entry_datetime, entry);
bch2_prt_datetime(out, le64_to_cpu(datetime->seconds));
}
struct jset_entry_ops { struct jset_entry_ops {
int (*validate)(struct bch_fs *, struct jset *, int (*validate)(struct bch_fs *, struct jset *,
struct jset_entry *, unsigned, int, struct jset_entry *, unsigned, int,
@ -1794,6 +1833,11 @@ static int bch2_journal_write_prep(struct journal *j, struct journal_buf *w)
end = bch2_btree_roots_to_journal_entries(c, end, btree_roots_have); end = bch2_btree_roots_to_journal_entries(c, end, btree_roots_have);
struct jset_entry_datetime *d =
container_of(jset_entry_init(&end, sizeof(*d)), struct jset_entry_datetime, entry);
d->entry.type = BCH_JSET_ENTRY_datetime;
d->seconds = cpu_to_le64(ktime_get_real_seconds());
bch2_journal_super_entries_add_common(c, &end, seq); bch2_journal_super_entries_add_common(c, &end, seq);
u64s = (u64 *) end - (u64 *) start; u64s = (u64 *) end - (u64 *) start;
BUG_ON(u64s > j->entry_u64s_reserved); BUG_ON(u64s > j->entry_u64s_reserved);

View File

@ -65,4 +65,20 @@ int bch2_journal_read(struct bch_fs *, u64 *, u64 *, u64 *);
CLOSURE_CALLBACK(bch2_journal_write); CLOSURE_CALLBACK(bch2_journal_write);
static inline struct jset_entry *jset_entry_init(struct jset_entry **end, size_t size)
{
struct jset_entry *entry = *end;
unsigned u64s = DIV_ROUND_UP(size, sizeof(u64));
memset(entry, 0, u64s * sizeof(u64));
/*
* The u64s field counts from the start of data, ignoring the shared
* fields.
*/
entry->u64s = cpu_to_le16(u64s - 1);
*end = vstruct_next(*end);
return entry;
}
#endif /* _BCACHEFS_JOURNAL_IO_H */ #endif /* _BCACHEFS_JOURNAL_IO_H */

View File

@ -171,22 +171,6 @@ fsck_err:
return ERR_PTR(ret); return ERR_PTR(ret);
} }
static struct jset_entry *jset_entry_init(struct jset_entry **end, size_t size)
{
struct jset_entry *entry = *end;
unsigned u64s = DIV_ROUND_UP(size, sizeof(u64));
memset(entry, 0, u64s * sizeof(u64));
/*
* The u64s field counts from the start of data, ignoring the shared
* fields.
*/
entry->u64s = cpu_to_le16(u64s - 1);
*end = vstruct_next(*end);
return entry;
}
void bch2_journal_super_entries_add_common(struct bch_fs *c, void bch2_journal_super_entries_add_common(struct bch_fs *c,
struct jset_entry **end, struct jset_entry **end,
u64 journal_seq) u64 journal_seq)