1 // SPDX-License-Identifier: GPL-2.0
5 #include "btree_update.h"
8 #include "logged_ops.h"
10 struct bch_logged_op_fn {
12 int (*resume)(struct btree_trans *, struct bkey_i *);
15 static const struct bch_logged_op_fn logged_op_fns[] = {
17 .type = KEY_TYPE_logged_op_##n, \
18 .resume = bch2_resume_logged_op_##n, \
24 static const struct bch_logged_op_fn *logged_op_fn(enum bch_bkey_type type)
26 for (unsigned i = 0; i < ARRAY_SIZE(logged_op_fns); i++)
27 if (logged_op_fns[i].type == type)
28 return logged_op_fns + i;
32 static int resume_logged_op(struct btree_trans *trans, struct btree_iter *iter,
35 struct bch_fs *c = trans->c;
36 const struct bch_logged_op_fn *fn = logged_op_fn(k.k->type);
38 u32 restart_count = trans->restart_count;
44 bch2_bkey_buf_init(&sk);
45 bch2_bkey_buf_reassemble(&sk, c, k);
47 ret = fn->resume(trans, sk.k) ?: trans_was_restarted(trans, restart_count);
49 bch2_bkey_buf_exit(&sk, c);
53 int bch2_resume_logged_ops(struct bch_fs *c)
55 struct btree_iter iter;
59 ret = bch2_trans_run(c,
60 for_each_btree_key2(trans, iter,
61 BTREE_ID_logged_ops, POS_MIN, BTREE_ITER_PREFETCH, k,
62 resume_logged_op(trans, &iter, k)));
68 static int __bch2_logged_op_start(struct btree_trans *trans, struct bkey_i *k)
70 struct btree_iter iter;
73 ret = bch2_bkey_get_empty_slot(trans, &iter, BTREE_ID_logged_ops, POS_MAX);
79 ret = bch2_trans_update(trans, &iter, k, 0);
80 bch2_trans_iter_exit(trans, &iter);
84 int bch2_logged_op_start(struct btree_trans *trans, struct bkey_i *k)
86 return commit_do(trans, NULL, NULL, BTREE_INSERT_NOFAIL,
87 __bch2_logged_op_start(trans, k));
90 void bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)
92 int ret = commit_do(trans, NULL, NULL, BTREE_INSERT_NOFAIL,
93 bch2_btree_delete(trans, BTREE_ID_logged_ops, k->k.p, 0));
95 * This needs to be a fatal error because we've left an unfinished
96 * operation in the logged ops btree.
98 * We should only ever see an error here if the filesystem has already
99 * been shut down, but make sure of that here:
102 struct bch_fs *c = trans->c;
103 struct printbuf buf = PRINTBUF;
105 bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));
106 bch2_fs_fatal_error(c, "%s: error deleting logged operation %s: %s",
107 __func__, buf.buf, bch2_err_str(ret));