goto fatal_err;
        }
 
-       trans_for_each_update(trans, i) {
-               enum bch_validate_flags invalid_flags = 0;
-
-               if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
-                       invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
-
-               ret = bch2_bkey_validate(c, bkey_i_to_s_c(i->k),
-                                        (struct bkey_validate_context) {
-                                               .from   = BKEY_VALIDATE_commit,
-                                               .level  = i->level,
-                                               .btree  = i->btree_id,
-                                               .flags  = invalid_flags,
-                                        });
-               if (unlikely(ret)){
-                       bch2_trans_inconsistent(trans, "invalid bkey on insert from %s -> %ps\n",
-                                               trans->fn, (void *) i->ip_allocated);
-                       goto fatal_err;
-               }
-               btree_insert_entry_checks(trans, i);
-       }
+       struct bkey_validate_context validate_context = { .from = BKEY_VALIDATE_commit };
+
+       if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
+               validate_context.flags = BCH_VALIDATE_write|BCH_VALIDATE_commit;
 
        for (struct jset_entry *i = trans->journal_entries;
             i != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
             i = vstruct_next(i)) {
-               enum bch_validate_flags invalid_flags = 0;
-
-               if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
-                       invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
-
                ret = bch2_journal_entry_validate(c, NULL, i,
                                                  bcachefs_metadata_version_current,
-                                                 CPU_BIG_ENDIAN, invalid_flags);
+                                                 CPU_BIG_ENDIAN, validate_context);
                if (unlikely(ret)) {
                        bch2_trans_inconsistent(trans, "invalid journal entry on insert from %s\n",
                                                trans->fn);
                }
        }
 
