bcachefs: jset_entry_datetime
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 27 Jan 2024 15:16:15 +0000 (10:16 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 10 Mar 2024 19:34:08 +0000 (15:34 -0400)
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>
fs/bcachefs/bcachefs_format.h
fs/bcachefs/journal_io.c
fs/bcachefs/journal_io.h
fs/bcachefs/sb-clean.c

index 0668b682a21ca8e035cae73f73e6774c99eaeb94..14f613617913e1a3ef0e93c51caa041041f822c2 100644 (file)
@@ -1275,7 +1275,8 @@ static inline __u64 __bset_magic(struct bch_sb *sb)
        x(dev_usage,            8)              \
        x(log,                  9)              \
        x(overwrite,            10)             \
-       x(write_buffer_keys,    11)
+       x(write_buffer_keys,    11)             \
+       x(datetime,             12)
 
 enum {
 #define x(f, nr)       BCH_JSET_ENTRY_##f      = nr,
@@ -1376,6 +1377,11 @@ struct jset_entry_log {
        u8                      d[];
 } __packed __aligned(8);
 
+struct jset_entry_datetime {
+       struct jset_entry       entry;
+       __le64                  seconds;
+} __packed __aligned(8);
+
 /*
  * On disk format for a journal entry:
  * seq is monotonically increasing; every journal entry has its own unique
index 66ce522950fff61d3a44473ae67763c59351184b..0ca6d976f4d51a8ceca262e57f3288e5890d3d3a 100644 (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));
 
        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)
@@ -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);
 }
 
+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 {
        int (*validate)(struct bch_fs *, struct jset *,
                        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);
 
+       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);
        u64s    = (u64 *) end - (u64 *) start;
        BUG_ON(u64s > j->entry_u64s_reserved);
index 1e0b9a57164868033fbf92dfeb822bad42e8ccd6..1f395f43cf76f38e66b9bd7b57dc56b0d72debfc 100644 (file)
@@ -65,4 +65,20 @@ int bch2_journal_read(struct bch_fs *, u64 *, u64 *, u64 *);
 
 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 */
index b6bf0ebe7e84046a5d08ade7d34bae9ae0bff3a5..5980ba2563fe9fa159ba9d87fe08ab2dc53a78fb 100644 (file)
@@ -171,22 +171,6 @@ fsck_err:
        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,
                                           struct jset_entry **end,
                                           u64 journal_seq)