1 // SPDX-License-Identifier: GPL-2.0
4 #include "alloc_background.h"
5 #include "backpointers.h"
7 #include "btree_node_scan.h"
8 #include "disk_accounting.h"
14 #include "logged_ops.h"
15 #include "rebalance.h"
17 #include "recovery_passes.h"
19 #include "subvolume.h"
23 const char * const bch2_recovery_passes[] = {
24 #define x(_fn, ...) #_fn,
30 /* Fake recovery pass, so that scan_for_btree_nodes isn't 0: */
31 static int bch2_recovery_pass_empty(struct bch_fs *c)
36 static int bch2_set_may_go_rw(struct bch_fs *c)
38 struct journal_keys *keys = &c->journal_keys;
41 * After we go RW, the journal keys buffer can't be modified (except for
42 * setting journal_key->overwritten: it will be accessed by multiple
45 move_gap(keys, keys->nr);
47 set_bit(BCH_FS_may_go_rw, &c->flags);
49 if (keys->nr || !c->opts.read_only || c->opts.fsck || !c->sb.clean || c->opts.recovery_passes)
50 return bch2_fs_read_write_early(c);
54 struct recovery_pass_fn {
55 int (*fn)(struct bch_fs *);
59 static struct recovery_pass_fn recovery_pass_fns[] = {
60 #define x(_fn, _id, _when) { .fn = bch2_##_fn, .when = _when },
65 static const u8 passes_to_stable_map[] = {
66 #define x(n, id, ...) [BCH_RECOVERY_PASS_##n] = BCH_RECOVERY_PASS_STABLE_##n,
71 static enum bch_recovery_pass_stable bch2_recovery_pass_to_stable(enum bch_recovery_pass pass)
73 return passes_to_stable_map[pass];
76 u64 bch2_recovery_passes_to_stable(u64 v)
79 for (unsigned i = 0; i < ARRAY_SIZE(passes_to_stable_map); i++)
81 ret |= BIT_ULL(passes_to_stable_map[i]);
85 u64 bch2_recovery_passes_from_stable(u64 v)
87 static const u8 map[] = {
88 #define x(n, id, ...) [BCH_RECOVERY_PASS_STABLE_##n] = BCH_RECOVERY_PASS_##n,
94 for (unsigned i = 0; i < ARRAY_SIZE(map); i++)
96 ret |= BIT_ULL(map[i]);
101 * For when we need to rewind recovery passes and run a pass we skipped:
103 static int __bch2_run_explicit_recovery_pass(struct bch_fs *c,
104 enum bch_recovery_pass pass)
106 if (c->curr_recovery_pass == ARRAY_SIZE(recovery_pass_fns))
107 return -BCH_ERR_not_in_recovery;
109 if (c->recovery_passes_complete & BIT_ULL(pass))
112 bool print = !(c->opts.recovery_passes & BIT_ULL(pass));
114 if (pass < BCH_RECOVERY_PASS_set_may_go_rw &&
115 c->curr_recovery_pass >= BCH_RECOVERY_PASS_set_may_go_rw) {
117 bch_info(c, "need recovery pass %s (%u), but already rw",
118 bch2_recovery_passes[pass], pass);
119 return -BCH_ERR_cannot_rewind_recovery;
123 bch_info(c, "running explicit recovery pass %s (%u), currently at %s (%u)",
124 bch2_recovery_passes[pass], pass,
125 bch2_recovery_passes[c->curr_recovery_pass], c->curr_recovery_pass);
127 c->opts.recovery_passes |= BIT_ULL(pass);
129 if (c->curr_recovery_pass > pass) {
130 c->next_recovery_pass = pass;
131 c->recovery_passes_complete &= (1ULL << pass) >> 1;
132 return -BCH_ERR_restart_recovery;
138 int bch2_run_explicit_recovery_pass(struct bch_fs *c,
139 enum bch_recovery_pass pass)
142 spin_lock_irqsave(&c->recovery_pass_lock, flags);
143 int ret = __bch2_run_explicit_recovery_pass(c, pass);
144 spin_unlock_irqrestore(&c->recovery_pass_lock, flags);
148 int bch2_run_explicit_recovery_pass_persistent_locked(struct bch_fs *c,
149 enum bch_recovery_pass pass)
151 lockdep_assert_held(&c->sb_lock);
153 struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
154 __set_bit_le64(bch2_recovery_pass_to_stable(pass), ext->recovery_passes_required);
156 return bch2_run_explicit_recovery_pass(c, pass);
159 int bch2_run_explicit_recovery_pass_persistent(struct bch_fs *c,
160 enum bch_recovery_pass pass)
162 enum bch_recovery_pass_stable s = bch2_recovery_pass_to_stable(pass);
164 mutex_lock(&c->sb_lock);
165 struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
167 if (!test_bit_le64(s, ext->recovery_passes_required)) {
168 __set_bit_le64(s, ext->recovery_passes_required);
171 mutex_unlock(&c->sb_lock);
173 return bch2_run_explicit_recovery_pass(c, pass);
176 static void bch2_clear_recovery_pass_required(struct bch_fs *c,
177 enum bch_recovery_pass pass)
179 enum bch_recovery_pass_stable s = bch2_recovery_pass_to_stable(pass);
181 mutex_lock(&c->sb_lock);
182 struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
184 if (test_bit_le64(s, ext->recovery_passes_required)) {
185 __clear_bit_le64(s, ext->recovery_passes_required);
188 mutex_unlock(&c->sb_lock);
191 u64 bch2_fsck_recovery_passes(void)
195 for (unsigned i = 0; i < ARRAY_SIZE(recovery_pass_fns); i++)
196 if (recovery_pass_fns[i].when & PASS_FSCK)
201 static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
203 struct recovery_pass_fn *p = recovery_pass_fns + pass;
205 if (c->opts.recovery_passes_exclude & BIT_ULL(pass))
207 if (c->opts.recovery_passes & BIT_ULL(pass))
209 if ((p->when & PASS_FSCK) && c->opts.fsck)
211 if ((p->when & PASS_UNCLEAN) && !c->sb.clean)
213 if (p->when & PASS_ALWAYS)
218 static int bch2_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
220 struct recovery_pass_fn *p = recovery_pass_fns + pass;
223 if (!(p->when & PASS_SILENT))
224 bch2_print(c, KERN_INFO bch2_log_msg(c, "%s..."),
225 bch2_recovery_passes[pass]);
229 if (!(p->when & PASS_SILENT))
230 bch2_print(c, KERN_CONT " done\n");
235 int bch2_run_online_recovery_passes(struct bch_fs *c)
239 down_read(&c->state_lock);
241 for (unsigned i = 0; i < ARRAY_SIZE(recovery_pass_fns); i++) {
242 struct recovery_pass_fn *p = recovery_pass_fns + i;
244 if (!(p->when & PASS_ONLINE))
247 ret = bch2_run_recovery_pass(c, i);
248 if (bch2_err_matches(ret, BCH_ERR_restart_recovery)) {
249 i = c->curr_recovery_pass;
256 up_read(&c->state_lock);
261 int bch2_run_recovery_passes(struct bch_fs *c)
266 * We can't allow set_may_go_rw to be excluded; that would cause us to
267 * use the journal replay keys for updates where it's not expected.
269 c->opts.recovery_passes_exclude &= ~BCH_RECOVERY_PASS_set_may_go_rw;
271 while (c->curr_recovery_pass < ARRAY_SIZE(recovery_pass_fns) && !ret) {
272 c->next_recovery_pass = c->curr_recovery_pass + 1;
274 spin_lock_irq(&c->recovery_pass_lock);
275 unsigned pass = c->curr_recovery_pass;
277 if (c->opts.recovery_pass_last &&
278 c->curr_recovery_pass > c->opts.recovery_pass_last) {
279 spin_unlock_irq(&c->recovery_pass_lock);
283 if (!should_run_recovery_pass(c, pass)) {
284 c->curr_recovery_pass++;
285 c->recovery_pass_done = max(c->recovery_pass_done, pass);
286 spin_unlock_irq(&c->recovery_pass_lock);
289 spin_unlock_irq(&c->recovery_pass_lock);
291 ret = bch2_run_recovery_pass(c, pass) ?:
292 bch2_journal_flush(&c->journal);
294 if (!ret && !test_bit(BCH_FS_error, &c->flags))
295 bch2_clear_recovery_pass_required(c, pass);
297 spin_lock_irq(&c->recovery_pass_lock);
298 if (c->next_recovery_pass < c->curr_recovery_pass) {
300 * bch2_run_explicit_recovery_pass() was called: we
301 * can't always catch -BCH_ERR_restart_recovery because
302 * it may have been called from another thread (btree
303 * node read completion)
306 c->recovery_passes_complete &= ~(~0ULL << c->curr_recovery_pass);
308 c->recovery_passes_complete |= BIT_ULL(pass);
309 c->recovery_pass_done = max(c->recovery_pass_done, pass);
311 c->curr_recovery_pass = c->next_recovery_pass;
312 spin_unlock_irq(&c->recovery_pass_lock);