]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: BCH_JSET_ENTRY_log
authorKent Overstreet <kent.overstreet@gmail.com>
Fri, 31 Dec 2021 21:12:54 +0000 (16:12 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:20 +0000 (17:09 -0400)
Add a journal entry type for logging messages, and add an option to use
it to log the transaction name - this makes for a very handy debugging
tool, as with it we can use the 'bcachefs list_journal' command to see
not only what updates were done, but what was doing them.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/bcachefs_format.h
fs/bcachefs/btree_types.h
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/journal_io.c
fs/bcachefs/opts.h

index 3c0ba301dad5549c7863adb7acd650e20588146c..7eeab46d21b54e2a026d04adeeee45fd5ebee0ac 100644 (file)
@@ -1430,6 +1430,7 @@ LE64_BITMASK(BCH_SB_INODES_USE_KEY_CACHE,struct bch_sb, flags[3], 29, 30);
 LE64_BITMASK(BCH_SB_JOURNAL_FLUSH_DELAY,struct bch_sb, flags[3], 30, 62);
 LE64_BITMASK(BCH_SB_JOURNAL_FLUSH_DISABLED,struct bch_sb, flags[3], 62, 63);
 LE64_BITMASK(BCH_SB_JOURNAL_RECLAIM_DELAY,struct bch_sb, flags[4], 0, 32);
+LE64_BITMASK(BCH_SB_JOURNAL_TRANSACTION_NAMES,struct bch_sb, flags[4], 32, 33);
 
 /*
  * Features:
@@ -1667,7 +1668,8 @@ static inline __u64 __bset_magic(struct bch_sb *sb)
        x(usage,                5)              \
        x(data_usage,           6)              \
        x(clock,                7)              \
-       x(dev_usage,            8)
+       x(dev_usage,            8)              \
+       x(log,                  9)
 
 enum {
 #define x(f, nr)       BCH_JSET_ENTRY_##f      = nr,
@@ -1739,6 +1741,11 @@ struct jset_entry_dev_usage {
        struct jset_entry_dev_usage_type d[];
 } __attribute__((packed));
 
+struct jset_entry_log {
+       struct jset_entry       entry;
+       u8                      d[];
+} __attribute__((packed));
+
 /*
  * On disk format for a journal entry:
  * seq is monotonically increasing; every journal entry has its own unique
index 223af7848fb45efa5d88da5e6b848cb552f58e2f..2c8b30949e6f86925f2fae67cb590e91249571a1 100644 (file)
@@ -380,6 +380,7 @@ struct btree_trans {
        bool                    in_traverse_all:1;
        bool                    restarted:1;
        bool                    paths_sorted:1;
+       bool                    journal_transaction_names:1;
        /*
         * For when bch2_trans_update notices we'll be splitting a compressed
         * extent:
index a70dc68d2fbaffb89a97b3a3ff6f8c2ece058bc6..40deafced921360cc3274c68944f1273cd48950f 100644 (file)
@@ -290,6 +290,31 @@ static inline int bch2_trans_journal_res_get(struct btree_trans *trans,
        return ret == -EAGAIN ? BTREE_INSERT_NEED_JOURNAL_RES : ret;
 }
 
+#define JSET_ENTRY_LOG_U64s            4
+
+static noinline void journal_transaction_name(struct btree_trans *trans)
+{
+       struct bch_fs *c = trans->c;
+       struct jset_entry *entry = journal_res_entry(&c->journal, &trans->journal_res);
+       struct jset_entry_log *l = container_of(entry, struct jset_entry_log, entry);
+       unsigned u64s = JSET_ENTRY_LOG_U64s - 1;
+       unsigned b, buflen = u64s * sizeof(u64);
+
+       l->entry.u64s           = cpu_to_le16(u64s);
+       l->entry.btree_id       = 0;
+       l->entry.level          = 0;
+       l->entry.type           = BCH_JSET_ENTRY_log;
+       l->entry.pad[0]         = 0;
+       l->entry.pad[1]         = 0;
+       l->entry.pad[2]         = 0;
+       b = snprintf(l->d, buflen, "%ps", (void *) trans->ip);
+       while (b < buflen)
+               l->d[b++] = '\0';
+
+       trans->journal_res.offset       += JSET_ENTRY_LOG_U64s;
+       trans->journal_res.u64s         -= JSET_ENTRY_LOG_U64s;
+}
+
 static inline enum btree_insert_ret
 btree_key_can_insert(struct btree_trans *trans,
                     struct btree *b,
@@ -451,6 +476,9 @@ bch2_trans_commit_write_locked(struct btree_trans *trans,
                                JOURNAL_RES_GET_NONBLOCK);
                if (ret)
                        return ret;
+
+               if (unlikely(trans->journal_transaction_names))
+                       journal_transaction_name(trans);
        } else {
                trans->journal_res.seq = c->journal.replay_journal_seq;
        }
@@ -911,6 +939,7 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
 
 int __bch2_trans_commit(struct btree_trans *trans)
 {
+       struct bch_fs *c = trans->c;
        struct btree_insert_entry *i = NULL;
        unsigned u64s;
        int ret = 0;
@@ -920,15 +949,20 @@ int __bch2_trans_commit(struct btree_trans *trans)
                goto out_reset;
 
        if (trans->flags & BTREE_INSERT_GC_LOCK_HELD)
-               lockdep_assert_held(&trans->c->gc_lock);
+               lockdep_assert_held(&c->gc_lock);
 
        memset(&trans->journal_preres, 0, sizeof(trans->journal_preres));
 
        trans->journal_u64s             = trans->extra_journal_entry_u64s;
        trans->journal_preres_u64s      = 0;
 
+       trans->journal_transaction_names = READ_ONCE(c->opts.journal_transaction_names);
+
+       if (trans->journal_transaction_names)
+               trans->journal_u64s += JSET_ENTRY_LOG_U64s;
+
        if (!(trans->flags & BTREE_INSERT_NOCHECK_RW) &&
-           unlikely(!percpu_ref_tryget(&trans->c->writes))) {
+           unlikely(!percpu_ref_tryget(&c->writes))) {
                ret = bch2_trans_commit_get_rw_cold(trans);
                if (ret)
                        goto out_reset;
@@ -972,7 +1006,7 @@ int __bch2_trans_commit(struct btree_trans *trans)
        }
 
        if (trans->extra_journal_res) {
-               ret = bch2_disk_reservation_add(trans->c, trans->disk_res,
+               ret = bch2_disk_reservation_add(c, trans->disk_res,
                                trans->extra_journal_res,
                                (trans->flags & BTREE_INSERT_NOFAIL)
                                ? BCH_DISK_RESERVATION_NOFAIL : 0);
@@ -991,10 +1025,10 @@ retry:
        if (ret)
                goto err;
 out:
-       bch2_journal_preres_put(&trans->c->journal, &trans->journal_preres);
+       bch2_journal_preres_put(&c->journal, &trans->journal_preres);
 
        if (likely(!(trans->flags & BTREE_INSERT_NOCHECK_RW)))
-               percpu_ref_put(&trans->c->writes);
+               percpu_ref_put(&c->writes);
 out_reset:
        trans_for_each_update(trans, i)
                bch2_path_put(trans, i->path, true);
index 4f8dd0130b37b37d4eb90545719566919f23ddf0..012b89e9d3cd30bea58945d13a0de134ff572d1f 100644 (file)
@@ -478,6 +478,14 @@ fsck_err:
        return ret;
 }
 
+static int journal_entry_validate_log(struct bch_fs *c,
+                                     const char *where,
+                                     struct jset_entry *entry,
+                                     unsigned version, int big_endian, int write)
+{
+       return 0;
+}
+
 struct jset_entry_ops {
        int (*validate)(struct bch_fs *, const char *,
                        struct jset_entry *, unsigned, int, int);
index af61fe588d3fd6ec626e65da9d258b15c01257af..f7355c455b628caf443f11b6c59c94418b7ae7c8 100644 (file)
@@ -327,6 +327,11 @@ enum opt_type {
          OPT_BOOL(),                                                   \
          NO_SB_OPT,                    false,                          \
          NULL,         "Read all journal entries, not just dirty ones")\
+       x(journal_transaction_names,    u8,                             \
+         OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME,                      \
+         OPT_BOOL(),                                                   \
+         BCH_SB_JOURNAL_TRANSACTION_NAMES, true,                       \
+         NULL,         "Log transaction function names in journal")    \
        x(noexcl,                       u8,                             \
          OPT_FS|OPT_MOUNT,                                             \
          OPT_BOOL(),                                                   \