int             (*trans_trigger)(struct btree_trans *, enum btree_id, unsigned,
                                         struct bkey_s_c, struct bkey_s, unsigned);
        int             (*atomic_trigger)(struct btree_trans *, enum btree_id, unsigned,
-                                         struct bkey_s_c, struct bkey_s_c, unsigned);
+                                         struct bkey_s_c, struct bkey_s, unsigned);
        void            (*compat)(enum btree_id id, unsigned version,
                                  unsigned big_endian, int write,
                                  struct bkey_s);
 
 static inline int bch2_mark_key(struct btree_trans *trans,
                enum btree_id btree, unsigned level,
-               struct bkey_s_c old, struct bkey_s_c new,
+               struct bkey_s_c old, struct bkey_s new,
                unsigned flags)
 {
        const struct bkey_ops *ops = bch2_bkey_type_ops(old.k->type ?: new.k->type);
 
 #define DROP_THIS_NODE         10
 #define DROP_PREV_NODE         11
 
+static struct bkey_s unsafe_bkey_s_c_to_s(struct bkey_s_c k)
+{
+       return (struct bkey_s) {{{
+               (struct bkey *) k.k,
+               (struct bch_val *) k.v
+       }}};
+}
+
 static bool should_restart_for_topology_repair(struct bch_fs *c)
 {
        return c->opts.fix_errors != FSCK_FIX_no &&
        }
 
        ret = commit_do(trans, NULL, NULL, 0,
-                       bch2_mark_key(trans, btree_id, level, old, *k, flags));
+                       bch2_mark_key(trans, btree_id, level, old, unsafe_bkey_s_c_to_s(*k), flags));
 fsck_err:
 err:
        bch_err_fn(c, ret);
 
 
        if (old_ops->atomic_trigger == new_ops->atomic_trigger) {
                ret   = bch2_mark_key(trans, i->btree_id, i->level,
-                               old, bkey_i_to_s_c(new),
+                               old, bkey_i_to_s(new),
                                BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|flags);
        } else {
                struct bkey             _deleted = POS_KEY((trans->paths + i->path)->pos);
-               struct bkey_s_c         deleted = (struct bkey_s_c) { &_deleted, NULL };
+               struct bkey_s           deleted = (struct bkey_s) { { { &_deleted, NULL } } };
 
                ret   = bch2_mark_key(trans, i->btree_id, i->level,
-                               deleted, bkey_i_to_s_c(new),
+                               deleted.s_c, bkey_i_to_s(new),
                                BTREE_TRIGGER_INSERT|flags) ?:
                        bch2_mark_key(trans, i->btree_id, i->level,
                                old, deleted,
 
 
 int bch2_mark_alloc(struct btree_trans *trans,
                    enum btree_id btree, unsigned level,
-                   struct bkey_s_c old, struct bkey_s_c new,
+                   struct bkey_s_c old, struct bkey_s new,
                    unsigned flags)
 {
        bool gc = flags & BTREE_TRIGGER_GC;
        ca = bch_dev_bkey_exists(c, new.k->p.inode);
 
        old_a = bch2_alloc_to_v4(old, &old_a_convert);
-       new_a = bch2_alloc_to_v4(new, &new_a_convert);
+       new_a = bch2_alloc_to_v4(new.s_c, &new_a_convert);
 
        bucket_journal_seq = new_a->journal_seq;
 
 
 int bch2_mark_extent(struct btree_trans *trans,
                     enum btree_id btree_id, unsigned level,
-                    struct bkey_s_c old, struct bkey_s_c new,
+                    struct bkey_s_c old, struct bkey_s new,
                     unsigned flags)
 {
        return mem_trigger_run_overwrite_then_insert(__mark_extent, trans, btree_id, level, old, new, flags);
 
 int bch2_mark_stripe(struct btree_trans *trans,
                     enum btree_id btree_id, unsigned level,
-                    struct bkey_s_c old, struct bkey_s_c new,
+                    struct bkey_s_c old, struct bkey_s _new,
                     unsigned flags)
 {
+       struct bkey_s_c new = _new.s_c;
        bool gc = flags & BTREE_TRIGGER_GC;
        u64 journal_seq = trans->journal_res.seq;
        struct bch_fs *c = trans->c;
 
 int bch2_mark_reservation(struct btree_trans *trans,
                          enum btree_id btree_id, unsigned level,
-                         struct bkey_s_c old, struct bkey_s_c new,
+                         struct bkey_s_c old, struct bkey_s new,
                          unsigned flags)
 {
        return mem_trigger_run_overwrite_then_insert(__mark_reservation, trans, btree_id, level, old, new, flags);
 
                              struct gc_pos, unsigned);
 
 int bch2_mark_alloc(struct btree_trans *, enum btree_id, unsigned,
-                   struct bkey_s_c, struct bkey_s_c, unsigned);
+                   struct bkey_s_c, struct bkey_s, unsigned);
 int bch2_mark_extent(struct btree_trans *, enum btree_id, unsigned,
-                    struct bkey_s_c, struct bkey_s_c, unsigned);
+                    struct bkey_s_c, struct bkey_s, unsigned);
 int bch2_mark_stripe(struct btree_trans *, enum btree_id, unsigned,
-                    struct bkey_s_c, struct bkey_s_c, unsigned);
+                    struct bkey_s_c, struct bkey_s, unsigned);
 int bch2_mark_reservation(struct btree_trans *, enum btree_id, unsigned,
-                         struct bkey_s_c, struct bkey_s_c, unsigned);
+                         struct bkey_s_c, struct bkey_s, unsigned);
 
 int bch2_trans_mark_extent(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_s, unsigned);
 int bch2_trans_mark_stripe(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_s, unsigned);
        if (_old.k->type)                                                                       \
                ret = _fn(_trans, _btree_id, _level, _old, _flags & ~BTREE_TRIGGER_INSERT);     \
        if (!ret && _new.k->type)                                                               \
-               ret = _fn(_trans, _btree_id, _level, _new, _flags & ~BTREE_TRIGGER_OVERWRITE);  \
+               ret = _fn(_trans, _btree_id, _level, _new.s_c, _flags & ~BTREE_TRIGGER_OVERWRITE);\
        ret;                                                                                    \
 })
 
 #define trigger_run_overwrite_then_insert(_fn, _trans, _btree_id, _level, _old, _new, _flags)  \