+       trans_for_each_update(trans, i) {
+               validate_context.level  = i->level;
+               validate_context.btree  = i->btree_id;
+
+               ret = bch2_bkey_validate(c, bkey_i_to_s_c(i->k), validate_context);
+               if (unlikely(ret)){
+                       bch2_trans_inconsistent(trans, "invalid bkey on insert from %s -> %ps\n",
+                                               trans->fn, (void *) i->ip_allocated);
+                       goto fatal_err;
+               }
+               btree_insert_entry_checks(trans, i);
+       }
+
        if (likely(!(flags & BCH_TRANS_COMMIT_no_journal_res))) {
                struct journal *j = &c->journal;
                struct jset_entry *entry;
 
        journal_entry_err_msg(&_buf, version, jset, entry);             \
        prt_printf(&_buf, msg, ##__VA_ARGS__);                          \
                                                                        \
-       switch (flags & BCH_VALIDATE_write) {                           \
+       switch (from.flags & BCH_VALIDATE_write) {                      \
        case READ:                                                      \
                mustfix_fsck_err(c, _err, "%s", _buf.buf);              \
                break;                                                  \
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        struct bkey_i *k = entry->start;
-       struct bkey_validate_context from = {
-               .from   = BKEY_VALIDATE_journal,
-               .level  = entry->level,
-               .btree  = entry->btree_id,
-               .flags  = flags|BCH_VALIDATE_journal,
-       };
+
+       from.level      = entry->level;
+       from.btree      = entry->btree_id;
 
        while (k != vstruct_last(entry)) {
                int ret = journal_validate_key(c, jset, entry, k, from, version, big_endian);
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        struct bkey_i *k = entry->start;
        int ret = 0;
 
+       from.root       = true;
+       from.level      = entry->level + 1;
+       from.btree      = entry->btree_id;
+
        if (journal_entry_err_on(!entry->u64s ||
                                 le16_to_cpu(entry->u64s) != k->k.u64s,
                                 c, version, jset, entry,
                return 0;
        }
 
-       struct bkey_validate_context from = {
-               .from   = BKEY_VALIDATE_journal,
-               .level  = entry->level + 1,
-               .btree  = entry->btree_id,
-               .root   = true,
-               .flags  = flags,
-       };
        ret = journal_validate_key(c, jset, entry, k, from, version, big_endian);
        if (ret == FSCK_DELETED_KEY)
                ret = 0;
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        /* obsolete, don't care: */
        return 0;
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        int ret = 0;
 
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        struct jset_entry_blacklist_v2 *bl_entry;
        int ret = 0;
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        struct jset_entry_usage *u =
                container_of(entry, struct jset_entry_usage, entry);
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        struct jset_entry_data_usage *u =
                container_of(entry, struct jset_entry_data_usage, entry);
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        struct jset_entry_clock *clock =
                container_of(entry, struct jset_entry_clock, entry);
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        struct jset_entry_dev_usage *u =
                container_of(entry, struct jset_entry_dev_usage, entry);
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        return 0;
 }
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
+       from.flags = 0;
        return journal_entry_btree_keys_validate(c, jset, entry,
-                               version, big_endian, READ);
+                               version, big_endian, from);
 }
 
 static void journal_entry_overwrite_to_text(struct printbuf *out, struct bch_fs *c,
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        return journal_entry_btree_keys_validate(c, jset, entry,
-                               version, big_endian, READ);
+                               version, big_endian, from);
 }
 
 static void journal_entry_write_buffer_keys_to_text(struct printbuf *out, struct bch_fs *c,
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        unsigned bytes = vstruct_bytes(entry);
        unsigned expected = 16;
 struct jset_entry_ops {
        int (*validate)(struct bch_fs *, struct jset *,
                        struct jset_entry *, unsigned, int,
-                       enum bch_validate_flags);
+                       struct bkey_validate_context);
        void (*to_text)(struct printbuf *, struct bch_fs *, struct jset_entry *);
 };
 
                                struct jset *jset,
                                struct jset_entry *entry,
                                unsigned version, int big_endian,
-                               enum bch_validate_flags flags)
+                               struct bkey_validate_context from)
 {
        return entry->type < BCH_JSET_ENTRY_NR
                ? bch2_jset_entry_ops[entry->type].validate(c, jset, entry,
-                               version, big_endian, flags)
+                               version, big_endian, from)
                : 0;
 }
 
 static int jset_validate_entries(struct bch_fs *c, struct jset *jset,
                                 enum bch_validate_flags flags)
 {
+       struct bkey_validate_context from = {
+               .flags          = flags,
+               .from           = BKEY_VALIDATE_journal,
+               .journal_seq    = le64_to_cpu(jset->seq),
+       };
+
        unsigned version = le32_to_cpu(jset->version);
        int ret = 0;
 
        vstruct_for_each(jset, entry) {
+               from.journal_offset = (u64 *) entry - jset->_data;
+
                if (journal_entry_err_on(vstruct_next(entry) > vstruct_last(jset),
                                c, version, jset, entry,
                                journal_entry_past_jset_end,
                        break;
                }
 
-               ret = bch2_journal_entry_validate(c, jset, entry,
-                                       version, JSET_BIG_ENDIAN(jset), flags);
+               ret = bch2_journal_entry_validate(c, jset, entry, version,
+                                                 JSET_BIG_ENDIAN(jset), from);
                if (ret)
                        break;
        }
                         struct jset *jset, u64 sector,
                         enum bch_validate_flags flags)
 {
-       unsigned version;
+       struct bkey_validate_context from = {
+               .flags          = flags,
+               .from           = BKEY_VALIDATE_journal,
+               .journal_seq    = le64_to_cpu(jset->seq),
+       };
        int ret = 0;
 
        if (le64_to_cpu(jset->magic) != jset_magic(c))
                return JOURNAL_ENTRY_NONE;
 
-       version = le32_to_cpu(jset->version);
+       unsigned version = le32_to_cpu(jset->version);
        if (journal_entry_err_on(!bch2_version_compatible(version),
                        c, version, jset, NULL,
                        jset_unsupported_version,
                         unsigned bucket_sectors_left,
                         unsigned sectors_read)
 {
-       size_t bytes = vstruct_bytes(jset);
-       unsigned version;
-       enum bch_validate_flags flags = BCH_VALIDATE_journal;
+       struct bkey_validate_context from = {
+               .from           = BKEY_VALIDATE_journal,
+               .journal_seq    = le64_to_cpu(jset->seq),
+       };
        int ret = 0;
 
        if (le64_to_cpu(jset->magic) != jset_magic(c))
                return JOURNAL_ENTRY_NONE;
 
-       version = le32_to_cpu(jset->version);
+       unsigned version = le32_to_cpu(jset->version);
        if (journal_entry_err_on(!bch2_version_compatible(version),
                        c, version, jset, NULL,
                        jset_unsupported_version,
                return -EINVAL;
        }
 
+       size_t bytes = vstruct_bytes(jset);
        if (bytes > (sectors_read << 9) &&
            sectors_read < bucket_sectors_left)
                return JOURNAL_ENTRY_REREAD;
         * those entries will be blacklisted:
         */
        genradix_for_each_reverse(&c->journal_entries, radix_iter, _i) {
-               enum bch_validate_flags flags = BCH_VALIDATE_journal;
-
                i = *_i;
 
                if (journal_replay_ignore(i))
                        continue;
                }
 
+               struct bkey_validate_context from = {
+                       .from           = BKEY_VALIDATE_journal,
+                       .journal_seq    = le64_to_cpu(i->j.seq),
+               };
                if (journal_entry_err_on(le64_to_cpu(i->j.last_seq) > le64_to_cpu(i->j.seq),
                                         c, le32_to_cpu(i->j.version), &i->j, NULL,
                                         jset_last_seq_newer_than_seq,