brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · 60e0070 Raw
119 lines · c
1// SPDX-License-Identifier: GPL-2.02 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 x23};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	u32 restart_count = trans->restart_count;38	struct printbuf buf = PRINTBUF;39	int ret = 0;40 41	fsck_err_on(test_bit(BCH_FS_clean_recovery, &c->flags),42		    trans, logged_op_but_clean,43		    "filesystem marked as clean but have logged op\n%s",44		    (bch2_bkey_val_to_text(&buf, c, k),45		     buf.buf));46 47	struct bkey_buf sk;48	bch2_bkey_buf_init(&sk);49	bch2_bkey_buf_reassemble(&sk, c, k);50 51	const struct bch_logged_op_fn *fn = logged_op_fn(sk.k->k.type);52	if (fn)53		fn->resume(trans, sk.k);54 55	ret = bch2_logged_op_finish(trans, sk.k);56 57	bch2_bkey_buf_exit(&sk, c);58fsck_err:59	printbuf_exit(&buf);60	return ret ?: trans_was_restarted(trans, restart_count);61}62 63int bch2_resume_logged_ops(struct bch_fs *c)64{65	int ret = bch2_trans_run(c,66		for_each_btree_key(trans, iter,67				   BTREE_ID_logged_ops, POS_MIN,68				   BTREE_ITER_prefetch, k,69			resume_logged_op(trans, &iter, k)));70	bch_err_fn(c, ret);71	return ret;72}73 74static int __bch2_logged_op_start(struct btree_trans *trans, struct bkey_i *k)75{76	struct btree_iter iter;77	int ret;78 79	ret = bch2_bkey_get_empty_slot(trans, &iter, BTREE_ID_logged_ops, POS_MAX);80	if (ret)81		return ret;82 83	k->k.p = iter.pos;84 85	ret = bch2_trans_update(trans, &iter, k, 0);86	bch2_trans_iter_exit(trans, &iter);87	return ret;88}89 90int bch2_logged_op_start(struct btree_trans *trans, struct bkey_i *k)91{92	return commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,93			 __bch2_logged_op_start(trans, k));94}95 96int bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)97{98	int ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,99			    bch2_btree_delete(trans, BTREE_ID_logged_ops, k->k.p, 0));100	/*101	 * This needs to be a fatal error because we've left an unfinished102	 * operation in the logged ops btree.103	 *104	 * We should only ever see an error here if the filesystem has already105	 * been shut down, but make sure of that here:106	 */107	if (ret) {108		struct bch_fs *c = trans->c;109		struct printbuf buf = PRINTBUF;110 111		bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));112		bch2_fs_fatal_error(c, "deleting logged operation %s: %s",113				    buf.buf, bch2_err_str(ret));114		printbuf_exit(&buf);115	}116 117	return ret;118}119