-       mem_trigger_run_overwrite_then_insert(_fn, _trans, _btree_id, _level, _old, _new.s_c, _flags)
+       mem_trigger_run_overwrite_then_insert(_fn, _trans, _btree_id, _level, _old, _new, _flags)
 
 void bch2_trans_fs_usage_revert(struct btree_trans *, struct replicas_delta_list *);
 int bch2_trans_fs_usage_apply(struct btree_trans *, struct replicas_delta_list *);
 
 
 int bch2_mark_inode(struct btree_trans *trans,
                    enum btree_id btree_id, unsigned level,
-                   struct bkey_s_c old, struct bkey_s_c new,
+                   struct bkey_s_c old, struct bkey_s new,
                    unsigned flags)
 {
        struct bch_fs *c = trans->c;
        u64 journal_seq = trans->journal_res.seq;
 
        if (flags & BTREE_TRIGGER_INSERT) {
-               struct bch_inode_v3 *v = (struct bch_inode_v3 *) new.v;
-
                BUG_ON(!journal_seq);
-               BUG_ON(new.k->type != KEY_TYPE_inode_v3);
 
-               v->bi_journal_seq = cpu_to_le64(journal_seq);
+               bkey_s_to_inode_v3(new).v->bi_journal_seq = cpu_to_le64(journal_seq);
        }
 
        if (flags & BTREE_TRIGGER_GC) {
 
 int bch2_trans_mark_inode(struct btree_trans *, enum btree_id, unsigned,
                          struct bkey_s_c, struct bkey_s, unsigned);
 int bch2_mark_inode(struct btree_trans *, enum btree_id, unsigned,
-                   struct bkey_s_c, struct bkey_s_c, unsigned);
+                   struct bkey_s_c, struct bkey_s, unsigned);
 
 #define bch2_bkey_ops_inode ((struct bkey_ops) {       \
        .key_invalid    = bch2_inode_invalid,           \
 
 
 int bch2_mark_reflink_p(struct btree_trans *trans,
                        enum btree_id btree_id, unsigned level,
-                       struct bkey_s_c old, struct bkey_s_c new,
+                       struct bkey_s_c old, struct bkey_s new,
                        unsigned flags)
 {
        return mem_trigger_run_overwrite_then_insert(__mark_reflink_p, trans, btree_id, level, old, new, flags);
 
 int bch2_trans_mark_reflink_p(struct btree_trans *, enum btree_id, unsigned,
                              struct bkey_s_c, struct bkey_s, unsigned);
 int bch2_mark_reflink_p(struct btree_trans *, enum btree_id, unsigned,
-                       struct bkey_s_c, struct bkey_s_c, unsigned);
+                       struct bkey_s_c, struct bkey_s, unsigned);
 
 #define bch2_bkey_ops_reflink_p ((struct bkey_ops) {           \
        .key_invalid    = bch2_reflink_p_invalid,               \
 
        mutex_unlock(&c->snapshot_table_lock);
 }
 
-int bch2_mark_snapshot(struct btree_trans *trans,
+static int __bch2_mark_snapshot(struct btree_trans *trans,
                       enum btree_id btree, unsigned level,
                       struct bkey_s_c old, struct bkey_s_c new,
                       unsigned flags)
        return ret;
 }
 
+int bch2_mark_snapshot(struct btree_trans *trans,
+                      enum btree_id btree, unsigned level,
+                      struct bkey_s_c old, struct bkey_s new,
+                      unsigned flags)
+{
+       return __bch2_mark_snapshot(trans, btree, level, old, new.s_c, flags);
+}
+
 int bch2_snapshot_lookup(struct btree_trans *trans, u32 id,
                         struct bch_snapshot *s)
 {
                bubble_sort(n->v.skip, ARRAY_SIZE(n->v.skip), cmp_le32);
                SET_BCH_SNAPSHOT_SUBVOL(&n->v, true);
 
-               ret = bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0,
+               ret = __bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0,
                                         bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0);
                if (ret)
                        goto err;
        int ret = bch2_trans_run(c,
                for_each_btree_key(trans, iter, BTREE_ID_snapshots,
                                   POS_MIN, 0, k,
-                       bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0, bkey_s_c_null, k, 0) ?:
+                       __bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0, bkey_s_c_null, k, 0) ?:
                        bch2_snapshot_set_equiv(trans, k) ?:
                        bch2_check_snapshot_needs_deletion(trans, k)) ?:
                for_each_btree_key(trans, iter, BTREE_ID_snapshots,
 
 int bch2_snapshot_invalid(struct bch_fs *, struct bkey_s_c,
                          enum bkey_invalid_flags, struct printbuf *);
 int bch2_mark_snapshot(struct btree_trans *, enum btree_id, unsigned,
-                      struct bkey_s_c, struct bkey_s_c, unsigned);
+                      struct bkey_s_c, struct bkey_s, unsigned);
 
 #define bch2_bkey_ops_snapshot ((struct bkey_ops) {            \
        .key_invalid    = bch2_snapshot_invalid,                \