]> Git Repo - J-linux.git/blob - fs/bcachefs/logged_ops.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / fs / bcachefs / logged_ops.c
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
11 struct bch_logged_op_fn {
12         u8              type;
13         int             (*resume)(struct btree_trans *, struct bkey_i *);
14 };
15
16 static 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
25 static 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
33 static 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);
58 fsck_err:
59         printbuf_exit(&buf);
60         return ret ?: trans_was_restarted(trans, restart_count);
61 }
62
63 int 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
74 static 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
90 int 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
96 int 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 unfinished
102          * operation in the logged ops btree.
103          *
104          * We should only ever see an error here if the filesystem has already
105          * 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 }
This page took 0.048583 seconds and 4 git commands to generate.