Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include "bcachefs.h"
  4#include "bkey_buf.h"
  5#include "btree_update.h"
  6#include "error.h"
  7#include "io_misc.h"
  8#include "logged_ops.h"
  9#include "super.h"
 10
 11struct bch_logged_op_fn {
 12	u8		type;
 13	int		(*resume)(struct btree_trans *, struct bkey_i *);
 14};
 15
 16static const struct bch_logged_op_fn logged_op_fns[] = {
 17#define x(n)		{					\
 18	.type		= KEY_TYPE_logged_op_##n,		\
 19	.resume		= bch2_resume_logged_op_##n,		\
 20},
 21	BCH_LOGGED_OPS()
 22#undef x
 23};
 24
 25static const struct bch_logged_op_fn *logged_op_fn(enum bch_bkey_type type)
 26{
 27	for (unsigned i = 0; i < ARRAY_SIZE(logged_op_fns); i++)
 28		if (logged_op_fns[i].type == type)
 29			return logged_op_fns + i;
 30	return NULL;
 31}
 32
 33static int resume_logged_op(struct btree_trans *trans, struct btree_iter *iter,
 34			    struct bkey_s_c k)
 35{
 36	struct bch_fs *c = trans->c;
 37	const struct bch_logged_op_fn *fn = logged_op_fn(k.k->type);
 38	struct bkey_buf sk;
 39	u32 restart_count = trans->restart_count;
 40	int ret;
 41
 42	if (!fn)
 43		return 0;
 44
 45	bch2_bkey_buf_init(&sk);
 46	bch2_bkey_buf_reassemble(&sk, c, k);
 47
 48	ret =   drop_locks_do(trans, (bch2_fs_lazy_rw(c), 0)) ?:
 49		fn->resume(trans, sk.k) ?: trans_was_restarted(trans, restart_count);
 50
 51	bch2_bkey_buf_exit(&sk, c);
 52	return ret;
 53}
 54
 55int bch2_resume_logged_ops(struct bch_fs *c)
 56{
 57	int ret = bch2_trans_run(c,
 58		for_each_btree_key(trans, iter,
 59				   BTREE_ID_logged_ops, POS_MIN,
 60				   BTREE_ITER_PREFETCH, k,
 61			resume_logged_op(trans, &iter, k)));
 62	bch_err_fn(c, ret);
 63	return ret;
 64}
 65
 66static int __bch2_logged_op_start(struct btree_trans *trans, struct bkey_i *k)
 67{
 68	struct btree_iter iter;
 69	int ret;
 70
 71	ret = bch2_bkey_get_empty_slot(trans, &iter, BTREE_ID_logged_ops, POS_MAX);
 72	if (ret)
 73		return ret;
 74
 75	k->k.p = iter.pos;
 76
 77	ret = bch2_trans_update(trans, &iter, k, 0);
 78	bch2_trans_iter_exit(trans, &iter);
 79	return ret;
 80}
 81
 82int bch2_logged_op_start(struct btree_trans *trans, struct bkey_i *k)
 83{
 84	return commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
 85			 __bch2_logged_op_start(trans, k));
 86}
 87
 88void bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)
 89{
 90	int ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
 91			    bch2_btree_delete(trans, BTREE_ID_logged_ops, k->k.p, 0));
 92	/*
 93	 * This needs to be a fatal error because we've left an unfinished
 94	 * operation in the logged ops btree.
 95	 *
 96	 * We should only ever see an error here if the filesystem has already
 97	 * been shut down, but make sure of that here:
 98	 */
 99	if (ret) {
100		struct bch_fs *c = trans->c;
101		struct printbuf buf = PRINTBUF;
102
103		bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));
104		bch2_fs_fatal_error(c, "%s: error deleting logged operation %s: %s",
105				     __func__, buf.buf, bch2_err_str(ret));
106		printbuf_exit(&buf);
107	}
108}