diff options
Diffstat (limited to 'fs/bcachefs/snapshot.c')
-rw-r--r-- | fs/bcachefs/snapshot.c | 155 |
1 files changed, 71 insertions, 84 deletions
diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c index 7a801513b134..1b7b21494479 100644 --- a/fs/bcachefs/snapshot.c +++ b/fs/bcachefs/snapshot.c @@ -11,6 +11,7 @@ #include "errcode.h" #include "error.h" #include "fs.h" +#include "progress.h" #include "recovery_passes.h" #include "snapshot.h" @@ -73,7 +74,7 @@ __bch2_snapshot_tree_create(struct btree_trans *trans) s_t = bch2_bkey_alloc(trans, &iter, 0, snapshot_tree); ret = PTR_ERR_OR_ZERO(s_t); - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); return ret ? ERR_PTR(ret) : s_t; } @@ -142,7 +143,7 @@ bool __bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ancestor) guard(rcu)(); struct snapshot_table *t = rcu_dereference(c->snapshots); - if (unlikely(c->recovery.pass_done < BCH_RECOVERY_PASS_check_snapshots)) + if (unlikely(recovery_pass_will_run(c, BCH_RECOVERY_PASS_check_snapshots))) return __bch2_snapshot_is_ancestor_early(t, id, ancestor); if (likely(ancestor >= IS_ANCESTOR_BITMAP)) @@ -364,31 +365,32 @@ int bch2_snapshot_lookup(struct btree_trans *trans, u32 id, /* fsck: */ -static u32 bch2_snapshot_child(struct bch_fs *c, u32 id, unsigned child) +static u32 bch2_snapshot_child(struct snapshot_table *t, + u32 id, unsigned child) { - return snapshot_t(c, id)->children[child]; + return __snapshot_t(t, id)->children[child]; } -static u32 bch2_snapshot_left_child(struct bch_fs *c, u32 id) +static u32 bch2_snapshot_left_child(struct snapshot_table *t, u32 id) { - return bch2_snapshot_child(c, id, 0); + return bch2_snapshot_child(t, id, 0); } -static u32 bch2_snapshot_right_child(struct bch_fs *c, u32 id) +static u32 bch2_snapshot_right_child(struct snapshot_table *t, u32 id) { - return bch2_snapshot_child(c, id, 1); + return bch2_snapshot_child(t, id, 1); } -static u32 bch2_snapshot_tree_next(struct bch_fs *c, u32 id) +static u32 bch2_snapshot_tree_next(struct snapshot_table *t, u32 id) { u32 n, parent; - n = bch2_snapshot_left_child(c, id); + n = bch2_snapshot_left_child(t, id); if (n) return n; - while ((parent = bch2_snapshot_parent(c, id))) { - n = bch2_snapshot_right_child(c, parent); + while ((parent = __bch2_snapshot_parent(t, id))) { + n = bch2_snapshot_right_child(t, parent); if (n && n != id) return n; id = parent; @@ -401,17 +403,18 @@ u32 bch2_snapshot_oldest_subvol(struct bch_fs *c, u32 snapshot_root, snapshot_id_list *skip) { guard(rcu)(); + struct snapshot_table *t = rcu_dereference(c->snapshots); u32 id, subvol = 0, s; retry: id = snapshot_root; - while (id && bch2_snapshot_exists(c, id)) { + while (id && __bch2_snapshot_exists(t, id)) { if (!(skip && snapshot_list_has_id(skip, id))) { - s = snapshot_t(c, id)->subvol; + s = __snapshot_t(t, id)->subvol; if (s && (!subvol || s < subvol)) subvol = s; } - id = bch2_snapshot_tree_next(c, id); + id = bch2_snapshot_tree_next(t, id); if (id == snapshot_root) break; } @@ -447,7 +450,7 @@ static int bch2_snapshot_tree_master_subvol(struct btree_trans *trans, break; } } - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); if (!ret && !found) { struct bkey_i_subvolume *u; @@ -560,7 +563,7 @@ static int check_snapshot_tree(struct btree_trans *trans, out: err: fsck_err: - bch2_trans_iter_exit(trans, &snapshot_iter); + bch2_trans_iter_exit(&snapshot_iter); return ret; } @@ -682,7 +685,7 @@ static int snapshot_tree_ptr_repair(struct btree_trans *trans, *s = u->v; } err: - bch2_trans_iter_exit(trans, &root_iter); + bch2_trans_iter_exit(&root_iter); return ret; } @@ -865,7 +868,7 @@ static int check_snapshot_exists(struct btree_trans *trans, u32 id) break; } } - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); if (ret) return ret; @@ -895,7 +898,7 @@ static int check_snapshot_exists(struct btree_trans *trans, u32 id) break; } } - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); return bch2_snapshot_table_make_room(c, id) ?: bch2_btree_insert_trans(trans, BTREE_ID_snapshots, &snapshot->k_i, 0); @@ -973,12 +976,16 @@ int bch2_reconstruct_snapshots(struct bch_fs *c) struct snapshot_tree_reconstruct r = {}; int ret = 0; + struct progress_indicator_state progress; + bch2_progress_init(&progress, c, btree_has_snapshots_mask); + for (unsigned btree = 0; btree < BTREE_ID_NR; btree++) { if (btree_type_has_snapshots(btree)) { r.btree = btree; ret = for_each_btree_key(trans, iter, btree, POS_MIN, BTREE_ITER_all_snapshots|BTREE_ITER_prefetch, k, ({ + progress_update_iter(trans, &progress, &iter); get_snapshot_trees(c, &r, k.k->p); })); if (ret) @@ -1093,7 +1100,7 @@ int __bch2_get_snapshot_overwrites(struct btree_trans *trans, if (ret) break; } - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); if (ret) darray_exit(s); @@ -1125,7 +1132,7 @@ int bch2_snapshot_node_set_deleted(struct btree_trans *trans, u32 id) SET_BCH_SNAPSHOT_SUBVOL(&s->v, false); s->v.subvol = 0; err: - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); return ret; } @@ -1250,10 +1257,10 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id) set_bkey_val_u64s(&s->k, 0); } err: - bch2_trans_iter_exit(trans, &tree_iter); - bch2_trans_iter_exit(trans, &p_iter); - bch2_trans_iter_exit(trans, &c_iter); - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&tree_iter); + bch2_trans_iter_exit(&p_iter); + bch2_trans_iter_exit(&c_iter); + bch2_trans_iter_exit(&iter); return ret; } @@ -1263,35 +1270,30 @@ static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree, unsigned nr_snapids) { struct bch_fs *c = trans->c; - struct btree_iter iter; struct bkey_i_snapshot *n; - struct bkey_s_c k; - unsigned i, j; u32 depth = bch2_snapshot_depth(c, parent); - int ret; - bch2_trans_iter_init(trans, &iter, BTREE_ID_snapshots, - POS_MIN, BTREE_ITER_intent); - k = bch2_btree_iter_peek(trans, &iter); - ret = bkey_err(k); + CLASS(btree_iter, iter)(trans, BTREE_ID_snapshots, + POS_MIN, BTREE_ITER_intent); + struct bkey_s_c k = bch2_btree_iter_peek(&iter); + int ret = bkey_err(k); if (ret) - goto err; + return ret; - for (i = 0; i < nr_snapids; i++) { - k = bch2_btree_iter_prev_slot(trans, &iter); + for (unsigned i = 0; i < nr_snapids; i++) { + k = bch2_btree_iter_prev_slot(&iter); ret = bkey_err(k); if (ret) - goto err; + return ret; if (!k.k || !k.k->p.offset) { - ret = bch_err_throw(c, ENOSPC_snapshot_create); - goto err; + return bch_err_throw(c, ENOSPC_snapshot_create); } n = bch2_bkey_alloc(trans, &iter, 0, snapshot); ret = PTR_ERR_OR_ZERO(n); if (ret) - goto err; + return ret; n->v.flags = 0; n->v.parent = cpu_to_le32(parent); @@ -1301,7 +1303,7 @@ static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree, n->v.btime.lo = cpu_to_le64(bch2_current_time(c)); n->v.btime.hi = 0; - for (j = 0; j < ARRAY_SIZE(n->v.skip); j++) + for (unsigned j = 0; j < ARRAY_SIZE(n->v.skip); j++) n->v.skip[j] = cpu_to_le32(bch2_snapshot_skiplist_get(c, parent)); bubble_sort(n->v.skip, ARRAY_SIZE(n->v.skip), cmp_le32); @@ -1310,13 +1312,12 @@ static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree, ret = __bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0, bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0); if (ret) - goto err; + return ret; new_snapids[i] = iter.pos.offset; } -err: - bch2_trans_iter_exit(trans, &iter); - return ret; + + return 0; } /* @@ -1357,7 +1358,7 @@ static int bch2_snapshot_node_create_children(struct btree_trans *trans, u32 par n_parent->v.subvol = 0; SET_BCH_SNAPSHOT_SUBVOL(&n_parent->v, false); err: - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); return ret; } @@ -1424,38 +1425,22 @@ static inline u32 interior_delete_has_id(interior_delete_list *l, u32 id) return i ? i->live_child : 0; } -static unsigned __live_child(struct snapshot_table *t, u32 id, - snapshot_id_list *delete_leaves, - interior_delete_list *delete_interior) -{ - struct snapshot_t *s = __snapshot_t(t, id); - if (!s) - return 0; - - for (unsigned i = 0; i < ARRAY_SIZE(s->children); i++) - if (s->children[i] && - !snapshot_list_has_id(delete_leaves, s->children[i]) && - !interior_delete_has_id(delete_interior, s->children[i])) - return s->children[i]; - - for (unsigned i = 0; i < ARRAY_SIZE(s->children); i++) { - u32 live_child = s->children[i] - ? __live_child(t, s->children[i], delete_leaves, delete_interior) - : 0; - if (live_child) - return live_child; - } - - return 0; -} - -static unsigned live_child(struct bch_fs *c, u32 id) +static unsigned live_child(struct bch_fs *c, u32 start) { struct snapshot_delete *d = &c->snapshot_delete; guard(rcu)(); - return __live_child(rcu_dereference(c->snapshots), id, - &d->delete_leaves, &d->delete_interior); + struct snapshot_table *t = rcu_dereference(c->snapshots); + + for (u32 id = bch2_snapshot_tree_next(t, start); + id && id != start; + id = bch2_snapshot_tree_next(t, id)) + if (bch2_snapshot_is_leaf(c, id) && + !snapshot_list_has_id(&d->delete_leaves, id) && + !interior_delete_has_id(&d->delete_interior, id)) + return id; + + return 0; } static bool snapshot_id_dying(struct snapshot_delete *d, unsigned id) @@ -1498,7 +1483,7 @@ static int delete_dead_snapshots_process_key(struct btree_trans *trans, : 0) ?: bch2_btree_delete_at(trans, iter, BTREE_UPDATE_internal_snapshot_node); - bch2_trans_iter_exit(trans, &dst_iter); + bch2_trans_iter_exit(&dst_iter); return ret; } @@ -1526,7 +1511,7 @@ static bool skip_unrelated_snapshot_tree(struct btree_trans *trans, struct btree pos.snapshot = 0; if (iter->btree_id != BTREE_ID_inodes) pos.offset = U64_MAX; - bch2_btree_iter_set_pos(trans, iter, bpos_nosnap_successor(pos)); + bch2_btree_iter_set_pos(iter, bpos_nosnap_successor(pos)); } return ret; @@ -1604,7 +1589,7 @@ static int delete_dead_snapshot_keys_v2(struct btree_trans *trans) while (1) { struct bkey_s_c k; ret = lockrestart_do(trans, - bkey_err(k = bch2_btree_iter_peek(trans, &iter))); + bkey_err(k = bch2_btree_iter_peek(&iter))); if (ret) break; @@ -1627,12 +1612,12 @@ static int delete_dead_snapshot_keys_v2(struct btree_trans *trans) if (ret) break; - bch2_btree_iter_set_pos(trans, &iter, POS(0, k.k->p.offset + 1)); + bch2_btree_iter_set_pos(&iter, POS(0, k.k->p.offset + 1)); } else { - bch2_btree_iter_advance(trans, &iter); + bch2_btree_iter_advance(&iter); } } - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); if (ret) goto err; @@ -1712,12 +1697,14 @@ static inline u32 bch2_snapshot_nth_parent_skip(struct bch_fs *c, u32 id, u32 n, interior_delete_list *skip) { guard(rcu)(); + struct snapshot_table *t = rcu_dereference(c->snapshots); + while (interior_delete_has_id(skip, id)) - id = __bch2_snapshot_parent(c, id); + id = __bch2_snapshot_parent(t, id); while (n--) { do { - id = __bch2_snapshot_parent(c, id); + id = __bch2_snapshot_parent(t, id); } while (interior_delete_has_id(skip, id)); } @@ -1960,7 +1947,7 @@ int __bch2_key_has_snapshot_overwrites(struct btree_trans *trans, break; } } - bch2_trans_iter_exit(trans, &iter); + bch2_trans_iter_exit(&iter); return ret; } |